微信公众号支付爬坑总结
来源:互联网 发布:联通网络报修电话 编辑:程序博客网 时间:2024/06/15 14:24
场景介绍:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
开发步骤:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3
业务流程时序图:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4
流程梳理:
- 获取用户授权: -> code -> openid
- 统一支付下单:组参 -> sign -> 调用统一支付下单接口 -> prepay_id
- 唤起微信内置支付页面:组参 -> sign -> js页面唤起
- 获取openid:
- 官方文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN
- js页面请求获取 code:
- 配置:
- 请求微信链接
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
- 所需参数(5个):
- appid: 应用唯一标识,在微信开放平台提交应用审核通过后获得
- redirect_uri:微信回调路径(域名未备案不影响测试,域名未备案不影响测试,域名未备案不影响测试,重要的事情多说几遍,不要再怀疑域名的问题)
- 必须为 Get 请求
- 必须用 encodeURI(redirect_uri) 处理成百分号编码对回调路径处理(在线转换)
- 必须设置授权域名:(微信公众号平台 -> 公众号设置 -> 功能设置)
- response_type:固定值 code
- scope:应用授权作用域(拥有多个作用域用逗号(,)分隔)
- snsapi_base:隐式授权,用户无感知,仅限于获取code等基本信息。
- snsapi_login:需要用户点击确认授权,获取更多用户信息。
- state:授权请求后原样带回给第三方。
- 返回说明:
- 用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数。
- redirect_uri?code=CODE&state=STATE
- 若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数
- redirect_uri?state=STATE
- js 代码:
var url = "http://wangy0228.imwork.net/weixin/order.shtml?parkId=" + $("#parkId").val();
var appid = $("#wxappid").val();
var weixinUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + encodeURI(url) + "&response_type=code&scope=snsapi_base&state=" + plate + "#wechat_redirect";
window.location.href = encodeURI(weixinUrl);
var appid = $("#wxappid").val();
var weixinUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + encodeURI(url) + "&response_type=code&scope=snsapi_base&state=" + plate + "#wechat_redirect";
window.location.href = encodeURI(weixinUrl);
- 用code换取openid:
- 请求的微信链接:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
- 所需参数(4个):
- appid:应用唯一标识,在微信开放平台提交应用审核通过后获得
- secret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
- code:填写第一步获取的code参数
- grant_type:填写第一步获取的code参数
- 返回说明:
- access_token:接口调用凭证
- expires_in:access_token接口调用凭证超时时间,单位(秒)
- refresh_token:用户刷新access_token
- openid:授权用户唯一标识
- scope:用户授权的作用域,使用逗号(,)分隔
- unionid:当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。
正确返回样例:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
错误返回样例:
{
"errcode":40029,
"errmsg":"invalid code"
}
- 代码:
String openIdUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
HttpPost post = new HttpPost(openIdUrl); // 设置响应头信息
post.addHeader("Connection", "keep-alive");
post.addHeader("Accept", "*/*");
post.addHeader("Content-Type", "application/json");
post.addHeader("Host", "api.mch.weixin.qq.com");
post.addHeader("X-Requested-With", "XMLHttpRequest");
post.addHeader("Cache-Control", "max-age=0");
post.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
HttpResponse response = httpclient.execute(post);
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
Map<String, Object> resultMap = (Map<String, Object>) JSONObject.parse(jsonStr);
String openid = resultMap.get("openid").toString();
2、统一下单支付:
- 官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
- 网站配置:(路径为支付路径的上一级目录)
- 调用的微信统一下单支付接口:
https://api.mch.weixin.qq.com/pay/unifiedorder
- 用 SortedMap 拼参数(11个)换取 prepay_id:
- appid:微信支付分配的公众账号ID
- mch_id:微信支付分配的商户号
- nonce_str:随机字符串,长度要求在32位以内
UUID.randomUUID().toString().replace("-", "");
- body:商品简单描述
- out_trade_no:订单号
- total_fee:总金额,单位为分
- spbill_create_ip:APP和网页支付提交用户端ip
InetAddress ip = InetAddress.getLocalHost().getHostAddress();
- notify_url:异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
- trade_type:取值如下:JSAPI,NATIVE,APP等(公众号支付此值为JSAPI)
- openid:trade_type=JSAPI时(即公众号支付),此参数必传,此参数为微信用户在商户对应appid下的唯一标识。
- sign:通过签名算法计算得出的签名值
- 签名算法需要用到商户的Appsecret:( 微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->密钥设置)
/**
* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
* packageParams 为除 sign 外所有参数
*/
public String createSign(SortedMap<String, String> packageParams, String appSecret) {
StringBuffer sb = new StringBuffer();
SortedMap<String, String> treeMap = new TreeMap<>();
for (Map.Entry<String, String> entry : treeMap.entrySet()){
String k = entry.getKey();
String v = entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k)
&& !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + appSecret);
return MD5Util.MD5Encode(sb.toString(), this.charset).toUpperCase();
}
- 将以上参数组参,拼接成 xml 格式字符串,调用统一支付接口换取 prepay_id。
- 当 return_code 和 result_code 都为 SUCCESS 时返回
- trade_type:支付类型(此处返回为JSAPI)
- prepay_id:微信预支付会话标记
- code_url:无
- 其他返回参数说明见微信官方文档,此处用不到所有就不做过多分析。
3、微信内H5调起支付:
- 用微信浏览器内置对象 WeixinJSBridge 调起支付(WeixinJSBridge 在其他浏览器无法识别):
- 参数(6个):
- appId:商户id
- timeStamp:时间戳
- nonceStr:随机字符串
- package:订单扩展字段(此处为前面获取的prepay_id,格式:prepay_id=***)
- signType:签名方式(MD5)
- paySign:签名
- 返回结果:
- get_brand_wcpay_request:ok:支付成功
- get_brand_wcpay_request: cancel:用户取消支付
- get_brand_wcpay_request:fail:支付失败
- js代码:
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady(data.data);
}
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady(data.data);
}
function onBridgeReady(data) {
var total = $("#total").val();
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": data.appId, //公众号名称,由商户传入
"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:ok") {
window.location.href="${ctx}/weixin/success.shtml?total=" + total;// 支付成功跳转到自定义页面
} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
alert("用户取消支付!");
} else {
alert("支付失败!");
}
});
var total = $("#total").val();
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": data.appId, //公众号名称,由商户传入
"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:ok") {
window.location.href="${ctx}/weixin/success.shtml?total=" + total;// 支付成功跳转到自定义页面
} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
alert("用户取消支付!");
} else {
alert("支付失败!");
}
});
};
阅读全文
0 0
- 微信公众号支付爬坑总结
- 微信公众号支付总结
- 微信公众号支付开发总结
- 微信公众号支付总结
- 微信公众号支付支付验证签名失败及公众号支付总结
- 微信公众号支付
- 微信公众号支付
- 微信公众号支付
- 微信公众号支付
- 微信公众号支付
- 微信公众号支付
- 微信公众号支付
- 支付--微信公众号
- 微信公众号支付。
- 微信公众号支付
- 微信公众号支付
- 微信公众号支付
- 微信公众号支付开发流程总结
- 神经网络与深度学习(第一章)(一)
- app开发流程、线程池
- 随机森林random forest及python实现
- triplet loss (原理 + 实现)
- java finalize方法总结、GC执行finalize的过程
- 微信公众号支付爬坑总结
- 【SSH网上商城】问题是老大
- codeforces 69A Young Physicist
- 堆和栈的区别
- 航空遥感图像(Aerial Images)目标检测数据集汇总
- C++ Vector遍历的几种方式()
- 程序编译-汇编-链接的理解04-可执行文件概述
- vue之项目目录设计
- cpu之register