细说第三方登录—>PHP实现支付宝、QQ、微博、百度账号、Github登录

本文,基于 Laravel 框架的内嵌语法,进行编码,原生实现也是一样,只是接收参数,读配置文件,语法变了。
在讲解支付宝、QQ、微博、Github、百度账号等平台的第三方登录之前,我们有必要先了解一下,第三方登录所使用的协议。具体的详细内容请看我的这篇博客:
https://blog.csdn.net/weixin_43885417/article/details/91163338
开始入正题,既然知道了授权协议,下一步,肯定开始申请开发者身份,获取请求接口的权限。
先来一个简单的热热身:
一 、Github
详细步骤:

  1. 首先进入 Github 官网登录
    https://github.com
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    等你注册好之后,你就可以上上一个图片显示你的应用,点进去
    在这里插入图片描述
    然后开始进入开发环节:
    在看我的代码之前,可以看看官方文档的接口和参数要求:
    https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/
  2. 首先我们需要在前端页面中添加一个登录连接,类似这样:
    https://github.com/login/oauth/authorize?client_id=你自己 APPID&redirect_uri =你的回调地址&scope =user&state=你自己的识别字段值(github 那边会再次返回给你,让你判断是不是你想要的请求)。
    github 会回调你的接口地址,类似这样。
    https://blogback.zhangtengfei-steven.cn/gitHub?code=425e65d6c1e18c821683&state=上面提到的标识
    你需要用 PHP 自带的$_GET[‘code’],获取 code,用它去获取 access_token。
  3. 请求https://github.com/login/oauth/access_token,获取access_token。需要传 client_id, client_secret, code。
    github那边会以 URL 参数格式返回给你结果,类似这样:
    access_token=d14bec07c422b4d03b11b9954f383a292ee3dd0e&scope=user&token_type=bearer
  4. 拿到 access_token之后,就可以获取用户信息了。
    请求https://api.github.com/user
    注意!注意!注意!:
    这里有一个坑,请求获取用户接口的时候,需要带上 header 头信息,否则会报一个错误,
    $headers[] = 'Authorization: token '. (拼接上获取的 access_token);

    下面我上菜了:
<?php
namespace App\Http\Controllers\CommonControllers;

use App\Http\Controllers\Controller;//laravel 框架封装好的Controller
use Illuminate\Http\Request;      //laravel 框架封装好的 Request
class GitHubLogin extends Controller
{
    public function gitHubCallBack(Request $request)
    {
        if ($request->has('code')) {
            $github_login_cg = config('github');//登录的配置文件加载
            $param = array(
                'code'          => $request->code,
                'client_id'     => $github_login_cg['client_id'],
                'client_secret' => $github_login_cg['client_secret'],
            );
            $url = $github_login_cg['access_token_url'];
            $content = getHttpResponsePOST($url, $param);         //获取access_token
            $data = array();
            //$content====>'A=XXXXX&B=XXXX', github以路由参数返回结果
            parse_str($content,$data);//解析返回的值,赋给变量$data
            //请求用户信息
            if (!empty($data['access_token'])) {
                $info_url  = $github_login_cg['get_user_url'] . $data['access_token'];
                $token     = $data['access_token'];
                $headers[] = 'Authorization: token '. $token;
                $headers[] = "User-Agent: 坏小哥博客";
                $result    = getHttpResponseGET($info_url, $headers);
                $user_info = json_decode($result, true);          
                //接下来就是你自己的业务逻辑
                ..............
            }
        }
    }
}

上面提到的 github.php配置 文件

<?php

return [
    'client_id'        => '你自己的client_id',
    'client_secret'    => '你自己的client_secrect',
    'state'            => 'xxxxx',                                      //标识字段,防csrf 攻击,github 那边会原模原样返回给你,返回state 不正确,我们不处理
    'access_token_url' => 'https://github.com/login/oauth/access_token',//获取toke地址
    'get_user_url'     => 'https://api.github.com/user?',               //获取用户信息地址
];

