由于 JSAPI 调用微信支付需要用户的 openid,所以要了解如何获取到 openid。
还是官方的文档说的清楚
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
以 snsapi_base 为 scope 发起的网页授权,是用来获取进入页面的用户的 openid 的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)。
应该是用在登录之后,如果没有绑定 open_id 就应该立即调用授权。
前端判断是否在微信中,同时判断是否有 openid,如果在微信中,已登录并且没有 openid,则跳转。回调回来时,由于带了 code 参数,所以后台 controller 可以直接获取到 openid。并与当前用户关联。(取消 openid 的唯一索引。因为一个用户可能拥有多个手机号,对应同一个 openid)
获取 openid 的时机问题
这取决于业务场景,但是可以肯定的是需要在调用预支付之前,必须获取到 openid。
实现代码
$user = Auth::user();
$code = $request->get('code', ''); # redirect_uri/?code=CODE&state=STATE
// 判断是否在微信中
$ua = $request->header('User-Agent');
$is_in_wechat = preg_match('/MicroMessenger/i', $ua);
if ($is_in_wechat && !$user->open_id) {
// 用户在微信中, 并且没有关联 openid
if ($code) {
// 通过 code 获取 open_id
$client = new Client();
$url = sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
env('WECHAT_APPID'), env('WECHAT_SECRET'), $code);
try {
$res = $client->request('GET', $url, ['timeout' => 1.5]);
$res = $res->getBody();
$res = json_decode($res);
$user->open_id = $res->openid;
$user->save();
} catch(\Throwable $e) {
Log::info('Fail to call api');
}
} else {
// 静默授权,跳转获取 code
$url = sprintf("https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base#wechat_redirect",
env('WECHAT_APPID'), urlencode(env('APP_URL') . '/cart'));
return redirect($url);
}
}
返回的 JSON 数据结构
{
"access_token": "xxx",
"expires_in": 7200,
"refresh_token": "xxx",
"openid": "xxx",
"scope": "snsapi_base"
}
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式