| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- <?php
- /**
- * Created by PhpStorm.
- * Author: 芸众商城 www.yunzshop.com
- * Date: 17/2/22
- * Time: 下午4:44
- */
- namespace app\frontend\modules\member\services;
- use app\common\exceptions\MemberErrorMsgException;
- use app\common\facades\EasyWeChat;
- use app\common\facades\Setting;
- use app\common\helpers\Cache;
- use app\common\helpers\Client;
- use app\common\helpers\Url;
- use app\common\models\AccountWechats;
- use app\common\models\Member;
- use app\common\services\Session;
- use app\frontend\modules\member\models\McMappingFansModel;
- use app\frontend\modules\member\models\MemberUniqueModel;
- use app\frontend\modules\member\models\SubMemberModel;
- use Illuminate\Contracts\Encryption\DecryptException;
- class MemberOfficeAccountService extends MemberService
- {
- const LOGIN_TYPE = '1';
- public function __construct()
- {
- }
- public function login()
- {
- $member_id = 0;
- $uniacid = \YunShop::app()->uniacid;
- $scope = \YunShop::request()->scope ?: 'userinfo'; //scope: base|home|userinfo
- $code = \YunShop::request()->code;
- if (Setting::get('shop.member')['wechat_login_mode'] == '1') {
- return $this->isPhoneLogin($uniacid);
- }
- $callback = ($_SERVER['REQUEST_SCHEME'] ? $_SERVER['REQUEST_SCHEME'] : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
- $wechat_scope = $this->wechatScope();
- $config = [
- 'oauth' => [
- 'scopes' => [$wechat_scope],
- 'callback' => $callback,
- ]
- ];
- $app = EasyWeChat::officialAccount($config);
- $oauth = $app->oauth;
- if (!empty($code)) {
- $oauthUser = $oauth->user();
- $userinfo = $oauthUser->getOriginal();
- $userinfo['access_token'] = $oauthUser->getAccessToken();
- $userinfo['expires_in'] = 7200;
- $userinfo['refresh_token'] = $oauthUser->getRefreshToken();
- \Log::debug('-----EasyWeChat-----', [$userinfo['openid']]);
- $user = $app->user->get($userinfo['openid']);
- $userinfo = array_merge($user, $userinfo);
- //Login
- $member_id = $this->memberLogin($userinfo);
- if($member_id) event(new \app\common\events\member\MemberLoginEvent($member_id));
- Session::set('member_id', $member_id);
- setcookie('Yz-Token', encrypt($userinfo['access_token'] . '\t' . ($userinfo['expires_in'] + time()) . '\t' . $userinfo['openid'] . '\t' . $scope), time() + self::TOKEN_EXPIRE);
- } else {
- $this->_setClientRequestUrl();
- $oauth->redirect()->send();
- exit;
- }
- redirect($this->_getClientRequestUrl())->send();
- exit;
- }
- /**
- * 获取用户信息
- *
- * @param $appId
- * @param $appSecret
- * @param $token
- * @return mixed
- */
- public function getUserInfo($appId, $appSecret, $token)
- {
- $scope = \YunShop::request()->scope ?: '';
- $subscribe = 0;
- $share = Setting::get('shop.share');
- $user_info = [];
- if (is_null($share) || $share['follow'] == 1 || ($share && is_null($share['follow']))) {
- $global_access_token_url = $this->_getAccessToken($appId, $appSecret);
- $global_token = \Curl::to($global_access_token_url)
- ->asJsonResponse(true)
- ->get();
- $global_userinfo_url = $this->_getInfo($global_token['access_token'], $token['openid']);
- $user_info = \Curl::to($global_userinfo_url)
- ->asJsonResponse(true)
- ->get();
- $subscribe = $user_info['subscribe'];
- }
- if (0 == $subscribe && $scope != 'base') { //未关注拉取不到用户信息
- $userinfo_url = $this->_getUserInfoUrl($token['access_token'], $token['openid']);
- $user_info = \Curl::to($userinfo_url)
- ->asJsonResponse(true)
- ->get();
- $user_info['subscribe'] = $subscribe;
- }
- return array_merge($user_info, $token);
- }
- /**
- * 用户验证授权 api
- *
- * snsapi_userinfo
- *
- * @param $appId
- * @param $url
- * @param $state
- * @return string
- */
- private function _getAuthUrl($appId, $url, $state)
- {
- return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appId . "&redirect_uri=" . urlencode($url) . "&response_type=code&scope=snsapi_userinfo&state={$state}#wechat_redirect";
- }
- /**
- *
- * 静默获取用户信息
- *
- * snsapi_base
- *
- * @param $appId
- * @param $url
- * @param $state
- * @return string
- */
- private function _getAuthBaseUrl($appId, $url, $state)
- {
- return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $appId . "&redirect_uri=" . urlencode($url) . "&response_type=code&scope=snsapi_base&state={$state}#wechat_redirect";
- }
- /**
- * 获取token api
- *
- * @param $appId
- * @param $appSecret
- * @param $code
- * @return string
- */
- private function _getTokenUrl($appId, $appSecret, $code)
- {
- return "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $appId . "&secret=" . $appSecret . "&code=" . $code . "&grant_type=authorization_code";
- }
- /**
- * 获取用户信息 api
- *
- * 无需关注
- *
- * @param $accesstoken
- * @param $openid
- * @return string
- */
- private function _getUserInfoUrl($accesstoken, $openid)
- {
- return "https://api.weixin.qq.com/sns/userinfo?access_token={$accesstoken}&openid={$openid}&lang=zh_CN";
- }
- /**
- * 获取全局ACCESS TOKEN
- * @return string
- */
- private function _getAccessToken($appId, $appSecret)
- {
- return 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appId . '&secret=' . $appSecret;
- }
- /**
- * 获取用户信息
- *
- * 需要关注
- *
- * @param $accesstoken
- * @param $openid
- * @return string
- */
- private function _getInfo($accesstoken, $openid)
- {
- return 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . $accesstoken . '&openid=' . $openid;
- }
- /**
- * 验证account_token
- *
- * @param $accesstoken
- * @param $openid
- *
- * @return string
- */
- private function _tokenAuth($accesstoken, $openid)
- {
- return 'https://api.weixin.qq.com/sns/auth?access_token=' . $accesstoken . '&openid=' . $openid;
- }
- private function _refreshAuth($appid, $refreshtoken)
- {
- return 'https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=' . $appid . '&grant_type=refresh_token&refresh_token=' . $refreshtoken;
- }
- /**
- * 设置客户端请求地址
- *
- * @return string
- */
- private function _setClientRequestUrl()
- {
- $pattern = '/(&t=([\d]+[^&]*))/';
- $t = time();
- if (\YunShop::request()->yz_redirect) {
- $yz_redirect = base64_decode(\YunShop::request()->yz_redirect);
- if (preg_match($pattern, $yz_redirect)) {
- $redirect_url = preg_replace($pattern, "&t={$t}", $yz_redirect);
- } else {
- $redirect_url = $yz_redirect . '&t=' . time();
- }
- Session::set('client_url', $redirect_url);
- } else {
- Session::set('client_url', '');
- }
- }
- private function _setClientRequestUrl_v2()
- {
- $redirect_url = '';
- $pattern = '/(&t=([\d]+[^&]*))/';
- $t = time();
- if (\YunShop::request()->yz_redirect) {
- $yz_redirect = base64_decode(\YunShop::request()->yz_redirect);
- if (preg_match($pattern, $yz_redirect)) {
- $redirect_url = preg_replace($pattern, "&t={$t}", $yz_redirect);
- } else {
- $redirect_url = $yz_redirect . '&t=' . time();
- }
- }
- return urlencode($redirect_url);
- }
- /**
- * 获取客户端地址
- *
- * @return mixed
- */
- private function _getClientRequestUrl()
- {
- $url = Session::get('client_url') ?: $this->_getFrontJumpUrl();
- if ($url === false || $url == '') {
- $url = Url::absoluteApp('home') . '&t=' . time();
- }
- return $url;
- }
- private function _getFrontJumpUrl()
- {
- $redirect_url = '';
- $pattern = '/(&t=([\d]+[^&]*))/';
- $t = time();
- if (\YunShop::request()->yz_redirect) {
- $yz_redirect = base64_decode(\YunShop::request()->yz_redirect);
- if (preg_match($pattern, $yz_redirect)) {
- $redirect_url = preg_replace($pattern, "&t={$t}", $yz_redirect);
- } else {
- $redirect_url = $yz_redirect . '&t=' . time();
- }
- }
- \Log::debug('-----------------front_url----------------', [$redirect_url]);
- return $redirect_url;
- }
- /**
- * 公众号开放平台授权登陆
- *
- * @param $uniacid
- * @param $userinfo
- * @return array|int|mixed
- */
- public function unionidLogin($uniacid, $userinfo, $upperMemberId = null)
- {
- $member_id = parent::unionidLogin($uniacid, $userinfo, $upperMemberId, self::LOGIN_TYPE);
- return $member_id;
- }
- public function updateMemberInfo($member_id, $userinfo)
- {
- parent::updateMemberInfo($member_id, $userinfo);
- \Log::debug('----update_mapping_fans----', $member_id);
- $record = array(
- 'nickname' => stripslashes($userinfo['nickname']),
- 'follow' => $userinfo['subscribe'] ?: 0,
- 'tag' => base64_encode(serialize($userinfo))
- );
- McMappingFansModel::updateData($member_id, $record);
- }
- public function addMemberInfo($uniacid, $userinfo)
- {
- $uid = parent::addMemberInfo($uniacid, $userinfo);
- \Log::debug('----mapping_fans----', $uid);
- //添加mapping_fans表
- $this->addFansMember($uid, $uniacid, $userinfo);
- return $uid;
- }
- public function addFansMember($uid, $uniacid, $userinfo)
- {
- McMappingFansModel::insertData($userinfo, array(
- 'uid' => $uid,
- 'acid' => $uniacid,
- 'uniacid' => $uniacid,
- 'salt' => Client::random(8),
- ));
- }
- public function getFansModel($openid)
- {
- return McMappingFansModel::getFansData($openid);
- }
- /**
- * 会员关联表操作
- *
- * @param $uniacid
- * @param $member_id
- * @param $unionid
- */
- public function addMemberUnionid($uniacid, $member_id, $unionid)
- {
- MemberUniqueModel::replace(array(
- 'uniacid' => $uniacid,
- 'unionid' => $unionid,
- 'member_id' => $member_id,
- 'type' => self::LOGIN_TYPE
- ));
- }
- public function updateFansMember($fan, $member_id, $userinfo)
- {
- $record = array(
- 'uid' => $member_id,
- 'nickname' => stripslashes($userinfo['nickname']),
- 'follow' => isset($userinfo['subscribe']) ? $userinfo['subscribe'] : 0,
- 'tag' => base64_encode(serialize($userinfo))
- );
- McMappingFansModel::updateDataById($fan->fanid, $record);
- }
- protected function updateSubMemberInfoV2($uid, $userinfo)
- {
- SubMemberModel::updateOpenid(
- $uid, [
- 'yz_openid' => $userinfo['openid'],
- 'access_token_1' => $userinfo['access_token'],
- 'access_expires_in_1' => time() + $userinfo['expires_in'],
- 'refresh_token_1' => $userinfo['refresh_token'],
- 'refresh_expires_in_1' => time() + (28 * 24 * 3600)
- ]
- );
- }
- public function checkMemberInfo($mcMember, $fansMember, $yzMember)
- {
- if ($mcMember->uid != $yzMember->member_id) {
- $mcMember->uid = $yzMember->member_id;
- $mcMember->save();
- }
- if ($fansMember->uid != $yzMember->member_id) {
- $fansMember->uid = $yzMember->member_id;
- $fansMember->save();
- }
- }
- /**
- * 添加会员主表信息
- *
- * @param $uniacid
- * @param $userinfo
- * @return mixed
- */
- public function addMcMemberInfo($uniacid, $userinfo)
- {
- $uid = parent::addMemberInfo($uniacid, $userinfo);
- return $uid;
- }
- /**
- * 判断是否为手机登录
- * @param $uniacid
- * @return array
- */
- public function isPhoneLogin($uniacid)
- {
- $mid = Member::getMid();
- $type = \YunShop::request()->type;
- $mobile = \YunShop::request()->mobile;
- $password = \YunShop::request()->password;
- $yz_redirect = \YunShop::request()->yz_redirect;
- if ($mobile && $password) {
- $res = (new MemberMobileService)->login();
- if ($res['status'] == 1) {
- $redirect_url = $this->_getClientRequestUrl();
- $res['json']['redirect_url'] = $redirect_url;
- }
- return $res;
- } else {
- $this->_setClientRequestUrl();
- $redirect_url = Url::absoluteApp('login', ['i' => $uniacid, 'type' => $type, 'mid' => $mid, 'yz_redirect' => $yz_redirect]);
- redirect($redirect_url)->send();
- }
- }
- public function chekAccount()
- {
- $uniacid = \YunShop::app()->uniacid;
- $code = \YunShop::request()->code;
- $account = AccountWechats::getAccountByUniacid($uniacid);
- $appId = $account->key;
- $appSecret = $account->secret;
- $state = 'yz-' . session_id();
- $callback = ($_SERVER['REQUEST_SCHEME'] ? $_SERVER['REQUEST_SCHEME'] : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
- $authurl = $this->_getAuthBaseUrl($appId, $callback, $state);
- $tokenurl = $this->_getTokenUrl($appId, $appSecret, $code);
- if (!empty($code)) {
- $redirect_url = $this->_getClientRequestUrl();
- $token = \Curl::to($tokenurl)
- ->asJsonResponse(true)
- ->get();
- if (!empty($token) && !empty($token['errmsg']) && $token['errmsg'] == 'invalid code') {
- return show_json(5, 'token请求错误');
- }
- $userinfo = $this->getUserInfo($appId, $appSecret, $token);
- if (is_array($userinfo) && !empty($userinfo['errcode'])) {
- \Log::debug('微信登陆授权失败-' . $userinfo['errcode']);
- return show_json(-3, '微信登陆授权失败');
- }
- $fans_info = McMappingFansModel::getFansById(\YunShop::app()->getMemberId());
- if ($fans_info->openid != $userinfo['openid']) {
- \Log::debug('----openid error----', [$fans_info->uid, $userinfo['openid']]);
- session_destroy();
- Cache::forget($fans_info->uid . ':chekAccount');
- redirect($redirect_url)->send();
- }
- } else {
- $this->_setClientRequestUrl();
- redirect($authurl)->send();
- exit;
- }
- redirect($redirect_url)->send();
- exit;
- }
- public function checkLogged($login = null)
- {
- $from = \YunShop::request()->scope;
- if (Setting::get('shop.member')['wechat_login_mode'] == '1') {
- return (new MemberMobileService)->checkLogged();
- }
- if (isset($_COOKIE['Yz-Token'])) {
- try {
- $yz_token = decrypt($_COOKIE['Yz-Token']);
- list($token, $expires, $openid, $scope) = explode('\t', $yz_token);
- } catch (DecryptException $e) {
- setcookie('Yz-Token', '', time() - self::TOKEN_EXPIRE);
- return false;
- }
- if ($scope === 'base' && $from != $scope) {
- $login->jump = true;
- setcookie('Yz-Token', '', time() - self::TOKEN_EXPIRE);
- return false;
- }
- if (empty($openid)) {
- setcookie('Yz-Token', '', time() - self::TOKEN_EXPIRE);
- return false;
- }
- $yz_member = SubMemberModel::getMemberByOpenid($openid);
- // 增加token验证
- if (is_null($yz_member) || $yz_member->member_id == 0 || $yz_member->access_token_1 != $token) {
- setcookie('Yz-Token', '', time() - self::TOKEN_EXPIRE);
- return false;
- }
- if (\YunShop::app()->getMemberId() != $yz_member->member_id) {
- Session::set('member_id', $yz_member->member_id);
- }
- return true;
- }
- return false;
- }
- private function wechatScope()
- {
- if (strpos($this->_getClientRequestUrl(), 'cashier_pay')) {
- $set = \Setting::get('plugin.store');
- if (isset($set['is_open_warrant']) && 1 == $set['is_open_warrant']) {
- return 'snsapi_userinfo';
- }
- return 'snsapi_base';
- }
- return 'snsapi_userinfo';
- }
- }
|