功能描述:用户下单支付时可以选择微信支付,并调用微信端接口实现支付完成

微信支付的种类

  • 微信扫描二维码支付
  • 微信端吊起H5进行支付
  • 微信公众号吊起支付
  • app吊起微信支付

本篇讲的是针对微信公众号和app吊起支付的流程

首先是图文流程

模块代码

一、申请微信商户平台

这里是详细的微信开发的开发文档链接

二、进入到商户平台,设置一些需要的参数

三、前台执行ajax请求,提交到后台吊起微信支付接口。用户在前台选择想要购买的商品,点击支付按钮时,前台ajax获取商品的具体信息(id,num,name),然后请求后台的支付方法,后台执行完成后给前台返回需要的参数并跳转到微信支付页面执行输入密码操作

function wechatDoPay({
//获取商品名称,价格,商品数量
$.ajax({type:"post",url:"http://www.xyz.cn/wechatTest/wechat/unifiedorder",success:function(data){if(data.status=="success"){wx.chooseWXPay(data);
}
}
})
});wx.chooseWXPay({
timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '', // 支付签名随机串,不长于 32 位
package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '', // 支付签名
success: function (res) {
// 支付成功后的回调函数
}
});

备注:prepay_id 通过微信支付统一下单接口拿到,paySign 采用统一的微信支付 Sign 签名生成方法,注意这里 appId 也要参与签名,appId 与 config 中传入的 appId 一致,即最后参与签名的参数有appId, timeStamp, nonceStr, package, signType。

四、后台controller层代码,校验用户的登陆状态,拿着openid和前台传来的参数去service层执行微信支付的具体方法

@RequestMapping("unifiedorder")
@ResponseBody
public String unifiedorder(HttpServletRequest request, String goodsId, int countNum){//在这里做一下校验,直接校验用户有没有登录,如果没有登录,就不允许吊起下单操作//接受前台的token防止用户重复提交String openid = "";//openid是微信用户在公众号appid下的唯一用户标识JSONObject jsonObject = service.unifiedorder(openid, goodsId,countNum);jsonObject.put("status", "success");return jsonObject.toString();
}

五、后台service层

处理主要的支付业务,根据前台传来的商品id获取详细商品信息,以及购买总价格,然后吊起微信统一下单的地址,在吊起之前,需要对传递的数据进行一些操作,首先需要appid和openid,商户ID,随即生成的字符串等等,还要设置一下支付完成后,微信如何通知后台管理用户已经完成了支付的路径,这些参数设置号以后,将它们转化成xml格式,并且调用支付接口,随后微信端返回对应的xml结果回来,我们在根据前台需要将传递回来的参数,进行json格式的转换以及paysign签名的重新生成,随后把拼接好的json字符串返回给前台

