215 lines
6.9 KiB
PHP
215 lines
6.9 KiB
PHP
<?php
|
||
|
||
/**
|
||
* @author Any
|
||
* @description KISS
|
||
* @date 2020-12-3
|
||
* @version 1.0.0
|
||
*
|
||
* _____LOG_____
|
||
*
|
||
*/
|
||
|
||
namespace app\modules\api\models;
|
||
|
||
|
||
use app\models\User;
|
||
use app\components\auth\AToken;
|
||
use app\components\wechat\aes\WxBizDataCrypt;
|
||
use app\models\UserOauth;
|
||
use app\models\common\CommonUserEditForm;
|
||
use app\components\SysConst;
|
||
use app\components\FlashStorage;
|
||
|
||
class LoginByWxoaForm extends ApiModel
|
||
{
|
||
public $code;
|
||
|
||
|
||
public $code_expires;//code是否过期,0=否,1=是
|
||
|
||
public $cx_mch_id;
|
||
public $token_type;
|
||
public $wechat_mp;
|
||
|
||
|
||
public function rules()
|
||
{
|
||
return [
|
||
[['code'], 'trim'],
|
||
[['code'], 'string'],
|
||
[['code_expires'], 'integer'],
|
||
[['code', 'token_type', 'wechat_mp'], 'required'],
|
||
];
|
||
}
|
||
|
||
public function login()
|
||
{
|
||
if (!$this->validate()) {
|
||
return $this->getModelError();
|
||
}
|
||
$res = FlashStorage::getCache("m{$this->cx_mch_id}_c{$this->code}");
|
||
if ($this->code_expires == 1 || $res === false) {
|
||
$res = $this->code2session($this->code);
|
||
if ($res['code'] != 0)
|
||
return $res;
|
||
FlashStorage::setCache("m{$this->cx_mch_id}_c{$this->code}", $res, 864000);
|
||
}
|
||
|
||
|
||
$session_key = $res['data']['session_key'];
|
||
$openid = $res['data']['openid'];
|
||
$unionid = isset($res['data']['unionid']) ? $res['data']['unionid'] : null;
|
||
$res = $this->decrypted_data($session_key);
|
||
if ($res['code'] != 0) {
|
||
return $res;
|
||
}
|
||
$decrypted_info = json_decode($res['data'], true);
|
||
$openid = $openid ? $openid : $decrypted_info['openId'];
|
||
$nickname = $decrypted_info['nickName'];
|
||
$avatar_url = empty($decrypted_info['avatarUrl']) ? User::DEFAULT_AVATAR_URL : $decrypted_info['avatarUrl'];
|
||
$gender = $decrypted_info['gender'];
|
||
if ($unionid == null) {
|
||
$unionid = isset($decrypted_info['unionId']) ? $decrypted_info['unionId'] : '0';
|
||
}
|
||
|
||
//用户是否存在
|
||
$user_oauth = null;
|
||
if ($unionid != 0) {
|
||
//优选使用unionid
|
||
$user_oauth = UserOauth::findOne([
|
||
'cx_mch_id' => $this->cx_mch_id,
|
||
'is_delete' => 0,
|
||
'unionid' => $unionid
|
||
]);
|
||
}
|
||
if ($user_oauth == null) {
|
||
$user_oauth = UserOauth::findOne([
|
||
'cx_mch_id' => $this->cx_mch_id,
|
||
'is_delete' => 0,
|
||
'type' => SysConst::$cxOauthProviderWxmp,
|
||
'openid' => $openid
|
||
]);
|
||
}
|
||
|
||
$t = \Yii::$app->db->beginTransaction();
|
||
if ($user_oauth != null) {
|
||
//用户是否存在
|
||
$user = User::findOne([
|
||
'id' => $user_oauth->user_id,
|
||
'is_delete' => 0,
|
||
'cx_mch_id' => $this->cx_mch_id,
|
||
'status' => User::STATUS_NORMAL
|
||
]);
|
||
if ($user == null) {
|
||
\Yii::error("[LoginByWxmpForm] 用户(ID:{$user_oauth->user_id})不存在");
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '系统内部异常,请联系管理员'
|
||
];
|
||
}
|
||
} else {
|
||
$form = new CommonUserEditForm();
|
||
$form->scenario = 'wxmp_signup';
|
||
$form->model = new User();
|
||
$form->cx_mch_id = $this->cx_mch_id;
|
||
$form->username = User::generateUsername(3, "wx", 6);
|
||
$form->nickname = $nickname;
|
||
$form->avatar_url = $avatar_url;
|
||
$form->access_token = \Yii::$app->security->generateRandomString();
|
||
$form->gender = $gender;
|
||
$form->is_modify_un = 1;
|
||
$res = $form->save();
|
||
if ($res['code'] != 0)
|
||
return $res;
|
||
|
||
$user = $form->model;
|
||
|
||
$user_oauth = new UserOauth();
|
||
$user_oauth->cx_mch_id = $this->cx_mch_id;
|
||
$user_oauth->type = SysConst::$cxOauthProviderWxmp;
|
||
$user_oauth->user_id = $user->id;
|
||
$user_oauth->openid = $openid;
|
||
$user_oauth->unionid = $unionid;
|
||
$user_oauth->is_delete = 0;
|
||
$user_oauth->created_at = time();
|
||
}
|
||
//更新用户信息
|
||
$user_oauth->nickname = $nickname;
|
||
$user_oauth->avatar_url = $avatar_url;
|
||
if ($unionid !== 0 && $user_oauth->unionid == 0) {
|
||
$user_oauth->unionid = $unionid;
|
||
}
|
||
if (!$user_oauth->save()) {
|
||
$t->rollBack();
|
||
return $this->getModelError($user_oauth);
|
||
}
|
||
if (!\Yii::$app->user->login($user)) {
|
||
$t->commit();
|
||
return [
|
||
'code' => 1,
|
||
'msg' => '登录失败'
|
||
];
|
||
}
|
||
$args = [];
|
||
$args['cx_mch_id'] = $this->cx_mch_id;
|
||
$args['token_type'] = $this->token_type;
|
||
$atoken = new AToken($args);
|
||
$data = $atoken->generate_access_token();
|
||
if ($data['code'] == 0) {
|
||
$err_msg = "微信小程序登录成功";
|
||
User::lastLogin($user->id, 1, $err_msg, $this->cx_mch_id);
|
||
}
|
||
$t->commit();
|
||
//是否需要绑定
|
||
$data = User::bindQuery($user_oauth->user, $data);
|
||
return $data;
|
||
}
|
||
|
||
|
||
/***
|
||
* 用户数据解密
|
||
*/
|
||
private function decrypted_data($session_key)
|
||
{
|
||
$pc = new WxBizDataCrypt($this->wechat_mp->appId, $session_key);
|
||
$errCode = $pc->decryptData($this->encrypted_data, $this->iv, $data);
|
||
if ($errCode == 0) {
|
||
return [
|
||
'code' => 0,
|
||
'msg' => 'success',
|
||
'data' => $data
|
||
];
|
||
} else {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => $errCode,
|
||
];
|
||
}
|
||
}
|
||
|
||
private function code2session($code)
|
||
{
|
||
$api = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->wechat_mp->appId}&secret={$this->wechat_mp->appSecret}&code=" . $code . "&grant_type=authorization_code";
|
||
$this->wechat_mp->curl->get($api);
|
||
if ($this->wechat_mp->curl->error_code != 0) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => "err_code:{$this->wechat_mp->curl->error_code}err_msg:{$this->wechat_mp->curl->error_msg}"
|
||
];
|
||
}
|
||
$resp = $this->wechat_mp->curl->response;
|
||
$res = json_decode($resp, true);
|
||
if (!isset($res['access_token']) || !isset($res['openid'])) {
|
||
return [
|
||
'code' => 1,
|
||
'msg' => isset($res['errmsg']) ? $res['errmsg'] : 'error'
|
||
];
|
||
}
|
||
return [
|
||
'code' => 0,
|
||
'msg' => 'ok',
|
||
'data' => $res
|
||
];
|
||
}
|
||
} |