diff --git a/app/admin/view/default/appconfig/app.html b/app/admin/view/default/appconfig/app.html index 566d9c879..a8928e8ac 100644 --- a/app/admin/view/default/appconfig/app.html +++ b/app/admin/view/default/appconfig/app.html @@ -31,14 +31,14 @@
-

1. 获取当前小程序平台账户或者本本机的手机号码一键登录绑定,目前仅支持【微信小程序、百度小程序】

+

1. 获取当前小程序平台账户或者本本机的手机号码一键登录绑定,目前仅支持【微信小程序、百度小程序、头条小程序】

2. 依赖需要开启《强制绑定手机》有效

3. 部分小程序平台可能需要申请权限、请根据小程序平台要求申请后再对应开启

diff --git a/app/admin/view/default/user/save_info.html b/app/admin/view/default/user/save_info.html index 3e1e2e84e..52e81f8da 100755 --- a/app/admin/view/default/user/save_info.html +++ b/app/admin/view/default/user/save_info.html @@ -43,6 +43,10 @@ +
+ + +
diff --git a/app/service/AppMiniUserService.php b/app/service/AppMiniUserService.php index e0522ea6a..7e0fe73a3 100644 --- a/app/service/AppMiniUserService.php +++ b/app/service/AppMiniUserService.php @@ -172,15 +172,27 @@ class AppMiniUserService { $ret = DataReturn('授权登录成功', 0, ['is_user_exist'=>0, 'openid'=>$ret['data']['openid'], 'unionid'=>$unionid]); } else { + $status = false; // 如果用户openid为空则绑定到用户下面 - if(empty($user['weixin_openid'])) + if(empty($user['toutiao_openid'])) { - if(UserService::UserOpenidBind($user['id'], $ret['data']['openid'], 'weixin_openid')) + $status = UserService::UserOpenidBind($user['id'], $ret['data']['openid'], 'toutiao_openid'); + } + // 如果用户unionid为空则绑定到用户下面 + if(empty($user['weixin_unionid']) && !empty($unionid)) + { + // uniapp无绑定用户则更新到当前用户 + $temp = UserService::UserInfo('weixin_unionid', $unionid); + if(empty($temp)) { - // 登录数据更新 - $user = UserService::AppUserInfoHandle($user['id']); + $status = UserService::UserOpenidBind($user['id'], $unionid, 'weixin_unionid'); } } + // 是否重新获取用户信息 + if($status) + { + $user = UserService::AppUserInfoHandle($user['id']); + } } // 用户状态 @@ -393,13 +405,46 @@ class AppMiniUserService $ret = (new \base\Toutiao($config))->GetAuthSessionKey($params); if($ret['code'] == 0) { + // unionid + $unionid = empty($ret['data']['unionid']) ? '' : $ret['data']['unionid']; + // 先从数据库获取用户信息 $user = UserService::AppUserInfoHandle(null, 'toutiao_openid', $ret['data']['openid']); + if(empty($user) && !empty($unionid)) + { + // 根据unionid获取数据 + $user = UserService::AppUserInfoHandle(null, 'toutiao_unionid', $unionid); + } if(empty($user)) { - $ret = DataReturn('授权登录成功', 0, ['is_user_exist'=>0, 'openid'=>$ret['data']['openid']]); + $ret = DataReturn('授权登录成功', 0, ['is_user_exist'=>0, 'openid'=>$ret['data']['openid'], 'unionid'=>$unionid]); } else { - // 用户状态 + $status = false; + // 如果用户openid为空则绑定到用户下面 + if(empty($user['toutiao_openid'])) + { + $status = UserService::UserOpenidBind($user['id'], $ret['data']['openid'], 'toutiao_openid'); + } + // 如果用户unionid为空则绑定到用户下面 + if(empty($user['toutiao_unionid']) && !empty($unionid)) + { + // uniapp无绑定用户则更新到当前用户 + $temp = UserService::UserInfo('toutiao_unionid', $unionid); + if(empty($temp)) + { + $status = UserService::UserOpenidBind($user['id'], $unionid, 'toutiao_unionid'); + } + } + // 是否重新获取用户信息 + if($status) + { + $user = UserService::AppUserInfoHandle($user['id']); + } + } + + // 用户状态 + if(!empty($user)) + { $ret = UserService::UserStatusCheck('id', $user['id']); if($ret['code'] == 0) { @@ -448,6 +493,7 @@ class AppMiniUserService $auth_data['avatar'] = isset($auth_data['avatarUrl']) ? $auth_data['avatarUrl'] : ''; $auth_data['gender'] = empty($auth_data['gender']) ? 0 : (($auth_data['gender'] == 2) ? 1 : 2); $auth_data['openid'] = $params['openid']; + $auth_data['toutiao_unionid'] = isset($params['unionid']) ? $params['unionid'] : ''; $auth_data['referrer']= isset($params['referrer']) ? $params['referrer'] : 0; $ret = UserService::AuthUserProgram($auth_data, 'toutiao_openid'); } else { @@ -571,13 +617,46 @@ class AppMiniUserService $ret = (new \base\QQ(self::AppMiniConfig('common_app_mini_qq_appid'), self::AppMiniConfig('common_app_mini_qq_appsecret')))->GetAuthSessionKey($params['authcode']); if($ret['code'] == 0) { + // unionid + $unionid = empty($ret['data']['unionid']) ? '' : $ret['data']['unionid']; + // 先从数据库获取用户信息 $user = UserService::AppUserInfoHandle(null, 'qq_openid', $ret['data']['openid']); + if(empty($user) && !empty($unionid)) + { + // 根据unionid获取数据 + $user = UserService::AppUserInfoHandle(null, 'qq_unionid', $unionid); + } if(empty($user)) { - $ret = DataReturn('授权登录成功', 0, ['is_user_exist'=>0, 'openid'=>$ret['data']['openid']]); + $ret = DataReturn('授权登录成功', 0, ['is_user_exist'=>0, 'openid'=>$ret['data']['openid'], 'unionid'=>$unionid]); } else { - // 用户状态 + $status = false; + // 如果用户openid为空则绑定到用户下面 + if(empty($user['qq_openid'])) + { + $status = UserService::UserOpenidBind($user['id'], $ret['data']['openid'], 'qq_openid'); + } + // 如果用户unionid为空则绑定到用户下面 + if(empty($user['qq_unionid']) && !empty($unionid)) + { + // uniapp无绑定用户则更新到当前用户 + $temp = UserService::UserInfo('qq_unionid', $unionid); + if(empty($temp)) + { + $status = UserService::UserOpenidBind($user['id'], $unionid, 'qq_unionid'); + } + } + // 是否重新获取用户信息 + if($status) + { + $user = UserService::AppUserInfoHandle($user['id']); + } + } + + // 用户状态 + if(!empty($user)) + { $ret = UserService::UserStatusCheck('id', $user['id']); if($ret['code'] == 0) { @@ -762,6 +841,41 @@ class AppMiniUserService } break; + // 头条 + case 'toutiao' : + // 参数校验 + $p = [ + [ + 'checked_type' => 'empty', + 'key_name' => 'encrypted_data', + 'error_msg' => '解密数据为空', + ], + [ + 'checked_type' => 'empty', + 'key_name' => 'iv', + 'error_msg' => 'iv为空,请重试', + ] + ]; + $ret = ParamsChecked($params, $p); + if($ret !== true) + { + return DataReturn($ret, -1); + } + + // 数据解密 + $config = [ + 'appid' => self::AppMiniConfig('common_app_mini_toutiao_appid'), + 'secret' => self::AppMiniConfig('common_app_mini_toutiao_appsecret'), + ]; + $ret = (new \base\Toutiao($config))->DecryptData($params['encrypted_data'], $params['iv'], $params['openid']); + if($ret['code'] == 0 && !empty($ret['data']) && !empty($ret['data']['purePhoneNumber'])) + { + $mobile = $ret['data']['purePhoneNumber']; + } else { + return $ret; + } + break; + // 默认 default : return DataReturn(APPLICATION_CLIENT_TYPE.'平台还未开发手机一键登录', -1); diff --git a/app/service/UserService.php b/app/service/UserService.php index 4d548ed29..df675eef6 100755 --- a/app/service/UserService.php +++ b/app/service/UserService.php @@ -385,6 +385,7 @@ class UserService 'alipay_openid' => isset($params['alipay_openid']) ? $params['alipay_openid'] : '', 'baidu_openid' => isset($params['baidu_openid']) ? $params['baidu_openid'] : '', 'toutiao_openid' => isset($params['toutiao_openid']) ? $params['toutiao_openid'] : '', + 'toutiao_unionid' => isset($params['toutiao_unionid']) ? $params['toutiao_unionid'] : '', 'qq_openid' => isset($params['qq_openid']) ? $params['qq_openid'] : '', 'qq_unionid' => isset($params['qq_unionid']) ? $params['qq_unionid'] : '', 'weixin_openid' => isset($params['weixin_openid']) ? $params['weixin_openid'] : '', @@ -2026,9 +2027,10 @@ class UserService // 用户unionid列表 // 微信用户unionid // QQ用户unionid + // 头条用户unionid $field = null; $value = null; - $fields_arr = ['weixin_unionid', 'qq_unionid']; + $fields_arr = ['weixin_unionid', 'qq_unionid', 'toutiao_unionid']; foreach($fields_arr as $unionid) { if(!empty($params[$unionid])) diff --git a/extend/base/Baidu.php b/extend/base/Baidu.php index 438fd5a3b..4cef1f6b3 100755 --- a/extend/base/Baidu.php +++ b/extend/base/Baidu.php @@ -50,7 +50,7 @@ class Baidu * @param [string] $encrypted_data [加密的用户数据] * @param [string] $iv [与用户数据一同返回的初始向量] * @param [string] $openid [解密后的原文] - * @param [string] $key [当时业务key] + * @param [string] $key [当前业务key] * @return [array|string] [成功返回用户信息数组, 失败返回错误信息] */ public function DecryptData($encrypted_data, $iv, $openid, $key = 'user_info') @@ -110,10 +110,6 @@ class Baidu { return DataReturn('appkey不匹配', -1); } - - // 缓存存储 - $data_key = 'baidu_'.$key.'_'.$openid; - MyCache($data_key, $data); return DataReturn('success', 0, $data); } diff --git a/extend/base/QQ.php b/extend/base/QQ.php index 4b9f06ffe..3ef333c2a 100644 --- a/extend/base/QQ.php +++ b/extend/base/QQ.php @@ -84,10 +84,6 @@ class QQ { return DataReturn('appid不匹配', -1); } - - // 缓存存储 - $data_key = 'qq_user_info_'.$openid; - MyCache($data_key, $data); return DataReturn('success', 0, $data); } diff --git a/extend/base/Toutiao.php b/extend/base/Toutiao.php index b0cc60a75..d25709eee 100644 --- a/extend/base/Toutiao.php +++ b/extend/base/Toutiao.php @@ -35,6 +35,52 @@ class Toutiao $this->config = $config; } + /** + * 检验数据的真实性,并且获取解密后的明文 + * @author Devil + * @blog http://gong.gg/ + * @version 1.0.0 + * @datetime 2017-12-30T18:20:53+0800 + * @param [string] $encrypted_data [加密的用户数据] + * @param [string] $iv [与用户数据一同返回的初始向量] + * @param [string] $openid [解密后的原文] + * @return [array|string] [成功返回用户信息数组, 失败返回错误信息] + */ + public function DecryptData($encrypted_data, $iv, $openid) + { + // 登录授权session + $login_key = 'toutiao_user_login_'.$openid; + $session_data = MyCache($login_key); + if(empty($session_data)) + { + return DataReturn('session key不存在', -1); + } + + // iv长度 + if(strlen($iv) != 24) + { + return DataReturn('iv长度错误', -1); + } + + // 加密函数 + if(!function_exists('openssl_decrypt')) + { + return DataReturn('openssl不支持', -1); + } + + $result = openssl_decrypt(base64_decode($encrypted_data), "AES-128-CBC", base64_decode($session_data['session_key']), 1, base64_decode($iv)); + $data = json_decode($result, true); + if($data == NULL) + { + return DataReturn('请重试!', -1); + } + if($data['watermark']['appid'] != $this->config['appid']) + { + return DataReturn('appid不匹配', -1); + } + return DataReturn('success', 0, $data); + } + /** * 用户授权 * @author Devil @@ -64,6 +110,11 @@ class Toutiao } if(!empty($result['openid'])) { + // 缓存SessionKey + $key = 'toutiao_user_login_'.$result['openid']; + + // 缓存存储 + MyCache($key, $result); return DataReturn('授权成功', 0, $result); } $msg = empty($result['errmsg']) ? '授权接口异常错误' : $result['errmsg']; diff --git a/extend/base/Wechat.php b/extend/base/Wechat.php index 3e6cfaf6f..129a52c49 100755 --- a/extend/base/Wechat.php +++ b/extend/base/Wechat.php @@ -171,10 +171,6 @@ class Wechat { return DataReturn('appid不匹配', -1); } - - // 缓存存储 - $data_key = 'wechat_user_info_'.$openid; - MyCache($data_key, $data); return DataReturn('success', 0, $data); }