下面是获取到的信息
在这里插入图片描述
二、支付宝:
详细步骤:
进入官网,先注册账号,然后申请开发者,进行认证。
https://open.alipay.com/platform/home.htm
然后创建一个应用
在这里插入图片描述
进入你的应用之后,你会看到能力列表,添加能力,获取接口权限
在这里插入图片描述
我们实现第三方登录只需有获取会员信息和第三方应用授权这俩接口就行。
在这里插入图片描述
点击应用信息
在这里插入图片描述
在这里插入图片描述
上面有APPID,还有上面圈住的都要进行配置,我们调用支付宝的接口,需要传我们的私钥,然后支付宝那边会回调我们配置的回调接口。
接下来就是开发流程:
支付宝获取用户信息的开发文档:https://opendocs.alipay.com/open/284/web

  1. 首先,我们需要前台点击支付宝登录按钮,请求支付宝授权
    URL:https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=APPID&scope=SCOPE&redirect_uri=你的回调地址,地址要和支付宝平台配置一致
    之后,支付宝会跳转到你配置的回调地址,类似这样:
    http://example.com/doc/toAuthPage.html?app_id=2014101500013658&source=alipay_wallet&scope=auth_user&auth_code=ca34ea491e7146cc87d25fca24c4cD11
    你可以通过PHP全局变量$_GET[‘auth_code’],获取auth_code。
  2. 拿auth_code换access_token
    auth_code、app_id(你的应用ID)、scope (接口权限值,目前只支持 auth_user 和 auth_base 两个值)
    获取access_token,接口地址:https://opendocs.alipay.com/apis/api_9/alipay.system.oauth.token
    在获取access_token的接口中,你要传一个sign(签名)参数,这个参数的值,需要我们自己拼接处理。
    下载生成私钥和公钥工具的地址:
    https://opendocs.alipay.com/open/291/105971
    文档写的很详细,在这里不再叙述,应该在配置应用的时候,已经下过,也进行配置了。把我们的公钥复制到应用信息接口加签方式里,目的是,支付宝会根据你的公钥进行解密你传的加密数据(利用的是非对称加密原理)
    在这里插入图片描述
    具体的sign(签名生成,代码中会解释说明)。
    根据文档说明,进行传参,POST请求,不出意外,我们可以得到以json形式返回的access_token信息。
  3. 获取用户信息,传access_token,POST方式请求用户信息接口。
    注意,用户信息数据是以gbk的编码格式返回给你数据,需要你用php的mb_convert_encoding编码转换函数,转换一下。才能解析,否则中文会乱码的。
    至此,流程讲解完毕。
    开始上菜:
<?php


namespace App\Http\Controllers\CommonControllers;


use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class AliPayLogin extends Controller
{
    public function aliPayLoginCallBack(Request $request)
    {
        if (!$request->has('auth_code')) {
            echo '获取app_auth_code失败,请重试';
            exit;
        }
        //获取app_auth_token
        $ali_pay_login_cg = config('alipay')['login'];
        $base_param = array(
            'app_id'     => $ali_pay_login_cg['app_id'],
            'grant_type' => $ali_pay_login_cg['grant_type'],
            'charset'    => $ali_pay_login_cg['charset'],
            'sign_type'  => $ali_pay_login_cg['sign_type'],
            'version'    => $ali_pay_login_cg['version'],
        );
        $get_token_param = array_merge($base_param, array(
            'method'     => $ali_pay_login_cg['get_token_api'],
            'code'       => $request->auth_code,
            'timestamp'  => date('Y-m-d H:i:s')
        ));
        $signStr = aliPayParamToString($get_token_param);        //参数拼接
        $rsa = enRSA2($signStr);                                 //对拼接好的请求参数数据进行RSA加密
        $sign = urlencode($rsa);                                 //生成url格式的请求参数
        $query = $signStr . '&sign=' . $sign;                    //请求参数
        $url = $ali_pay_login_cg['base_url'] . $query;
        $access_token = getHttpResponsePOST($ali_pay_login_cg['base_url'], $query);
        $access_token_info = json_decode($access_token, true);
        if (!isset($access_token_info['alipay_system_oauth_token_response'])) {
            echo '获取token信息失败';
            exit;
        }
        $access_token = $access_token_info['alipay_system_oauth_token_response']['access_token'];
        //请求用户信息
        $get_info_param = array_merge($base_param, array(
                'method'     => $ali_pay_login_cg['user_info_api'],
                'timestamp'  => date('Y-m-d H:i:s'),
                'auth_token' => $access_token,
        ));
        $signStr = aliPayParamToString($get_info_param);//拼接参数
        $rsaStr = enRSA2($signStr);                     //RSA加密
        $sign = urlencode($rsaStr);                     //生成url格式的请求参数
        $query = $signStr . '&sign=' . $sign;请求参数
        $user_info = getHttpResponsePOST($ali_pay_login_cg['base_url'], $query);
        $user_info = mb_convert_encoding($user_info, 'utf-8', 'gbk');//把返回结果,从gbk格式转为utf-8格式
        $user_info = json_decode($user_info, true);                  //解析json
        //接下来,写自己的业务逻辑
        .........................
    }
}

