公司开发的项目用uni-app开发,功能要求使用支付宝授权登录,由于uni-ap官网并没有实现支付宝的第三方登陆(集成了QQ,微博,微信的授权登录)。没办法,只能满网搜教程。
首先,由于想要实现支付宝登陆必须要在支付宝内打开我们拼接的连接类似这样:
https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=商户的APPID&scope=auth_user&redirect_uri=ENCODED_URL&state=init
实现步骤:
1.在点击事件上使用plus.runtime模块调用支付宝打开授权地址(授权地址是后端拼接也可以前端写死,个人感觉后端获取相对比较好)
//相关示例代码:(该代码会打开支付宝授权,授权之后会在支付宝中打开你所设置的【回调地址】网页)//***********************//***url授权地址由后端拼接也可以前端写死***//***以下是一个拼接示例,仅需修改app_id的值和redirect_uri的值***//***app_id是商户的APPID,redirect_uri是页面跳回地址(授权成功之后会在支付宝中打开这个地址)***//***********************let urls='https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=2021001183611007&scope=auth_userinfo&redirect_uri=https://shandianlaoshi.com/api/user/zfb_url';urls=encodeURIComponent(urls);//将地址编码成浏览器访问的格式// 判断平台if (plus.os.name == 'Android') { plus.runtime.openURL( 'alipays://platformapi/startapp?appId=20000067&url=' + urls, res => {//这里写打开URL地址失败后的处理 console.log(res); uni.showModal({ content: '本机未检测到对应客户端,是否打开浏览器访问页面?', success: function (res) { if (res.confirm) { //plus.runtime.openURL(); } } }); }, 'com.eg.android.AlipayGphone' );} else if (plus.os.name == 'iOS') { plus.runtime.openURL( 'alipay://platformapi/startapp?appId=20000067&url=' + urls, res => { console.log(res); uni.showModal({ content: '本机未检测到对应客户端,是否打开浏览器访问页面?', success: function (res) { if (res.confirm) { //plus.runtime.openURL(url); } } }); }, 'com.eg.android.AlipayGphone' );}
注意:其中20000067这个appId是固定值,不需要修改成你的APPID。
如此调用即可正常使用支付宝登陆了。
2.给你的APP设置一个urlscheme
这是Android平台设置UrlSchemes,为了方便实现被第三方应用调用
HBuilder/HBuilderX自带真机运行基座的UrlSchemes为"hbuilder://",方便开发者调测。
设置方法连接:https://uniapp.dcloud.io/tutorial/app-android-schemes.html
3.提交打包(urlscheme)设置之后需重新打包(可以重新打基座也可以直接云App打包,建议打基座【因为还需要写从支付宝回来之后的事件】)
4.编写(redirect_uri)页面,编写完成后拿给后端放在服务器上就基本成功了
如果出现没有跳转到你的APP说明你的urlscheme没填写对或者是你的APP没有打包
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>XXXX登录</title> <style> body { display: flex; justify-content: center; align-items: center; text-align: center; height: 90vh; font-size: .9375rem; } content{ display: flex; flex-direction: column; justify-content: center ; align-items: center; } .logo_img { width: 6.875rem; height: 6.875rem; margin-bottom: .625rem; } #box { width: 80%; height: 2rem; text-align: center; line-height: 2rem; border-radius: 20px; background-color: rgb(23, 120, 194); color: white; margin: .9375rem auto; } .desc { font-size: .3125rem; color: gray; } </style></head><body> <content> <img src="./logo.png" class="logo_img"> <div id="box" onclick="func()">返回XXXX</div> <div class="desc">您已授权登录,请点击返回XXXX</div> </content><script>var code ;function getQueryVariable(variable) { var query = window.location.search.substring(1); var vars = query.split("&"); for (var i = 0; i < vars.length; i++) { var pair = vars[i].split("="); if (pair[0] == variable) { return pair[1]; } } return (false); } function func(){ code = getQueryVariable("auth_code"); // 判断是那种设备 let u = navigator.userAgent; console.log(u); var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; // Android系统或者uc浏览器 var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); // iOS系统 // 如果为Android系统 if (isAndroid) { window.location.href = "hbuilder://?auth_code="+code; // 注意*** 这里需要修改为刚刚设置的urlscheme,auth_code需要后端拼接。auth_code只有后端才能拿到 window.setTimeout(function () { window.location.href = "http://www.baidu.com"; // 3s后如果不能跳转到 App,则跳转到 App 的下载地址,一般是应用宝的对应的下载地址 }, 2000); return; } // ios设备:原理:判断是否认识这个协议,认识则直接跳转,不认识就在这里下载appios(); if (isiOS) { let startIndex = u.indexOf('iPhone OS') + 9; let endIndex = u.indexOf('like Mac OS') - 1; let num = +u.slice(startIndex, endIndex).split('_')[0]; // 计算版本号的前面数值 if (num < 9) { window.location.href = "hbuilder://?auth_code="+code; // 注意*** 这里需要修改为刚刚设置的urlscheme,auth_code需要后端拼接。auth_code只有后端才能拿到 } else { window.location.href = " "; // universal link 链接 } window.setTimeout(function () { window.location.href = " "; // 3s后如果不能跳转到 App,则跳转到 AppStore 的下载地址 }, 3000); return; };}</script></body></html>
千万注意:alipayUrl中的回调地址(redirect_uri)必须是可以从公网直接访问的,格式是http://或者https:// 开头的,请不要填写内网地址(如:http://localhost:8080/)和相对地址(/pages/aliPay)等等,否则跳转会提示404或无法访问。
5.在页面中监听支付宝App传过来的auth_code,再通过auth_code获取到userId就完成了支付宝的授权啦(可以在redirect_uri页面中直接获取userId再跳转回APP也可以返回App后通过auth_code请求后端获取userId【PS:后者方案更灵活】)
onShow: function() {let args = plus.runtime.arguments;//console.log(args); //这里可以看到从后端拿过来的urlschemeif (args) {plus.runtime.arguments=null;//进入之后就把urlscheme清空要不然下一次oushow时还会执行// 处理args参数,如直达到某新页面等//通过code请求获取user_idvar authCode = args.split("=")[1];if(authCode!=undefined&&authCode!=""&&authCode!=null){this.$busapi.restAuth.queryAlipayInfo("authCode="+authCode).then(res => {if (res.code == '0000') {if(res.data.userId){this.whetherBinding(res.data.userId,"alipay");}}else{this.$message({ message: res.msg, type: 'error' });}}).catch(res => {this.$message({ message: res.errmsg, type: 'error' });});}}},
由此,该功能就差不多完成了,最后一定要感谢两位大佬的文章指点,链接如下:
https://blog.csdn.net/z1783883121/article/details/116268402
https://ask.dcloud.net.cn/article/36971