前端:
<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-TOUTIAO
page.can_switch = true
page.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.code
page.anonymousCode = res.anonymousCode
} else {
reject('登录失败!' + res.errMsg)
}
},
fail(res) {
console.log(`login 调用失败`);
},
})
})
}
// 按钮发起请求
// 抖音登陆
const ttLogin = (e) => {
const account = tt.getEnvInfoSync()
const appid = account.microapp.appId // 获取appid
const {
iv,
encryptedData
} = e.detail;
const code = page.ttcode;
const anonymous_code = page.anonymousCode;
if (code) {
passport.ttlogin({
appid,
code
anonymous_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;
}