第一种原生写法拉起登录
class Register extends Api
{
protected $appid;
protected $secret;
protected $loginUrl;
protected $noNeedLogin = ['login', 'saveUserInfo'];
protected $noNeedRight = ['*'];
// 基本配置
public function _initialize()
{
parent::_initialize();
$this->appid = get_addon_config("epay")['wechat']['miniapp_id'];
$this->secret = get_addon_config("epay")['wechat']['miniapp_secret'];
$this->loginUrl = get_addon_config("epay")['wechat']['miniapp_url'];
}
# 根据code获取sessionKey和openId
public function login()
{
$code = $this->request->get('code');
if (!$code) {
$this->error('缺少必要参数code');
}
$url = sprintf($this->loginUrl, $this->appid, $this->secret, $code);
$result = json_decode(file_get_contents($url),true);
if (!$result) {
$this->error('获取sessionKey和openId时异常');
}
if (!empty($result['errcode']) && $result['errcode'] != 0) {
return ['code' => $result['errcode'], 'msg' => $result['errmsg']];
}
$this->success('获取信息成功', $result);
}
/* login() 输出结果
* {
"code":1,
"msg":"获取信息成功",
"time":"1619158127",
"data":{
"session_key":"u3mgBqx1GH8fNsx06Ja4FA==",
"openid":"ooOoU5a6Ulb0-bXZqjlWsZowwVRc"
}
}*/
# 获取用户基本信息
public function saveUserInfo()
{
$params = $this->request->post();
// 入参
extract($params);
$errCode = $this->decryptData($encryptedData, $iv, $data, $sessionKey, $this->appid);
if ($errCode == 0) {
$result = json_decode($data,true);
$user = User::get(['openid' => $openid]);
if (!empty($user)) {
if ($user->status != 'normal') {
$this->error(__('Account is locked'));
}
// 更新用户数据
$user->nickname = base64_decode(base64_encode($result['nickName']));
$user->avatar = $result['avatarUrl'];
$user->save();
// 直接登陆
$ret = $this->auth->direct($user->id);
} else {
// 拉起小程序登录
$ret = $this->auth->wxMiniProgramLogin($result,$openid);
}
if ($ret) {
$this->success('授权登录成功', $this->auth->getUserInfo());
} else {
$this->error('授权登录失败');
}
} else {
$this->error('授权登录失败了');
}
}
/*{
"code":1,
"msg":"授权登录成功",
"time":"1619593469",
"data":{
"id":1,
"nickname":"霍文霆",
"avatar":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTJoxeWibNOCabPKocbFBH1QjoFnFwUnIUF9D12xhpeHjVAEQWxmsnrsSWswoyW654zteF4AtHyeU4A\/132",
"mobile":"18186518743",
"score":0,
"token":"9030eb92-1efc-42e4-9000-531222d94a06",
"user_id":1,
"createtime":1619593469,
"expiretime":1622185469,
"expires_in":2592000
}
}*/
# 检验数据的真实性,并且获取解密后的明文.
# @param $encryptedData string 加密的用户数据
# @param $iv string 与用户数据一同返回的初始向量
# @param $data string 解密后的原文
# @return int 成功0,失败返回对应的错误码
public function decryptData($encryptedData, $iv, &$data, $sessionKey, $appid)
{
if (strlen($sessionKey) != 24) {
return -41001;
}
$aesKey = base64_decode($sessionKey);
if (strlen($iv) != 24) {
return -41002;
}
$aesIV = base64_decode($iv);
$aesCipher = base64_decode($encryptedData);
$result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
$dataObj = json_decode($result);
if ($dataObj == NULL) {
return -41003;
}
if ($dataObj->watermark->appid != $appid) {
return -41003;
}
$data = $result;
return 0;
}
}
第二种EasyWeChat拉起登录,如果有不会安装EasyWeChat的新手可以去看看我的公众号授权登录
use EasyWeChat\Factory;
class Register extends Api
{
protected $app;
protected $config;
protected $noNeedLogin = ['login', 'saveUserInfo'];
protected $noNeedRight = ['*'];
public function _initialize()
{
parent::_initialize();
// 这里的配置信息可以写入基本配置里面,这里只是为了练手
$this->config = [
'app_id' => 'wx53ce******3dcd53',
'secret' => 'c8c80544f7************0034acdab9',
// 下面为可选项
// 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
'response_type' => 'array',
'log' => [
'level' => 'debug',
'file' => ROOT_PATH . '/public/logs/wxMiniProgramLogin.log'
]
];
$this->app = Factory::miniProgram($this->config);
}
# 根据code获取sessionKey和openId
public function login()
{
$code = $this->request->get('code');
if (!$code) {
$this->error('缺少必要参数code');
}
$result = $this->app->auth->session($code);
/* $result 输出结果
* Array (
[session_key] => 0mZrSFu1K6vX7appQsrxOw==
[openid] => ooOoU5a6Ulb0-bXZqjlWsZowwVRc
)*/
if (!$result) {
$this->error('获取sessionKey和openId时异常');
}
if (!empty($result['errcode']) && $result['errcode'] != 0) {
return ['code' => $result['errcode'], 'msg' => $result['errmsg']];
}
$this->success('获取信息成功', $result);
}
/* login() 输出结果
* {
"code":1,
"msg":"获取信息成功",
"time":"1619163984",
"data":{
"session_key":"3uh+wLzDl47zHOEj4H4fSg==",
"openid":"ooOoU5a6Ulb0-bXZqjlWsZowwVRc"
}
}*/
# 获取用户基本信息
public function saveUserInfo()
{
$params = $this->request->post();
// 入参
extract($params);
if (empty($iv) || empty($openid) || empty($sessionKey) || empty($encryptedData)) {
$this->error('缺少必要参数!');
}
$result = $this->app->encryptor->decryptData($sessionKey, $iv, $encryptedData);
/* $result 输出结果
* Array (
[nickName] => 霍文霆
[gender] => 1
[language] => zh_CN
[city] =>
[province] => Anhui
[country] => China
[avatarUrl] => https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTIwdDXLgfezLpDudf6gu0yD2VBE7dHgiaGFWT2HwRcNuN9paUSlCvPWaQtOSOPHpLtRxKzK7DtJiaHQ/132
[watermark] => Array (
[timestamp] => 1619163984
[appid] => wx53ce5308043dcd53
)
)*/
$user = User::get(['openid' => $openid]);
if (!empty($user)) {
if ($user->status != 'normal') {
$this->error(__('Account is locked'));
}
// 更新用户数据
$user->nickname = base64_decode(base64_encode($result['nickName']));
$user->avatar = $result['avatarUrl'];
$user->save();
// 直接登陆
$ret = $this->auth->direct($user->id);
} else {
// 拉起小程序登录
$ret = $this->auth->wxMiniProgramLogin($result,$openid);
}
if ($ret) {
$this->success('授权登录成功', $this->auth->getUserInfo());
} else {
$this->error('授权登录失败');
}
}
/* saveUserInfo() 输出结果
* {
"code":1,
"msg":"授权登录成功",
"time":"1619164807",
"data":{
"openid":"ooOoU5a6Ulb0-bXZqjlWsZowwVRc",
"nickname":"霍文霆",
"avatar":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTIwdDXLgfezLpDudf6gu0yD2VBE7dHgiaGFWT2HwRcNuN9paUSlCvPWaQtOSOPHpLtRxKzK7DtJiaHQ\/132",
"token":"20abd047-ea42-4a32-88b8-68efecafaec6",
"user_id":1,
"createtime":1619164807,
"expiretime":1621756807,
"expires_in":2592000
}
}*/
}
在 app\common\library 方法中添加如下方法(这是基于fastadmin开发的,可以作为参考,数据写入方式个人有个人的风格,我认为我既然用了这个框架那就用它自带封装好的,代码越精简越好,能少写就少写,能不写就不写,最大的提高代码复用率,这样后续如果有二开就会舒服很多)
/**
* 微信小程序注册用户
*
* @param string $username 用户名
* @param string $password 密码
* @param string $email 邮箱
* @param string $mobile 手机号
* @param array $extend 扩展参数
* @return boolean
*/
public function wxMiniProgramLogin($result, $openid)
{
/* $result 打印结果
* Array (
[nickName] => 霍文霆
[gender] => 1
[language] => zh_CN
[city] =>
[province] => Anhui
[country] => China
[avatarUrl] => https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTIwdDXLgfezLpDudf6gu0yD2VBE7dHgiaGFWT2HwRcNuN9paUSlCvPWaQtOSOPHpLtRxKzK7DtJiaHQ/132
[watermark] => Array (
[timestamp] => 1618847873
[appid] => wx53ce5308043dcd53
)
)*/
$params = [
'openid' => $openid,
'nickname' => base64_decode(base64_encode($result['nickName'])),
'avatar' => $result['avatarUrl'],
'jointime' => time(),
'joinip' => request()->ip(),
'logintime' => time(),
'loginip' => request()->ip(),
'prevtime' => time(),
'status' => 'normal'
];
Db::startTrans();
try {
$user = User::create($params, true);
$this->_user = User::get($user->id);
//设置Token
$this->_token = Random::uuid();
Token::set($this->_token, $user->id, $this->keeptime);
Db::commit();
} catch (Exception $e) {
$this->setError($e->getMessage());
Db::rollback();
return false;
}
return true;
}