Lumen/Laravel 中支付宝 / 微信第三方 App 登陆
介绍
现在几乎所有APP都集成了微信/支付宝登录,简化用户操作.这里介绍下在lumen/laravel中如何进行微信/支付宝APP登陆。
配置文件
config.woann.php 这里是我自己创建的配置文件,可以自行调整
<?php
// +----------------------------------------------------------------------
// | Created by PhpStorm
// +----------------------------------------------------------------------
// | Date: 2019-03-29
// +----------------------------------------------------------------------
// | Blog: ( http://www.woann.cn )
// +----------------------------------------------------------------------
// | Author: woann <www.woann.cn>
// +----------------------------------------------------------------------
return [
//微信
'wechat' => [
'app' => [
'appid' => env('WECHAT_APPID', ''),
'secret' => env('WECHAT_APP_SECRET', '')
]
],
//支付宝
'alipay' => [
'app_id' => env('ALI_APP_ID'),
'pid' => env('ALI_PID'),
'private_key' => env('ALI_PRIVATE_KEY')
]
];
支付宝登录基类
app/utility/AliPayLogin.php 这个文件随便你放哪里,能调用到即可
<?php
// +----------------------------------------------------------------------
// | Created by PhpStorm
// +----------------------------------------------------------------------
// | Date: 2019-05-24
// +----------------------------------------------------------------------
// | Blog: ( http://www.woann.cn )
// +----------------------------------------------------------------------
// | Author: woann <www.woann.cn>
// +----------------------------------------------------------------------
namespace App\Utility;
use GuzzleHttp\Client;
class AliPayLogin
{
protected $app_id;
protected $pid;
protected $private_key;
public function __construct()
{
$config = config('woann.alipay');
$this->app_id = $config['app_id'];
$this->pid = $config['pid'];
$this->private_key = $config['private_key'];
}
/**
* InfoStr APP登录需要的的infostr
*
* @return String
*/
public function infoStr()
{
$infoStr = http_build_query([
'apiname' => 'com.alipay.account.auth',
'method' => 'alipay.open.auth.sdk.code.get',
'app_id' => $this->app_id,
'app_name' => 'mc',
'biz_type' => 'openservice',
'pid' => $this->pid,
'product_id' => 'APP_FAST_LOGIN',
'scope' => 'kuaijie',
'target_id' => getOrderNo(), //商户标识该次用户授权请求的ID,该值在商户端应保持唯一
'auth_type' => 'AUTHACCOUNT', // AUTHACCOUNT代表授权;LOGIN代表登录
'sign_type' => 'RSA2',
]);
$infoStr .= '&sign='.$this->enRSA2($infoStr);
return $infoStr;
}
/**
* AlipayToken 获得用户 请求token, 通过它获得 用户信息
*
* 需要按照支付宝加签流程来。
*/
public function userInfo($app_auth_token)
{
$infoArr = [
'method' => 'alipay.system.oauth.token',
'app_id' => $this->app_id,
'charset' => 'utf-8',
'sign_type' => 'RSA2',
'timestamp' => date('Y-m-d H:i:s'),
'version' => '1.0',
'code' => $app_auth_token,
'grant_type' => 'authorization_code',
];
$signStr = $this->myHttpBuildQuery($infoArr);
$sign = urlencode($this->enRSA2($signStr));
$qureStr = $signStr.'&sign='.$sign;
$res = new Client();
$body = $res->get('https://openapi.alipay.com/gateway.do?'.$qureStr)->getBody()->getContents();
$body = json_decode($body);
if (!isset($body->alipay_system_oauth_token_response->access_token)) {
return false;
} else {
$autho_token = $body->alipay_system_oauth_token_response->access_token;
$userinfo = $this->aliPayUserInfo($autho_token);
return $userinfo; // 或则 返回 json_encode($userinfo) 根据实际需求来
}
}
/**
* AliPayUserInfo 通过 token 获取用户信息
*/
private function aliPayUserInfo($autho_token)
{
$infoArr = [
'method' => 'alipay.user.info.share',
'app_id' => $this->app_id,
'charset' => 'utf-8',
'sign_type' => 'RSA2',
'timestamp' => date('Y-m-d H:i:s'),
'version' => '1.0',
'auth_token' => $autho_token,
];
$signStr = $this->myHttpBuildQuery($infoArr);
$sign = urlencode($this->enRSA2($signStr));
$qureStr = $signStr.'&sign='.$sign;
$res = new Client();
$body = $res->get('https://openapi.alipay.com/gateway.do?'.$qureStr)->getBody()->getContents();
$body = json_decode($body);
if (!isset($body->alipay_user_info_share_response)) {
return '接口异常';
}
$body = $body->alipay_user_info_share_response;
return $body;
}
/**
* enRSA2 RSA加密
*
* @param String $data
* @return String
*/
private function enRSA2($data)
{
$str = chunk_split(trim($this->private_key), 64, "\n");
$key = "-----BEGIN RSA PRIVATE KEY-----\n$str-----END RSA PRIVATE KEY-----\n";
// $key = file_get_contents(storage_path('rsa_private_key.pem')); 为文件时这样引入
$signature = '';
$signature = openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA256)?base64_encode($signature):NULL;
return $signature;
}
/**
* myHttpBuildQuery 返回一个 http Get 传参数组
* 之所以不用 自带函数 http_build_query 时间带 ‘:’ 会被转换
*
* @param Array
* @return String
*/
private function myHttpBuildQuery($dataArr)
{
ksort($dataArr);
$signStr = '';
foreach ($dataArr as $key => $val) {
if (empty($signStr)) {
$signStr = $key.'='.$val;
} else {
$signStr .= '&'.$key.'='.$val;
}
}
return $signStr;
}
}
支付宝给客户端提供的两个接口
1.获取code字符串(客户端通过这个字符串获取code)
public function aliLoginInfoStr()
{
$ali = new AliPayLogin();//实例化支付
$res = $ali->infoStr();
return returnApi(200,'SUCCESS',['str' => $res]);
}
/*
数据示例
{
"code":200,
"msg":"SUCCESS",
"data":{ "str":"apiname=com.alipay.account.auth&method=alipay.open.auth.sdk.code.get&app_id=2021001100636235&app_name=mc&biz_type=openservice&pid=2088631756058087&product_id=APP_FAST_LOGIN&scope=kuaijie&target_id=44039&auth_type=AUTHACCOUNT&sign_type=RSA2&sign=EXMs+NtovsZEKxcwjprKYwIJIbdeESLYxI/cjyqQ1Re8st0ejTktkX06V+gnyTiwfi9KtdSXbM1HMuC8hGyCEeMZb0IDSyOmOXp+f2dDJDXdlzoqyVowOxn7enTejXnngmu2WDuKQo2KcWfRVBKFlnYyA42QOUYw0PEKiXsgJYdjNPyVqKH9oTJJWIASJgZOgXbY4LSDh8gP+P/5QsuM41fTggeeRLJYHNlvbFuigSF+KpdcPiXXi6huI+4NQpN/7PLzXbVHzdeipkHeYTV6tMZY4njv5RvE4UH9ESd3urpoCgRJxriR/mUdGdQZCDHIBKMXTHmagRXH8mx70SFdpA=="
}
}
*/
2.通过code获取用户信息进行登录
public function loginByAli(Request $request)
{
$code = $request->post('code');
$ali = new AliPayLogin();//实例化支付宝登录基类
$res = $ali->userInfo($code);//获取用户信息
//....根据业务自行处理
}
微信登录
1.微信通过code获取用户信息(供微信登录接口调用)
private function getUserInfoByWx($code)
{
$app = config('woann.wechat.app');//获取app_id,secret
$auth_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$app['appid']."&secret=".$app['secret']."&code=".$code."&grant_type=authorization_code";
$auth_res = httpRequest($auth_url);
if(isset($auth_res['errcode'])){
return ['code' => $auth_res['errcode'], 'msg' => $auth_res['errmsg']];
}
$info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$auth_res['access_token']."&openid=".$auth_res['openid']."&lang=zh_CN";
$userinfo = httpRequest($info_url);
if(isset($userinfo['errcode'])){
return ['code' => $userinfo['errcode'], 'msg' => $userinfo['errmsg']];
}
return ['code' => 200, 'msg' => $userinfo];
}
2.登陆接口
public function loginByWechat(Request $reques)
{
$code = $request->post('code');
$userInfo = $this->getUserInfoByWx($code);
if ($userInfo['code'] != 200) {
return returnApi($userInfo['code'], $userInfo['msg']);
}
//以下根据自己业务进行调整
DB::beginTransaction();
//根据openid查询用户是否存在
$user = $this->where('wechat_openid', $userInfo['msg']['openid'])->first();
if (!$user) {
$user = new User();
$user->avatar = $userInfo['msg']['headimgurl'];
$user->nickname = $userInfo['msg']['nickname'];
$user->sex = $userInfo['msg']['sex'];
$user->wechat_openid = $userInfo['msg']['openid'];
}
$res = $user->save();
if($res){
if (!$token = Auth::login($user)) {
DB::rollBack();
return returnApi(500, '未知错误');
} else {
DB::commit();
return returnApi(200, '登录成功', [
'access_token' => 'Bearer '.$token
]);
}
}else{
DB::rollBack();
return returnApi(500,'未知错误');
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接