前几天写了一个B扫C,管理员登录公众号扫用户微信付款码,类似于超市收银员扫我们的手机一样,第一次做这种,就把流程写下来!
B扫C
1.首先第一步要先设置安全域名
先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
备注:登录后可在“开发者中心”查看对应的接口权限。
2.引入js文件
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js
如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)。
安装:npm install weixin-js-sdk
let wx = require('weixin-js-sdk');
备注:支持使用 AMD/CMD 标准模块加载方法加载
3.通过config接口注入权限验证配置
let timestamp = DateFmt.Formate(DateFmt.DateCalc(new Date(), 'd', 0), 'yyyyMMddHHmmss');
let curUrl = window.location.href.split('#')[0];
let nonceStr = uuids(16, 16);
let jsapiTicket = data.retData.ticket;
let appid = data.retData.appid;
let before = 'jsapi_ticket=' + jsapiTicket + '&noncestr=' + nonceStr + '×tamp=' + timestamp + '&url=' + curUrl;
let signature = sha1(before);
wx.config({
debug: false, // 开启调试模式
appId: appid, // 必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: nonceStr, // 必填,生成签名的随机串
signature: signature, // 必填,签名
jsApiList: ['scanQRCode']
appid是公众号的唯一标识,可以让后端返回。
timestamp是生成当前时间的时间戳
nonceStr是生成一个随机串
jsapi_ticket是公众号用于调用微信JS接口的临时票据,让后端返回
signature是签名,生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。
jsApiList是需要使用的js接口列表
4.验证成功就可以写逻辑
let that = this;
wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有
success: function(res) {
let result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
let barCode = that.getBarCode(result);
这里掉后端接口,把barCode用户的付款码传给后端 }, fail: function(res) {
console.log(res);
}
});
引入js-sdk文件
let wx = require('weixin-js-sdk');
调起微信扫一扫接口
1.这里注意this指向
2.needResult要改成1,我们只要结果
wx.scanQRCode({
needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
success: function (res) {
var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
}
})
获取返回结果
var result = res.resultStr;
3.result为用户的付款码,苹果扫苹果手机当时正常,当苹果扫安卓手机的时候返回的结果带一个CODE_128。例:CODE_128,134564512168951760;这个时候就要把CODE_128截取掉;CODE_128是一种条码类型值
let result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
let barCode = that.getBarCode(result);
调用getBarCode方法截取code_128
getBarCode(resultStr) {
let serial = resultStr.split(',');
let barCode = serial[serial.length - 1];
return barCode;
};
最后把用户的付款码传给后端,具体扣款逻辑在后端!
PS:此次项目,前端都是axios的get请求,在苹果手机上是没有问题的,在安卓所有机型上就不行,status为0,报错为Network Error(网络错误)。这个时候就考虑到是Promise,es6语法等兼容性问题,后来确定是get请求URL拼接的参数过长导致的,然后就改用post请求,就遇到了新问题,前端post请求所有参数传过去,后端日志收到的都是null,
传过去是这样的,status为200,部分参数后端还是接收不到。
问题分析:也就是说,我们的 Content-Type 变成了 application/json;charset=utf-8然后,因为我们的参数是 JSON 对象,axios 帮我们做了一个 stringify 的处理。 而且查阅 axios 文档可以知道:axios 使用 post 发送数据时,默认是直接把 json 放到请求体中提交到后端的。
解决方案一:引入 qs ,这个库是 axios 里面包含的,不需要再下载了。
import Qs from 'qs';
return new Promise((resolve, reject) => {
axios({
url: url,
method,
params: isGet ? params : '',
data: isGet ? '' : Qs.stringify(params),
...config
}).then(rep =>
Qs.stringify()将对象 序列化成URL的形式,以&进行拼接
这样才完美解决!试了华为,vivo,oppo,等各种主流机型都没有问题。只有一个小米低版本目前还是存在一些问题!