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 ]; } }