public JSONObject unifiedorder(String openid, String goodsId, int countNum) {GoodsOrder goodsOrder = new GoodsOrder();//根据用户id查询用户权限,看看用户是否是VIP//根据商品id查询出商品信息//根据商品数量和商品价格,计算出要付的价格//4、调用微信下单操作,开始执行微信下单功能//获取预支付号String out_trade_no = UUID.randomUUID().toString();//需要插入订单表的订单IDString prepayId = "";//第一次生成的预支付订单SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();//使用sortedmap给下面插入的数据进行排序parameters.put("appid", WechatUtils.appid);//微信支付分配的公众账号IDparameters.put("mch_id", WechatUtils.mch_id);//微信支付分配的商户号,注册完公众号后开通微信支付接口时给的idparameters.put("nonce_str", WechatUtils.CreateNoncestr());//随即生成的16位的字符串parameters.put("body", "我是从商品表中拿出来的商品名字");
//        parameters.put("body", goodsOrder.getId());parameters.put("out_trade_no", out_trade_no);//110 等于一块一毛钱//10000 等于一百//如果数据库存的是double类型的,价格是10.5怎么传入微信里,10.5*100=1050
//        parameters.put("total_fee", String.valueOf(goods.getPrice())+"00");parameters.put("total_fee", String.valueOf(10)+"00");//我是十块parameters.put("spbill_create_ip", WechatUtils.spbill_create_ip);//调用微信支付API的机器IPparameters.put("notify_url", WechatUtils.WECHAT_NOTIFY_URL);//支付完成后回返回后台系统的调用的请求路径parameters.put("trade_type", "JSAPI");//交易类型//生成签名的地方需要一个openid,所以把这个openid加上//openid是微信用户在公众号appid下的唯一用户标识(appid不同,则获取到的openid就不同),// 可用于永久标记一个用户,同时也是微信JSAPI支付的必传参数parameters.put("openid", openid);parameters.put("timeStamp", WechatUtils.create_timestamp());//生成时间戳//我的作用是为了生成一个签名String sign = WechatUtils.createSign(parameters);parameters.put("sign", sign);//把map类型的参数转换成xml格式的String requestXML = WechatUtils.getRequestXml(parameters);//开始请求支付接口,返回微信的订单结果String preparyIdXml = CommonUtil.httpRequestJson(WechatUtils.unifiedorder, "POST", requestXML);//把返回的订单结果转换为map类型的Map<String, String> prepayIdMap =new HashMap<String, String>();try {prepayIdMap = XMLUtil.doXMLParse(preparyIdXml);} catch (JDOMException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}if (null != prepayIdMap) {prepayId =prepayIdMap.get("prepay_id");}}

这是微信端需要的参数格式,都是以xml的形式传递

<xml><appid>wx2421b1c4370ec43b</appid><attach>支付测试</attach><body>JSAPI支付测试</body><mch_id>10000100</mch_id><detail><![CDATA[{
"goods_detail":[
{
"goods_id":"iphone6s_16G",
"wxpay_goods_id":"1001",
"goods_name":"iPhone6s 16G",
"quantity":1,
"price":528800,
"goods_category":"123456",
"body":"苹果手机"
},
{
"goods_id":"iphone6s_32G",
"wxpay_goods_id":"1002",
"goods_name":"iPhone6s 32G",
"quantity":1,
"price":608800,
"goods_category":"123789",
"body":"苹果手机"
}
]
}]]></detail><nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str><notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url><openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid><out_trade_no>1415659990</out_trade_no><spbill_create_ip>14.23.150.211</spbill_create_ip><total_fee>1</total_fee><trade_type>JSAPI</trade_type><sign>0CB01533B8C1EF103065174F50BCA001</sign></xml>

这是第二次返回的xml结果,需要我们后台进行转换以及拼接成json字符串返回给前台

<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg><appid><![CDATA[wx2421b1c4370ec43b]]></appid><mch_id><![CDATA[10000100]]></mch_id><nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str><openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid><sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign><result_code><![CDATA[SUCCESS]]></result_code><prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id><trade_type><![CDATA[JSAPI]]></trade_type></xml>

这是前台需要的参数类型,后台需要拼接成这种类似的格式,前台才能引用

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

后台controller层,负责接收微信端的回调数据,主要是解析用户有没有完成支付,并进行更进一步的业务判断和处理

@RequestMapping("wechatNotifyUrl")
@ResponseBody
public String wechatNotifyUrl(HttpServletRequest request){try {//用户发送了一条消息或关注了我的公众号,都会发一条消息,消息是流形式InputStream inStream = request.getInputStream();//把消息流转换成文本类型ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}outSteam.close();String result = new String(outSteam.toByteArray(), "UTF-8");System.out.println("result==="+result);//SAX解析xmlMap<String, String> map = null;//通过sax解析xml技术,把xml文本解析成map对象try {map = XMLUtil.doXMLParse(result);} catch (JDOMException e) {e.printStackTrace();}//必须要给微信一个回复,否则微信端会一直请求你的接口return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";}catch (Exception e){}return null;
}

这里需要注意的是,一定要给微信端返回

“<return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg>”;

这种形式的数据,不然微信端会一直调用你的后台接口确认你有没有接受到数据

总结

前台调用后台接口→后台调用微信统一下单接口,后台返回调用微信统一下单后返回的内容给前台→前台根据后台返回的内容调用微信浏览器内置JS弹出支付→支付后有两种处理 ①前台支付成功后的页面 ②微信回调url(一般处理业务逻辑)

支付的幂等性

什么是支付的幂等性?
(1)用户多次请求造成出现多个订单
(2)支付完成后,被拦截或网络不好,造成收不到回调通知或是收到了回调通知,但是这个回调通知的金额和支付信息不匹配,说明数据有问题

可以参考以下博客来进行问题的解决
https://blog.csdn.net/github_36032947/article/details/78386551
https://www.cnblogs.com/leechenxiang/p/6626629.html
https://blog.csdn.net/aly1989/article/details/52352726

项目开发之微信支付接口调用相关推荐

  1. 微信支付接口调用问题(android正常,iphone调不起)

    碰到的问题 :根据微信提供的示例代码(ASP.NET),配置好一切后, 用android微信客户端返回,调起支付接口一切正常, 但使用iphone微信客户端时,点击"立即支付"按钮 ...

  2. 微信小程序PHP 微信支付接口调用

    小程序端  js数据处理 根据官方文档配置好参数,传入服务器. /*** 微信支付接口*/wxPaymoney:function (out_trade_no, true_money){ //out_t ...

  3. 微信支付接口调用之二维码失效时间的设置

    今天解决了测试提交上来的一个bug,说是公司网站调用的二维码接口没有做超时失效处理,这种情况容易导致用户账号登出后,该二维码还是有效的,当用户扫描支付时还是能够支付成功,但是微信支付成功后调用我们配置 ...

  4. 微信支付接口调用记录

    1. totalmoney 必须是不带小数的,默认单位是分  ,如 你付款0.01元,传到后端要*100单位变为分,然后 强转整数 2. 支付异步回调,做出判断,如果订单已经处理过,就不让执行业务代码 ...

  5. 微信小程序开发实现微信支付

    微信支付是时下最流行的交易支付方法之一,潜移默化推动着无现今社会的变革.小程序作为微信上的轻应用,同时也开放微信支付的接口,可以通过转账,扫二维码支付.要完成一次具体的订单支付需要完整的支付流程,具体 ...

  6. 调用微信支付接口总结

        项目里面用到了微信支付的功能,照着文档学习了一下,这里做个总结来记录.项目用到的是anglusJS来做前端开发,我这边简化了,用的ajax进行异步的调用,然后业务也直接写在了控制层(不过不应该 ...

  7. Android_APP 微信支付接口开发

    1.首先说一下我们在开发微信支付接口的时候遇到最多和最疑惑的问题,那就是明明 appid.商户号.API密钥 都对照了好几遍确实是和自己的一样,并且也没有在Log日志中出现签名错误等信息,却始终调不起 ...

  8. 微信支付接口,提示:调用支付jsapi缺少参数: $key0$

    下面是 官方给的 帮助文档. 支付返回签名错误 注意签名参数的大小写,支付密钥key要到商户平台设置,设置的规则是32位数字与字母大小写的组合.以下链接为签名过程. (https://pay.weix ...

  9. java支付接口开发原理_java对接微信支付接口开发的过程是什么?

    java对接微信支付接口开发的过程是什么?以下是小编整理的java对接微信支付接口实现的方法和过程,有需要的朋友可以学习以下的java对接微信支付接口内容. java对接微信支付接口开发的过程是什么? ...

  10. Magento微信支付接口开发小记

    姗姗来迟的Magento微信支付接口插件 半年之前,有朋友网站需要接入微信支付,是Magento站,于是花费了近二周时间,研究微信开发文档.示例代码,并初步制作了个支付模块,不巧的是,朋友的微信支付接 ...

最新文章

  1. html如何让tr自动换行,js和css如何让table自动换行但是不是超出td?
  2. 演技之神周润发背后的故事——评影帝周润发鲜为人知的封神之路
  3. 聚焦3D地形编程第五章GeomipMapping for the CLOD
  4. pku 1486 求出二分匹配图中的必须边
  5. linux GD库安装
  6. ARM Trustzone介绍-视频学习
  7. Mysql存储级别_mysql 存储引擎分类和事务隔离级别
  8. Hadoop入门(二十二)Mapreduce的求平均值程序
  9. spring的applicationContext.xml如何自动加载
  10. lightroom手机版下载_vnc控制手机版下载,vnc控制手机版下载的使用教程
  11. Struts2知识点总结
  12. ProGuard:类混淆,类的指定函数保留
  13. JCR分区与中科院分区详解-中科院基础版和升级版详解
  14. MATLAB画图调整分辨率
  15. 国内外你知道的设计网站!给你的设计找点灵感!
  16. 心不唤物,物不至,聊聊积极心态重要性
  17. 移动终端浏览器初始设置apple-mobile-web-app-capable(转)
  18. 我所经历的Android面试|掘金技术征文
  19. 前端——js关闭页面方法
  20. 【LOJ2867】「IOI2018」高速公路收费

热门文章

  1. 教你如何玩转豆瓣(douban) 豆瓣使用入门!
  2. CrazyBox常见问题
  3. MTK(Android N)设置SDCard为默认存储
  4. 电子烟脱去糖衣后,下一步往哪走?
  5. 凯利公式(庄家必胜篇)——致放假在家的高薪程序员们
  6. 继明当时明月在:万历十五年
  7. 机器学习-sklearn第十二天——笔记
  8. Matplotlib画热力图---heatmap(逐行注释)
  9. 有关String类与StringBuffer类
  10. 网盘上传文件服务器失败原因,win10系统在百度网盘上传文件一直失败的恢复教程...