最近公司项目有个充值需求,在微信公众号中添加在线充值,充值页面是用H5完成的,页面中包括微信支付方式和支付宝支付方式。也就是说,要在微信内置浏览器中完成微信支付和支付宝支付。
这个页面,我通过接入Ping++的H5 SDK完成充值功能。附上Ping++的H5 SDK接入指南地址:Ping++ H5 SDK接入指南
开发之前,建议先看一下SDK,有一个大致的了解,然后可以下载demo。附上Github上的demo下载地址:Github上的demo地址。这个链接在文档中也有。
在下载的文件中,有一个demo文件夹,其中的wap.html可以作为开发参考。
下面是ping++支付中前端开发流程的总结(当然需要后端的配合),需要可以做个参考。
微信支付
1.引入pingpp.js文件(文件路径都是我自己项目的文件路径,应该根据自己的项目进行修改)。
<script src="node_modules/pingpp-js/dist/pingpp.js"></script>
2.js中写入支付函数,参照demo中wap.html的wap_pay( )函数。
刚开始我是将demo中的函数直接复制过来的,但是测试过程中post请求这一块总是有问题,数据发送不过去,我就稍微修改了一下,但是没搞明白为什么demo中的会出错,有清楚的朋友欢迎评论中赐教。示例:
function wap_pay(channel) {
var YOUR_URL = 后台的充值接口;
if(YOUR_URL.length == 0 || !YOUR_URL.startsWith('http')){
alert("请填写正确的URL");
return;
}
var amount = document.getElementById('amount').value * 100; //获取充值金额
var xhr = new XMLHttpRequest();
xhr.open("POST", YOUR_URL, true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded;application/json;charset=UTF-8");
xhr.send("channel="+channel+"&amt="+amount+"&id="+id+"&open_id="+open_id);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
try{
var charge = JSON.parse(xhr.responseText)['charge'];
}catch(err){
alert('系统错误!');
}
pingpp.createPayment(xhr.responseText, function(result, err) {
console.log(result);
console.log(err.msg);
console.log(err.extra);
if (result == "success") {
// 只有微信公众账号 wx_pub 支付成功的结果会在这里返回,其他的支付结果都会跳转到 extra 中对应的 URL(后端处理)。
//我的项目中在微信公众号支付成功会跳转到我们的支付成功页面
window.location.href = 'success.html';
} else if (result == "fail") {
// charge 不正确或者微信公众账号支付失败时会在此处返回
//支付失败会跳转到支付失败页面
window.location.href = 'fail.html';
} else if (result == "cancel") {
// 微信公众账号支付取消支付
//取消支付同样跳转到支付失败页面
window.location.href = 'fail.html';
}
});
}
}
}
注:请求中需要传给后端的数据,由自己的项目需求而定,比如我的项目中就需要传入用户的id。
关于open_id的获取
微信公众号支付中,需要注意的是,要获取用户的open_id作为用户唯一标识,才能唤起微信支付。同时还需要配置安全域名之类的,我是公司的技术负责人配置的。文档中有链接地址。
关于open_id的获取方式,我是通过和后端协商以后决定的,大致的前后端交互思路如下:
1. 进入充值页面以后,当用户选好金额,点击微信支付按钮时,跳转至后端给的一个链接,也就是一个后台接口地址,同时将金额和用户id拼接在地址后。
2. 后端在接口中,会默认用户授权登录,获取到授权code,再使用code获取open_id。
3. 后端获取到open_id以后,会将页面跳转到开始的H5充值页面,同时将金额、用户id以及open_id拼接在url地址中。
4. 前端,嗯,也就是我,获取到url中的数据,然后直接执行wap_pay(‘wx_pub’)支付函数,同时将channel、金额、用户id、open_id通过post请求传给后端。
5. 后端返回正确的charge,就可以成功调起支付。(charge中应该是要包含open_id)
6. 在这个过程中,用户的视觉效果就是,点击微信支付以后,页面刷新了一下, 随后就直接调起了微信支付。
上述是一个前后端交互的思路,结合到前端代码的编写,我是按照如下思路编写的: 1. 用户进入充值页面以后,先判断url地址中是否拼接了open_id字段,如果没有拼接,则跳转至后端接口地址。
2. 如果获取到了url地址中open_id字段,则直接执行wap_pay(‘wx_pub’)。
注:获取到open_id重新返回充值页面以后,之前页面中的金额被选中状态已经没有了,所以这里需要根据url中返回的金额,通过JS逻辑将页面重现跳转之前的状态。
这里附上我关于这部分的代码作为参考,不同的项目要根据自己的页面以及需求去修改JS逻辑。
//获取url中的open_id
var Request = new Object();
Request = GetRequest();
open_id = Request['open_id'];
if(open_id == undefined){
$('.wx').unbind('click').click(function(){
if(jingyu_id == '' || jingyu_id == null){
alert('请登录后再充值!');
}else{
if($('#amount').length > 0){
window.location.href = 'http://a.whale.ikanlive.com/web/wx_pub_pay?money='+amount+'&id='+jingyu_id;
}else{
alert('请选择充值金额!');
}
}
})
}else{
//这部分代码是为了复现页面跳转之前的状态,也就是页面跳转回来以后,页面仍然是选中金额的状态
amount = parseInt(Request['money']);
var money = amount + '元';
$('.content').find('.content_li').each(function(){
if($(this).find('.zs_price').text() == money){
$(this).css('background-image','url(img/images_xz_@2x.png)');
$(this).attr('id','amount');
}
});
//执行支付函数
wap_pay('wx_pub');
}
支付宝支付
支付宝支付相比微信支付,要简单一些。只需要在点击按钮时,直接执行wap_pay(‘alipay_wap’);
但是存在的一个问题是,在微信内置浏览器中,是无法直接调起支付宝网页版支付控件的。
针对这一问题,Ping++给出的解决方案是这样的:
这上面的两种解决方案都是让充值页面跳转至一个中间页,中间页会提示用户用手机浏览器打开当前页面。
第一种是将pay.htm文件放在和H5充值页面同级目录下。
第二种方式,在充值页面html文件中添加代码:
然后修改pay.htm最下面的代码:
上面两种方式我都尝试过了,但是都不起作用,点击支付宝支付还是出现了一长串链接。这个问题搞了很久都没有解决,中间页就是无法唤起。后来无奈换了需求,自己做了一个中间跳转页面,然后点击支付宝支付时,跳转至自己的中间页面,提示用户在手机浏览器中打开。这一块有清楚的也欢迎评论留言哦~
支付宝支付思路
所以点击支付宝支付时,先判断当前浏览器,如果是微信浏览器,则跳转中间页,如果是手机浏览器,则执行支付函数。代码示例如下:
//点击支付宝支付判断浏览器
$('.zfb').unbind('click').click(function(){
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=="micromessenger") {
// 微信 JS逻辑根据自己需要进行修改
$('.prompt').slideDown('slow');
} else {
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
//苹果手机浏览器
wap_pay('alipay_wap');
} else if (/(Android)/i.test(navigator.userAgent)) {
//安卓手机浏览器
wap_pay('alipay_wap');
} else {
confirm('请通过手机浏览器查看此页面!');
}
}
})
一个大概的微信内置浏览器中微信支付和支付宝支付的总结,前端方面的任务其实很简单,只需要将页面搭建好,然后在点击支付按钮时,执行demo中的wap_pay()函数,向后台发送正确的ajax请求就可以了,主要是后端要返回正确的charge。
文章中有描述不清楚的地方或者错误的地方还希望能及时指出。后续再有关于H5支付或者PC支付的项目,也会进行补充。