微信公众平台开发注意事项

在此记录一波对接微信公众号的一些经验及注意事项,以供参考

防盗号或诈骗,请不要输入QQ密码

在公众号里打开的网页,遇到输入框时,首先就遇到上面的提示。把它干掉,首要的需求

解决方案:微信公共平台–>公众号设置—>功能设置—>业务域名

授权

点击微信公众号网页,获取用户的openid, 以及其他基本信息(包括头像,微信昵称),这也是基本需求

实现方式有两种,都是基于重定向的

  1. 请求业务后台地址,获取用户信息后,重定向到前端页面。此时前端需要给后端人员一个外网可访问的首页url,openid及头像等参数作为query值拼接在url上
  2. 请求微信网页授权地址,获取用户code,重定向到前端页面, code作为query拼接在url上,之后再进行一系列操作(获取用户openid, 及基本信息)。这种情况,url同样由前端提供

所以说,对query值的获取是基本操作,推荐yarn命令走一波

1
yarn add qs

至于选用哪种方式,结合己方业务去考量。

注意:如果是网页授权,重定向的url不能带锚点(#),也不能带query(会被微信Auth2.0重定向后的query覆盖掉),所以hash模式的SPA只能重定向到首页, 微信模板消息同理。

微信JS-SDK

需要做以下配置:

  • JS安全域名: 微信公众平台–>公众号设置–>功能设置–>JS接口安全域名
  • ip白名单: 获取access_token要用到

需要拿到以下参数:

  • appsecret(获取access_token要用到, 这是获取jsapi_ticket的前提)
  • appid(获取access_token要用到, 这是获取jsapi_ticket的前提)

后面则是引入js文件,获取jsapi_ticket,并进行配置

jsapi_ticket需要后台提供接口

下面给出基于Nuxt开发的Vue SPA工程的配置实现,以供参考:

1
2
3
4
5
6
7
8
9
10
// nuxt.config.js
module.exports = {
head: {
script: [
// 接入微信sdk要用
{src: 'https://cdn.bootcss.com/js-sha1/0.4.1/sha1.min.js'},
{src: 'https://res.wx.qq.com/open/js/jweixin-1.2.0.js'},
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// plugins/wechat

/**
* Created by levy on 2018/8/15.
*/
import {wechatAppId, jsApiTicket,} from '@/const/wechat'

export default function({app}) {
if (process.env.NODE_ENV !== 'production') return

app.router.afterEach(async (to, from) => {
let resp
try {
// jsapi_ticket是公众号用于调用微信JS接口的临时票据,由开发者后台实现
resp = await app.$axios.$get(jsApiTicket)

let ticket = resp.payload,
timestamp = new Date().getTime(),
nonceStr = 'nonceStr',
// 注意:就算是SPA工程,路由模式是hash,url也一定是这样获取
// 直接使用这里的代码就好了,否则必定报错,切记切记
url = location.href.split('#')[0]

let str = `jsapi_ticket=${ticket}&noncestr=${nonceStr}&timestamp=${timestamp}&url=${url}`,
signature = sha1(str)

// 配置菜单
wx.config({
// debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: wechatAppId, // 必填,公众号的唯一标识
timestamp, // 必填,生成签名的时间戳
nonceStr, // 必填,生成签名的随机串
signature, // 必填,签名,
jsApiList: [
'hideAllNonBaseMenuItem',
'scanQRCode',
'chooseWXPay',
'closeWindow'
] // 必填,需要使用的JS接口列表,如果为空,则后面调用jsApi时将失败
})

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

// 隐藏所有传播菜单, 不能复制链接等, 只能刷新
wx.hideAllNonBaseMenuItem()
})
} catch (e) {
console.error('wechat sdk config error : ', e)
}
})
}

扫一扫/二维码

  1. 问:是否可以在h5页面中显示自己的微信二维码,让对方扫一扫添加好友?

    答:可以在h5页面中调用SDK的scanQRCodeAPI, 调用扫一扫功能,里面会有一个“我的二维码”,达到“曲线救国”的目的

  2. 问:是否可以实现扫一扫后带参跳转?

    答:可以,不过需要结合具体场景来考虑实现方式

    如果完全由前端来做,那么,这个扫一扫功能必须在公众号的h5页面内,自行处理scanQRCode后的处理逻辑,在公众号内实现带参的跳转。

    如果有后台配合,则可以做到由微信自带的扫一扫功能,扫码后带参进入公众号h5页面

公众号支付

你需要做以下设置:

  • 设置JS安全域名:微信公众平台–>公众号设置–>功能设置–>JS接口安全域名(微信JS-SDK要用)
  • 设置授权域名:微信公众平台–>公众号设置–>功能设置–>网页授权域名
  • 设置支付目录:微信商户平台 –> 产品中心 –> 开发配置–> 微信支付授权目录(支付页面所在的最后一层目录)

你需要拿到以下参数:

  • appid(公众账号ID,一定是wx开头的,如wxd678efh567hg6787)统一下单,配置JS-SDK要用到
  • mch_id(商户号, 如1230000109) 统一下单要用到
  • 商户平台设置的密钥key 统一下单要用到: 微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>密钥设置

微信支付分旧版跟新版,如何区分呢?简单来说,写这篇文章的时候,就已经是新版的了

微信支付很多坑,懂的自然懂,但我希望你不需要懂

如果不想看到下面的报错

1
{"errMsg":"chooseWXPay:fail"}

请严谨检查以下操作

  • 微信支付授权目录一定要配置到最后一层

例如调用微信支付的页面url为

1
http://portal.deepexi.top/moby-mobile/index.html#/payment-method

则支付授权目录为

1
http://portal.deepexi.top/moby-mobile/
  • 后台参与生成签名的有appId, timeStamp, nonceStr, package, signType
  • 后台生成chooseWXPay的签名时,timestamp的s要大写,即timeStamp;appid的i也要大写,即appId

虽然前端调用JS-SDK时是这样的

1
2
3
4
5
6
7
8
9
wx.chooseWXPay({
timestamp: '', // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '', // 支付签名随机串,不长于 32 位
package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '', // 支付签名
success: res => {
}
})

用微信web开发者工具观察,我发现chooseWXPay的入参timestamp自动变成了timeStamp,对此我只能呵呵了

一般而言,是先生成业务订单,再调用业务支付接口,业务后台调用微信后台进行统一下单,并返回微信JS-SDK需要的签名及各种参数,示例代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 调用业务支付接口
let resp = await this.$axios.$post(wxPayUrl, {
data: {
openId: 'openId', // 用于业务后台调用统一下单接口,该接口要求必传用户openid
orderAmount: 1, // 分
orderDesc: 'orderDesc'
orderNo: 'orderNo_'
}
})

// 利用后台返回的参数,调用微信支付
wx.chooseWXPay({
timestamp: resp.timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: resp.nonceStr, // 支付签名随机串,不长于 32 位
package: resp.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: resp.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: resp.sign, // 支付签名
success: res => {
}
})

调试

强烈建议第一次对接的时候,微信JS-SDK配置时开启debug模式,并下载微信web开发者工具观察网络请求

同时需要在公众平台–>开发者中心–>开发者工具, web开发者工具中绑定你的微信帐号

微信公众号支付签名校验工具

参考

网页授权

微信JS-SDK开发文档

微信web开发者工具

Fork me on GitHub