介紹
現在幾乎所有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 Hs'), '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 Hs'), '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 協議》,轉載必須註明作者和本文連結