admin

支付宝沙箱环境授权登录(原生PHP)
支付宝授权登录开发文档(https://docs.open.alipay.com/263/105809/)步骤1:...
扫描右侧二维码阅读全文
01
2019/01

支付宝沙箱环境授权登录(原生PHP)

支付宝授权登录开发文档(https://docs.open.alipay.com/263/105809/)

步骤1:
url的拼接规则是:

https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=商户的APPID&scope=auth_user&redirect_uri=ENCODED_URL&state=init
需要注意的是Redirect_uri为页面跳回地址,需要到后台配置的,并且该URL是经过URLENCODE转义 的url链接,并且必须以http或者https开头,这样的话,构造URL应该是这样的:

 public function alioAuthLogin()
 {
        if(!session('user_id')){
            $surl       = 'https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm?app_id=
            &scope=auth_user&redirect_uri='.urlencode('http://521bug.cn/portal/Alicallback/back');
            header('Location:'.$surl);
            exit;
        }
  }

这个方法我是写在一个基类控制器里面 如果其他的页面需要授权才能查看 则对应的控制器集成于这个基类即可

由回调地址可知,该方法会重定向到Alicallback控制器一个back方法里面 于是在back方法进行后续处理

步骤2:获取auth_code

当用户授权成功后,会跳转至开发者定义的回调页面,支付宝会在回调页面请求中加入参数,包括auth_code、app_id、scope等,需要注意的是支付宝仅保证auth_code、app_id以及scope参数的有效性。支付宝请求开发者回调页面示例如下:

http://example.com/doc/toAuthPage.html?app_id=2014101500013658&source=alipay_wallet&scope=auth_user&auth_code=ca34ea491e7146cc87d25fca24c4cD11
在该页面上获得auth_code

$auth_code         =       Request()->get('auth_code');

获得了auth_code之后,构造请求参数获取授权访问令牌access_token

3.通过auth_code获取access_token 参数文档可参考(https://docs.open.alipay.com/api_9/alipay.system.oauth.token)

由开发文档可知 需要构造的请求参数数组大概是

$app_id      =       config('alipay.APPID');
$get_access_token_arr = [
                        "app_id"        =>  $app_id,
                        "method"        =>  "alipay.system.oauth.token",
                        'format'        =>  "JSON",
                        "charset"       =>  "utf-8",
                        "sign_type"     =>  "RSA2",
                        "timestamp"     =>  date('Y-m-d H:i:s'),
                        "sign"          =>  "",
                        "version"       =>  "1.0",
                        "grant_type"    =>  "authorization_code",
                        "code"          =>  $get['auth_code'],
                    ];

很不好的是 从开发文档上面看得出 我先要生成一个签名

那么先生成签名吧,其实签名的步骤和支付的时候签名的步骤差不多的 详细参考(https://docs.open.alipay.com/291/105974)

如果想看详细的签名 点击(http://521bug.cn/article/index/id/12/cid/1.html)

//设置一个带签名的数组

function setSign($params)
{
    unset($params['sign']);
    ksort($params);
    $queryUrl = urldecode(http_build_query($params));
    $sign = createSign($queryUrl);
    $params['sign'] = $sign;
    return $params;
}
//生成签名
function createSign($data = '')
{
    if (!is_string($data)) {
        return null;
    }
      $res  = getPrivateKey();
      $sign = openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA256 ) ? base64_encode($sign) : null;
      return $sign;
}
//获取私钥
function getPrivateKey()
{
    $alipayConfigs = config('alipay');
    $privKey = $alipayConfigs['APPPRI_KEY'];
    $search = [
        "-----BEGIN RSA PRIVATE KEY-----",
        "-----END RSA PRIVATE KEY-----",
        "\n",
        "\r",
        "\r\n"
    ];

     $privKey       = str_replace($search,"",$privKey);
     $private_key   = $search[0] . PHP_EOL . wordwrap($privKey, 64, "\n", true) . PHP_EOL . $search[1];
     $res           = openssl_pkey_get_private($private_key);
     return $res;
}
有了签名之后,用请求参数数组构造出一个请求URL 于是有了

//$accesstoken_userinfo_gatewag是一个url
//即https://openapi.alipaydev.com/gateway.do?
$accesstoken_userinfo_gatewag = config('alipay.accesstoken_userinfo_gatewag');
$get_access_token_res  =  curlGet($accesstoken_userinfo_gatewag.http_build_query(setSign($get_access_token_arr)));


/*
curlGet
*/
function curlGet($url , $param = []){
    $p='';
    foreach($param as $key => $value){
    $p=$p.$key.'='.urlencode($value).'&';
}
if(preg_match('/\?[\d\D]+/',$url)){//matched ?c
        $p='&'.$p;
}else if(preg_match('/\?$/',$url)){//matched ?$
       $p=$p;
}else{
     $p='?'.$p;
}
     $p=preg_replace('/&$/','',$p);
     $url=$url.$p;
     $httph =curl_init($url);
     curl_setopt($httph, CURLOPT_SSL_VERIFYPEER, 0);
     curl_setopt($httph,CURLOPT_RETURNTRANSFER,1);
     curl_setopt($httph, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
     curl_setopt($httph, CURLOPT_RETURNTRANSFER,1);
     curl_setopt($httph, CURLOPT_HEADER,0);
     $rst=curl_exec($httph);
     curl_close($httph);
     return $rst;
}

如果以上的curl执行成功 , 它的返回结果应该有:

b1.png

步骤3 根据access_token获取用户信息 文档(https://docs.open.alipay.com/api_2/alipay.user.info.share)

从步骤2中拿到access_token

$get_access_token_res = json_decode($get_access_token_res,true);
通过文档可以得出 我们大概需要一个请求参数数组 它应该是这个样子的

$get_user_info_arr = [
                        "app_id"        =>  $app_id,
                        "method"        =>  "alipay.user.info.share",
                        'format'        =>  "JSON",
                        "charset"       =>  "utf-8",
                        "sign_type"     =>  "RSA2",
                        "timestamp"     =>  date('Y-m-d H:i:s'),
                        "sign"          =>  "",
                        "version"       =>  "1.0",
                        'auth_token'    =>  $get_access_token_res['alipay_system_oauth_token_response']['access_token'],
                ];

这里又需要一个签名 签名方法我用步骤2的

通过步骤2的方法得到一个签名之后,再通过含有签名的请求数组构造请求的URL,所以构造URL的方法应该是这样的:

$get_user_info_res       =  curlGet($accesstoken_userinfo_gatewag.http_build_query(setSign($get_user_info_arr)));

如果该curl执行成功,如果你用的不是沙箱环境而是正式环境,则返回的信息里面有

b2.png

用户信息获取成功之后,把信息根据需要存进数据库

$user_info               =  json_decode($get_user_info_res,true);
$user_id                 =  $user_info['alipay_user_info_share_response']['user_id'];
Session::set('user_id',$user_id);
/****简单处理 调试用户是否已授权成功并显示在前台 */
Db::name('userlogin')->where('user_id',$user_id)->delete();
Db::name('userlogin')->insert([
'user_id'=>$user_id,
'login_time'=>date('Y-m-d H:i:s')
]);
//获取授权成功之后 返回业务页面
header('Location:'.'https://www.521bug.cn/');
exit;

完整的代码如下:

//发起授权的方法

public function alioAuthLogin()
 {
        if(!session('user_id')){
            $surl       = 'https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm?app_id=2016092600599427
            &scope=auth_user&redirect_uri='.urlencode('http://521bug.cn/portal/Alicallback/back');
            header('Location:'.$surl);
            exit;
        }
  }


/****************************授权回调页逻辑***********************************/
    public function back()
    {
        // die('暂停获取授权');
        $accesstoken_userinfo_gatewag = config('alipay.accesstoken_userinfo_gatewag');
        $get         =       Request()->get();
        $app_id      =       config('alipay.APPID');
            if(!Session::get('access_token')){
                if(isset($get['auth_code'])){
                    //通过auth_code获取access_token
                    $get_access_token_arr = [
                        "app_id"        =>  $app_id,
                        "method"        =>  "alipay.system.oauth.token",
                        'format'        =>  "JSON",
                        "charset"       =>  "utf-8",
                        "sign_type"     =>  "RSA2",
                        "timestamp"     =>  date('Y-m-d H:i:s'),
                        "sign"          =>  "",
                        "version"       =>  "1.0",
                        "grant_type"    =>  "authorization_code",
                        "code"          =>  $get['auth_code'],
                    ];
                    //注意 该网关是沙箱地址测试网关
                    $get_access_token_res  =  curlGet($accesstoken_userinfo_gatewag.http_build_query(setSign($get_access_token_arr)));
                    $get_access_token_res  =  json_decode($get_access_token_res,true);
                    $get_user_info_arr = [
                        "app_id"        =>  $app_id,
                        "method"        =>  "alipay.user.info.share",
                        'format'        =>  "JSON",
                        "charset"       =>  "utf-8",
                        "sign_type"     =>  "RSA2",
                        "timestamp"     =>  date('Y-m-d H:i:s'),
                        "sign"          =>  "",
                        "version"       =>  "1.0",
                        'auth_token'    =>  $get_access_token_res['alipay_system_oauth_token_response']['access_token'],
                ];
                    //注意 该网关是沙箱地址测试网关
                    $get_user_info_res       =  curlGet($accesstoken_userinfo_gatewag.http_build_query(setSign($get_user_info_arr)));
                    $user_info               =  json_decode($get_user_info_res,true);
                    $user_id                 =  $user_info['alipay_user_info_share_response']['user_id'];
                    Session::set('user_id',$user_id);
                    /****简单处理 调试用户是否已授权成功并显示在前台 */
                    Db::name('userlogin')->where('user_id',$user_id)->delete();
                    Db::name('userlogin')->insert([
                        'user_id'=>$user_id,
                        'login_time'=>date('Y-m-d H:i:s')
                    ]);
                    //获取授权成功之后 返回业务页面
                    header('Location:'.'http://521bug.cn/');
                    exit;
                }
            }   
    }



/******************************使用到的相关方法**********************************/
/*
curlGet
*/
function curlGet($url , $param = []){
    $p='';
    foreach($param as $key => $value){
        $p=$p.$key.'='.urlencode($value).'&';
    }
    if(preg_match('/\?[\d\D]+/',$url)){//matched ?c
        $p='&'.$p;
    }else if(preg_match('/\?$/',$url)){//matched ?$
        $p=$p;
    }else{
        $p='?'.$p;
    }
    $p=preg_replace('/&$/','',$p);
    $url=$url.$p;
    $httph =curl_init($url);
    curl_setopt($httph, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($httph,CURLOPT_RETURNTRANSFER,1);
    curl_setopt($httph, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
    
    curl_setopt($httph, CURLOPT_RETURNTRANSFER,1);
    curl_setopt($httph, CURLOPT_HEADER,0);
    $rst=curl_exec($httph);
    curl_close($httph);
    return $rst;
}



//设置一个带签名的数组
function setSign($params)
{
    unset($params['sign']);
    ksort($params);
    $queryUrl = urldecode(http_build_query($params));
    $sign = createSign($queryUrl);
    $params['sign'] = $sign;
    return $params;
}


//生成签名
function createSign($data = '')
{
    if (!is_string($data)) {
        return null;
    }
      $res  = getPrivateKey();
      $sign = openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA256 ) ? base64_encode($sign) : null;
      return $sign;
}


//获取私钥
function getPrivateKey()
{
    $alipayConfigs = config('alipay');
    $privKey = $alipayConfigs['APPPRI_KEY'];
    $search = [
        "-----BEGIN RSA PRIVATE KEY-----",
        "-----END RSA PRIVATE KEY-----",
        "\n",
        "\r",
        "\r\n"
    ];

     $privKey       = str_replace($search,"",$privKey);
     $private_key   = $search[0] . PHP_EOL . wordwrap($privKey, 64, "\n", true) . PHP_EOL . $search[1];
     $res           = openssl_pkey_get_private($private_key);
     return $res;
}
最后修改:2019 年 05 月 10 日 02 : 38 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论