最近在做微信支付,当对接微信客户端浏览器支付所需要的jsapi接口时,需获取微信公众号的用户openid,为了用户体验采用了静默登陆的方式 /sns/oauth2/access_token,然而对接后发现获取openid原始页面的返回上一页功能变成当页死循环刷新,无法回到上一页了。
仔细看了静默登陆的代码,发现微信的实现方式是用页面刷新跳转到微信页拿code,然后跳转回客户当前页。导致当前页的来源页变为微信页了,因此无法再拿到当前页真正的项目来源页。
多番尝试,解决方法如下:
1、粗暴处理
将静默登陆获取code的页面换为项目入口文件页,或者首页,即不需要返回按钮操作的页面。
2、温柔处理
因在下单页获取授权后url中携带code
参数,会出现这种死循环的问题,可在授权页面指定的redirect_uri
页面(本例的下单页)做一下处理,满足某个条件就不再跳往到微信授权页。
实现方案如下:
-
指定一个用于授权成功后的回调链接redirect url,域名得和前端业务域名一致,并且整个链接是需要在微信开发者后台配置的。
-
在进入步骤1指定的页面后,需要获取url参数code和session中的code值,根据二者code是否均有值来判断是否需要重定向到微信授权页面
-
在步骤2中两种情况下的code值都为空时,前端使用location.replace(url)方法来跳转到微信授权页面,授权成功后跳转到步骤1指定的回调页面。此时浏览器历史记录只增加了1条,即微信授权页面历史记录
-
在步骤2设置的回调页面中,若url的code参数有值且session获取的code值为null时,将url的code参数值存到session中,然后history.back()
-
在history.back()执行后,就又回到授权链接跳转之前的那个页面,即进入未跳转前的下单页。
-
再次点击微信返回按钮,就可以正常返回了
具体的代码实现部分如下:
1) JS代码:
const params = getQueryParams()
const code = sessionStorage.getItem('code')
if (!params.code && !code) {
let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${yourAppId}&redirect_uri=${encodeURIComponent(location.href)}&response_type=code&scope=snsapi_base&state=1#wechat_redirect`
window.location.replace(url)
} else if(!code){
sessionStorage.setItem('code', params.code)
history.back()
}
2)PHP代码:
/**
*
* 通过跳转获取用户的openid,跳转流程如下:
* 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
* 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code
*
* @return 用户的openid
*/
public function GetOpenid()
{
$wx_code = @session('wx_code');
$wx_openid = @session('wx_openid');
if($wx_openid){
if($wx_code){
session('wx_code', null);
}
return $wx_openid;
}
//通过code获得openid
if (!isset($_GET['code']) && !$wx_code){
$old_url = HTTP_TYPE.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
//触发微信返回code码
$baseUrl = urlencode($old_url);
$url = $this->__CreateOauthUrlForCode($baseUrl);
echo '<script>window.location.replace("'.$url.'")</script>';exit;
} else if(!$wx_code && isset($_GET['code'])) {
//获取code码,以获取openid
$code = $_GET['code'];
$openid = $this->getOpenidFromMp($code);
session('wx_code', $code);
session('wx_openid', $openid);
return $openid;
}
}