aliPay.php(请求配置文件)

<?php

return [
    'login' => [
        'app_id'        => 'yourselfID',                           //应用ID
        'format'        => 'json',                                 //要求支付宝返回的数据格式  
        'charset'       => 'utf-8',                                //我们的请求参数的编码格式
        'sign_type'     => 'RSA2',                                 //签名加密方式
        'version'       => '1.0',                                  //调用接口的版本
        'scope'         => 'auth_user',                            //获取的信息类型
        'grant_type'    => 'authorization_code',                   //获取code需要传,固定格式
        'base_url'      => 'https://openapi.alipay.com/gateway.do',//请求支付宝的基础接口地址
        'get_token_api' => 'alipay.system.oauth.token',            //请求access_token的接口名
        'user_info_api' => 'alipay.user.info.share'                //请求用户信息的接口名
    ]
];

上面提到的aliPayParamToString参数拼接方法

function aliPayParamToString($dataArr)
{
    ksort($dataArr);   //按键进行降序排序,这个必须要做
    $signStr = '';
    foreach ($dataArr as $key => $val) {
        if (empty($signStr)) {
            $signStr = $key.'='.$val;
        } else {
            $signStr .= '&'.$key.'='.$val;
        }
    }
    return $signStr;
}

上面提到的enRSA2参数拼接方法

function enRSA2($data)
{
    $path = public_path() . '/key/private_key.txt';    //私钥地址
    $private_key = file_get_contents($path);           //读取私钥内容
    $str = chunk_split(trim($private_key), 64, "\n");  //去除空格,并且每64个字符,加一个换行符。
    $key = "-----BEGIN RSA PRIVATE KEY-----\n$str-----END RSA PRIVATE KEY-----\n";
    $signature = '';
    $signature = openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA256) ? base64_encode($signature) : NULL;//数据加密
    return $signature;
}

上面提到的请求接口的公共方法:
getHttpResponseGET()

/**
 * @param $url
 * @param null $header
 * @return bool|string
 */
function getHttpResponseGET($url,$header = null) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    if(!empty($header)){
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($curl);
    curl_close($curl);
    unset($curl);
    return $output;
}

getHttpResponsePOST()

/**
 * 远程获取数据,POST模式
 * @param string $url
 * @param array $param
 * @return bool|string
 */
function getHttpResponsePOST($url = '', $param = array()) {
    if (empty($url)) {
        return false;
    }
    $ch = curl_init();                               //初始化curl
    curl_setopt($ch, CURLOPT_URL,$url);              //抓取指定网页
    curl_setopt($ch, CURLOPT_HEADER, false);         //是否返回响应头信息
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  //要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_POST, true);            //post提交方式
    if (!empty($param)) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  //是否将结果返回
    $data = curl_exec($ch);                          //运行curl
    if (curl_errno($ch)) {
        echo 'Errno'. json_encode(curl_error($ch));  //捕抓异常
    }
    curl_close($ch);
    return $data;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章