微信公众号支付

时间:2022-10-25 10:57:05

微信公众号支付

最近群里被微信小程序刷了屏,由于目前没有具体去研究过,所以也不知道这个对APP的市场冲击有多大。

当然撇开小应用不说,微信的公众号开发还是必须要学习的,本文记录了最近开发公众号遇到的公众号支付问题及个人心得。

支付功能只有服务号才有,对于普通的订阅号是无法使用的,服务号的申请工作本文不赘述

微信jssdk配置步骤

使用公众号支付我们需要使用到微信的jssdk,微信jssdk配置步骤如下:

一、绑定域名

域名设置,如图:

微信公众号支付

微信公众号支付

二、引入js文件(支持https)

三、通过config接口注入权限验证配置

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。

wx.config({
debug: true// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: ''// 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: ''// 必填,生成签名的随机串
signature: ''// 必填,签名,
jsApiList: []//必填,需要使用的JS接口列表(权限),所有JS接口列表下面会给出本人已经摘录好的!!!
});

注意:所有接口通过wx对象(也可使用jWeixin对象)来调用,参数是一个对象,除了每个接口本身需要传的参数之外,还有以下通用参数:
success:接口调用成功时执行的回调函数。
fail:接口调用失败时执行的回调函数。
complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。
备注:不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回。
以上几个函数都带有一个参数,类型为对象,其中除了每个接口本身返回的数据之外,还有一个通用属性errMsg,其值格式如下:
调用成功时:”xxx:ok” ,其中xxx为调用的接口名
用户取消时:”xxx:cancel”,其中xxx为调用的接口名
调用失败时:其值为具体错误信息`

四、通过ready接口处理成功验证

wx.ready(function(){
});

注意: config信息验证后会执行ready()方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready()函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready()函数中。

五、通过error接口处理失败验证

wx.error(function(res){
});

注意 config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。

微信支付所需要的配置:

微信支付需要设置支付目录,特别要注意的是这里必须是直接父级目录,比如我的支付页面目录为xxx/html/order/pay.html那么支付目录需要设置为xxx/html/order,最多能设置3个支付目录且域名必须通过ICP备案。

如图:

微信公众号支付

微信支付业务流程:

微信公众号支付

如何调起微信:
公众号支付如何调起微信?

jssdk封装的支付接口:

wx.chooseWXPay({
timestamp: 0// 支付签名时间戳,微信jssdk中的所有timestamp字段均为小写。最新版需要大写S。
nonceStr: ''// 支付签名随机串,不长于 32 位。
package: ''// 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=xxx。
signType: ''// 签名方式,默认为'SHA1',使用新版支付需传入'MD5'。
paySign: ''// 支付签名。
success: function (res) {
// 支付成功后的回调函数
}
});

以上的参数在调用微信统一下单接口会返回,当然这个最好让自己服务器给你返回:

微信公众号支付

封装举例说明

我这里对微信支付封装了一个wechat.js,有需要的同学可以参考下:

var wechat = {};
var DEBUG = true;
//通过服务器接口获取配置信息
wechat.getWXConfig = function(url, callback) {
app.webapi.wechat.getWXConfig(url, function(data) {
if(data.status == 1) {
callback(data.data);
}
}, function(xhr, type, errorThrown) {
callback();
});
}

//初始化微信jssdk
wechat.initPay = function(callback) {
var url = location.href;
wechat.getWXConfig(url, function(config) {
var appId = config.appId;
var timestamp = config.timestamp;
var nonceStr = config.nonceStr;
var signature = config.signature;
wx.config({
debug: DEBUG,
appId: appId,
timestamp: timestamp,
nonceStr: nonceStr,
signature: signature,
jsApiList: [
CHOOSE_WX_PAY //这里只需要支付权限
]
});
wx.ready(function() {
callback();
});
wx.error(function(res) {

});
});
}


/**
* 微信公众号支付
* @param {Object} timestamp 时间戳
* @param {Object} nonceStr 支付签名随机串
* @param {Object} package 统一接口返回的prepay_id
* @param {Object} signType 签名方式,新版需要MD5
* @param {Object} paySign 支付签名
* @param {Object} callBack 支付之后的回调
*/

wechat.pay = function(timestamp, nonceStr, packag, signType, paySign,callBack) {
wechat.initPay(function() {
wx.chooseWXPay({
timestamp: timestamp,
nonceStr: nonceStr,
'package': packag,//关键字需要处理一下
signType: signType,
paySign: paySign,
success: function(res) {
if(callBack){
callBack(0);
}
}
});
});
}

这样只需要在调用的地方传入相应的参数就能调起公众号支付了,成功掉起微信支付如图所示:

微信公众号支付

附权限列表

const CHECKJSAPI = 'checkJsApi'; //检测js是否可用
const SHARE_TO_APP = 'onMenuShareAppMessage'; //分享到微信
const SHARE_TIMELINE = 'onMenuShareTimeline'; //分享到朋友圈
const SHARE_TO_QQ = 'onMenuShareQQ'; //分享到QQ
const SHARE_TO_WEIBO = 'onMenuShareWeibo'; //分享到微博
const SHARE_TO_QZONE = 'onMenuShareQZone'; //分享到QQ控件
const HIDE_MENU_ITEMS = 'hideMenuItems'; //隐藏某个菜单item
const SHOW_MENU_ITEMS = 'showMenuItems'; //显示某个菜单item
const HIDE_ALL_NONE_BASE_ITEMS = 'hideAllNonBaseMenuItem'; //隐藏所有非基础菜单item
const SHOW_ALL_NONE_BASE_ITEMS = 'showAllNonBaseMenuItem'; //显示所有非基础菜单item
const TRANSLATEVOICE = 'translateVoice'; //声音转文本
const START_RECORD = 'startRecord'; //开始录音
const STOP_RECORD = 'stopRecord'; //停止录音
const RECORD_END = 'onVoiceRecordEnd'; //录音结束
const PLAY_VOICE = 'playVoice'; //播放录音
const ON_VOICE_PLAY_END = 'onVoicePlayEnd'; //播放录音结束
const PAUSE_VOICE = 'pauseVoice'; //暂停播放录音
const STOP_VOICE = 'stopVoice'; //停止播放录音
const UPLOAD_VOICE = 'uploadVoice'; //上传录音
const DOWNLOAD_VOICE = 'downloadVoice'; //下载录音
const CHOOSE_IMAGE = 'chooseImage'; //从图库选择图片
const PREVIEW_IMAGE = 'previewImage'; //预览图片
const UPLOAD_IMAGE = 'uploadImage'; //上传图片
const DOWNLOAD_IMAGE = 'downloadImage'; //下载图片
const GET_NET_STATE = 'getNetworkType'; //获取网络状态
const OPEN_LOCATION = 'openLocation'; //打开定位
const GET_LOCATION = 'getLocation'; //获取定位
const HIDE_OPTION_MENU = 'hideOptionMenu'; //隐藏右上角菜单
const SHOW_OPTION_MENU = 'showOptionMenu'; //显示右上角惨淡
const CLOSE_WINDOW = 'closeWindow'; //关闭窗口
const SCAN_QRCODE = 'scanQRCode'; //开始扫描
const CHOOSE_WX_PAY = 'chooseWXPay'; //微信支付
const OPEN_PRODUCT_SPECIFIC_VIEW = 'openProductSpecificView'; //微信商品页
const ADD_CARD = 'addCard' //添加卡券
const CHOOSE_CARD = 'chooseCard'; //选择卡券
const OPEN_CARD = 'openCard'; //打开卡券

改进的封装

你以为结束了,并没有!微信jssdk有个坑,那就是在iframe里面会失效,我做公众号的时候开始也是莫名其妙后来经过本人多次测试终于找到原因,就是因为页面包含iframe的话导致jssdk无法正常使用,于是我改进了支付接口的封装:

/**
* 在iframe里面支付,jsdk在iframe会失效
* @param {Object} timestamp
* @param {Object} nonceStr
* @param {Object} package
* @param {Object} signType
* @param {Object} paySign
* @param {Object} callback
*/

wechat.payInIframe = function(timestamp, nonceStr, packag, signType, paySign,callBack) {
parent.wx.ready(function() {
parent.wx.chooseWXPay({
timestamp: timestamp,
nonceStr: nonceStr,
'package': packag,
signType: signType,
paySign: paySign,
success: function(res) {
if(callBack){
callBack(0);
}
}
});
});
}

当你的页面包含iframe的话你只需要在主页面进行签名验证,子页面不添加jssdk的签名信息。需要调用jssdk接口时,在jssdk的函数前加parent.,即调用父页面的此函数

另外还有一个问题,就是你在输入框输入的时候可能会提示一些安全提示之类的术语,这是因为你的业务域名没有设置,在这里设置你的业务域名之后安全提示就没有了:

微信公众号支付

Android开发者看这里