前端:
<view class="form weapp"><button v-if="page.agree" open-type="getPhoneNumber" @getphonenumber="ttLogin" class="btn":class="{ disabled: !page.agree, 'ttprefix': page.mode== 'tt' }"><text>授权登录</text></button><view v-else class="btn" @click="validateChecked" :class="{ disabled: !page.agree }"><text class="text">授权登录</text></view>
</view>onLoad(({type
}) => {// #ifdef MP-TOUTIAOpage.can_switch = truepage.mode = 'tt'douyinLogin() // 进入就请求抖音login// #endif});const douyinLogin = () => {return new Promise(function(reslove, reject) {tt.login({success(res) {if (res.code && res.anonymousCode) {reslove(res);page.ttcode = res.codepage.anonymousCode = res.anonymousCode} else {reject('登录失败!' + res.errMsg)}},fail(res) {console.log(`login 调用失败`);},})})
}// 按钮发起请求
// 抖音登陆
const ttLogin = (e) => {const account = tt.getEnvInfoSync()const appid = account.microapp.appId // 获取appidconst {iv,encryptedData} = e.detail;const code = page.ttcode;const anonymous_code = page.anonymousCode;if (code) {passport.ttlogin({appid,codeanonymous_code,iv,encryptedData}).then(({data,err,msg}) => {if (err === 0) {const {token,user} = data;auth.login(token, {...user});uni.showToast({title: "登录成功"});setTimeout(() => {handleBack();}, 1500)} else {uni.showToast({title: msg,icon: "none"});}});} else {uni.showModal({title: "提示",content: "拒绝授权将无法登陆小程序!",showCancel: false,});}// ttcheckSession()
}
后端:
/*** @notes:抖音授权登陆* @return \think\response\Json* User: Administrator* Author:timeAxis* @date: * @throws \think\db\exception\DbException* @throws \think\db\exception\ModelNotFoundException* @throws \think\db\exception\DataNotFoundException*/public function ttlogin(){$rules = ['appid' => 'require','code' => 'require','anonymous_code' => 'require','source' => 'string','inviter' => 'string','iv' => 'require','encryptedData' => 'require'];$this->validate(request()->param(), $rules);$params = request()->only(array_keys($rules));$thirdmobile = ThirdPlatformUser::getmobile($params['appid'], $params['code'], $params['anonymous_code']);// 解密获取手机号$encryptedData = base64_decode($params['encryptedData'],true);$sessionKey = base64_decode($thirdmobile['data']['session_key']);$iv = base64_decode($params['iv']);$output = openssl_decrypt($encryptedData, 'AES-128-CBC',$sessionKey, 1,$iv);$output = json_decode($output, true);$mobile = $output['phoneNumber'];$user = User::where(['mobile' => $mobile,])->find();if(!$user){$lastFourDigits = substr($mobile, -4);$user = new User;$user->user_id = User::genID();$user->username = $user->user_id;$user->mobile = $mobile;$user->nickname = '昵称'.$lastFourDigits;$user->save();}$return = User::login_return($user);return success($return);}// 获取抖音授权凭证
public static function getmobile($appid, $code,$anonymous_code= null)
{$instance = App::instance(['app_id' => $appid,]);$resultparams = ['appid' => $instance->app_id,'secret' => $instance->secret,'code' => $code,'anonymous_code' => $anonymous_code];$resultstr = json_encode($resultparams);$url = "https://developer.toutiao.com/api/apps/v2/jscode2session"; // 地址
// $url = "https://open-sandbox.douyin.com/api/apps/v2/jscode2session"; // 测试$client = new Client;$resp = $client->post($url, ['body' => $resultstr]);$body = $resp->getBody()->getContents();$return = json_decode($body, true);if ($return['err_no']) {throw new \Exception("抖音授权失败: ".$return['errmsg']);}return $return;
}