本文介绍微信公众号的JSAPI支付方式:
用大白话倒着说:
- 微信支付,最终要实现的是拉起微信支付jsapi提示用户输入密码支付这笔订单;
- 拉起微信支付jsapi需要的参数有公众号id,时间戳,随机字符串,订单详情扩展字符串,签名方式,签名⑥个;
- 订单详情扩展字符串是统一下单接口返回的prepay_id
- 在支付之前需要后端先调用统一下单接口向微信下一笔订单,将返回的订单号告诉前端
- 后端要下单需要先知道为那个用户下单,即需要用户唯一标识openId
- 要获取openid又需要code,获取code需要前端引导用户进行授权操作;
一个最简单的公众号网页支付流程为:用户进入公众号=>引导用户授权=>将code传给后端=>后端用code获取openid=>后端下单=>告诉我们订单号=>拉起微信支付jsapi完成支付;
微信支付业务流程时序图

一. 场景介绍:
(商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程)
- 商户下发图文消息或者通过自定义菜单吸引用户点击进入商户网页;
- 进入商户网页,用户选择购买,完成选购流程;
- 调起微信支付控件,用户开始输入支付密码;
- 密码验证通过,支付成功。商户后台得到支付成功的通知;
- 返回商户页面,显示购买成功。该页面由商户自定义;
- 微信支付公众号下发支付凭证;
- 商户公众号下发消息,提示发货成功。该步骤可选;
二. 交互细节:
- 用户打开商户网页选购商品,发起支付,在网页通过JavaScript调用getBrandWCPayRequest接口,发起微信支付请求,用户进入支付流程
- 用户成功支付点击完成按钮后,商户的前端会收到JavaScript的返回值。商户可直接跳转到支付成功的静态页面进行展示
- 商户后台收到来自微信开放平台的支付成功回调通知,标志该笔订单支付成功。
三. 支付流程图:
四.前端代码:
1.引导用户进入静默授权页面(回调链接一定要urlEncode,不然识别不出)
mounted() {
window.onload = function () {
window.location.href =
"https://open.weixin.qq.com/connect/oauth2/authorize?" +
"appid=xxxxxxxxx" +
"&redirect_uri=https%3A%2F%2Fxxx.xxx.xxx?" +
"&response_type=code" +
"&scope=snsapi_base" +
"&state=state";
}
2.进入支付页面,请求接口,通过code换取openId:
mounted(){
this.code = this.$route.query.code;
},
getWeiXinData() {
getWeiXinOpenId({code: this.code}).then((res) => {
if (res.code === 1) {
this.openId = res.data.openId;
} else {
this.$message({
type: 'error',
message: res.msg
})
}
})
},
3.调用支付接口成功后,调用微信服务窗进行支付:
pay(this.obj).then((res) => {
this.data=JSON.stringify(res.data)
var { data , code} = res.data
if(code == "1"){
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{
"appId":'xxx', //公众号名称,由商户传入
"timeStamp":data.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr":data.nonceStr, //随机串
"package":data.package,
"signType":data.signType, //微信签名方式:
"paySign":data.paySign //微信签名
},
function(res){
if(res.err_msg=="get_brand_wcpay_request:cancel" ){
alert('已取消支付')
}
});
}).catch(e=>{
console.log(e);
})
五,后端代码:
1.根据code换取openId
@GetMapping(value = "/getWeiXinOpenId")
public Result getWeiXinOpenId(String code) {
String requestUrl = url.replace("APPID",appId ).replace("SECRET" ,secret).replace("CODE", code);
String result = HttpServletUtils.get(requestUrl);
JSONObject jsonObject = JSONObject.parseObject(result);
String openId = jsonObject.getString("openid");
System.out.println(openId);
return success(openId);
}
2.下单接口:
@RequestMapping(value = "/pay", method = RequestMethod.POST)
public Result pay(@RequestBody PayBean bean) {
if (bean == null){
return failure("支付失败! 参数异常!");
}
log.info("支付请求参数: " + bean.toString());
JSONObject jsonObject = service.pay(bean);
if (jsonObject.get("code").equals("0")){
return success(jsonObject.get("info"));
}
return failure(jsonObject.get("info").toString());
}
3.支付回调接口:
@RequestMapping(value = "/notify", method = RequestMethod.POST)
public String notify(HttpServletRequest req){
try {
req.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String resString = XmlUtils.parseRequst(req);
return service.notify(resString);
}
六.微信公众号和商户平台的配置信息:
- 申请公众号:
微信公众号支付流程 -
授权回调页面域名:
接口权限-网页账号-获取用户基本信息
微信公众号支付流程 微信公众号支付流程 -
公众号支付支付目录
商户平台–>产品中心–>开发配置
微信公众号支付流程 -
ip白名单
开发–>基本配置–>IP白名单
微信公众号支付流程 5.设置支付密钥app_key
帐户中心——API安全——设置API密钥
微信公众号支付流程