微信公众号支付H5调用支付详解

最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验。

一、配置公众号微信支付

需要我们配置微信公众号支付地址和测试白名单。

比如:支付JS页面的地址为 http://www.xxx.com/shop/pay/

那此处配置www.xxx.com/shop/pay/

二、开发流程

借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/doc/api/index.PHP?chapter=7_4),我们需要开发的为红色标记出的。如下:

三、向微信服务器端下订单

调用统一下单接口,这样就能获取微信支付的prepay_id(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1)。

在调用该接口前有几个字段是H5支付必须填写的openid

3.1 获取openid

可以通过网页授权形式(http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html)

在微信中发送如下链接

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=要跳转的下订单的url&response_type=code&scope=snsapi_base&state=123#wechat_redirect

3.2 下订单获取prepay_id

代码如下,实际上是通过post发送一个xml 文件,获取微信服务器端发送过来的prepay_id。

[java]  view plain copy
  1. import java.io.ByteArrayInputStream;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.UnsupportedEncodingException;
  5. import java.util.Date;
  6. import java.util.HashMap;
  7. import java.util.Iterator;
  8. import java.util.Map;
  9. import java.util.Map.Entry;
  10. import java.util.Random;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import org.apache.commons.codec.digest.DigestUtils;
  14. import org.springframework.stereotype.Controller;
  15. import org.springframework.web.bind.annotation.RequestMapping;
  16. import org.xmlpull.v1.XmlPullParser;
  17. import org.xmlpull.v1.XmlPullParserException;
  18. import org.xmlpull.v1.XmlPullParserFactory;
  19. import com.fasterxml.jackson.databind.JsonNode;
  20. import com.gson.oauth.Oauth;
  21. import com.gson.oauth.Pay;
  22. import com.gson.util.HttpKit;
  23. import com.sy.util.DatetimeUtil;
  24. import com.sy.util.JsonUtil;
  25. @Controller
  26. @RequestMapping("/pay")
  27. public class WXPayController {
  28. @RequestMapping(value = "wxprepay.do")
  29. public void jspay(HttpServletRequest request, HttpServletResponse response, String callback) throws Exception {
  30. // 获取openid
  31. String openId = SessionUtil.getAtt(request, "openId");
  32. if (openId == null) {
  33. openId = getUserOpenId(request);
  34. }
  35. String appid = "wx16691fcb0523c1a4";
  36. String paternerKey = "ININGFENG1234567fdfwfdfd1ss234567";
  37. String out_trade_no = getTradeNo();
  38. Map<String, String> paraMap = new HashMap<String, String>();
  39. paraMap.put("appid", appid);
  40. paraMap.put("attach", "测试");
  41. paraMap.put("body", "测试购买支付");
  42. paraMap.put("mch_id", "10283271");
  43. paraMap.put("nonce_str", create_nonce_str());
  44. paraMap.put("openid", openId);
  45. paraMap.put("out_trade_no", out_trade_no);
  46. paraMap.put("spbill_create_ip", getAddrIp(request));
  47. paraMap.put("total_fee", "1");
  48. paraMap.put("trade_type", "JSAPI");
  49. paraMap.put("notify_url", "http://www.xxx.co/bank/page/wxnotify");
  50. String sign = getSign(paraMap, paternerKey);
  51. paraMap.put("sign", sign);
  52. // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
  53. String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
  54. String xml = ArrayToXml(paraMap);
  55. String xmlStr = HttpKit.post(url, xml);
  56. // 预付商品id
  57. String prepay_id = "";
  58. if (xmlStr.indexOf("SUCCESS") != -1) {
  59. Map<String, String> map = doXMLParse(xmlStr);
  60. prepay_id = (String) map.get("prepay_id");
  61. }
  62. Map<String, String> payMap = new HashMap<String, String>();
  63. payMap.put("appId", appid);
  64. payMap.put("timeStamp", create_timestamp());
  65. payMap.put("nonceStr", create_nonce_str());
  66. payMap.put("signType", "MD5");
  67. payMap.put("package", "prepay_id=" + prepay_id);
  68. String paySign = getSign(payMap, paternerKey);
  69. payMap.put("pg", prepay_id);
  70. payMap.put("paySign", paySign);
  71. WebUtil.response(response, WebUtil.packJsonp(callback, JsonUtil.warpJsonNodeResponse(JsonUtil.objectToJsonNode(payMap)).toString()));
  72. }
  73. /**
  74. * map转成xml
  75. *
  76. * @param arr
  77. * @return
  78. */
  79. public String ArrayToXml(Map<String, String> arr) {
  80. String xml = "<xml>";
  81. Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
  82. while (iter.hasNext()) {
  83. Entry<String, String> entry = iter.next();
  84. String key = entry.getKey();
  85. String val = entry.getValue();
  86. xml += "<" + key + ">" + val + "</" + key + ">";
  87. }
  88. xml += "</xml>";
  89. return xml;
  90. }
  91. // 获取openId
  92. private String getUserOpenId(HttpServletRequest request) throws Exception {
  93. String code = request.getParameter("code");
  94. if (code == null) {
  95. String openId = request.getParameter("openId");
  96. return openId;
  97. }
  98. Oauth o = new Oauth();
  99. String token = o.getToken(code);
  100. JsonNode node = JsonUtil.StringToJsonNode(token);
  101. String openId = node.get("openid").asText();
  102. return openId;
  103. }
  104. private String create_nonce_str() {
  105. String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  106. String res = "";
  107. for (int i = 0; i < 16; i++) {
  108. Random rd = new Random();
  109. res += chars.charAt(rd.nextInt(chars.length() - 1));
  110. }
  111. return res;
  112. }
  113. private String getAddrIp(HttpServletRequest request){
  114. return request.getRemoteAddr();
  115. }
  116. private String create_timestamp() {
  117. return Long.toString(System.currentTimeMillis() / 1000);
  118. }
  119. private String getTradeNo(){
  120. String timestamp = DatetimeUtil.formatDate(new Date(), DatetimeUtil.DATETIME_PATTERN);
  121. return "HZNO" + timestamp;
  122. }
  123. private String getSign(Map<String, String> params, String paternerKey )
  124. throws UnsupportedEncodingException {
  125. String string1 = Pay.createSign(params, false);
  126. String stringSignTemp = string1 + "&key=" + paternerKey;
  127. String signValue = DigestUtils.md5Hex(stringSignTemp).toUpperCase();
  128. return  signValue;
  129. }
  130. private Map<String, String> doXMLParse(String xml)
  131. throws XmlPullParserException, IOException {
  132. InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
  133. Map<String, String> map = null;
  134. XmlPullParser pullParser = XmlPullParserFactory.newInstance()
  135. .newPullParser();
  136. pullParser.setInput(inputStream, "UTF-8"); // 为xml设置要解析的xml数据
  137. int eventType = pullParser.getEventType();
  138. while (eventType != XmlPullParser.END_DOCUMENT) {
  139. switch (eventType) {
  140. case XmlPullParser.START_DOCUMENT:
  141. map = new HashMap<String, String>();
  142. break;
  143. case XmlPullParser.START_TAG:
  144. String key = pullParser.getName();
  145. if (key.equals("xml"))
  146. break;
  147. String value = pullParser.nextText();
  148. map.put(key, value);
  149. break;
  150. case XmlPullParser.END_TAG:
  151. break;
  152. }
  153. eventType = pullParser.next();
  154. }
  155. return map;
  156. }
  157. }

四、H5支付

H5支付其实很简单,只需要调用微信内嵌浏览器的js方法就行(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=7_7)

[plain]  view plain copy
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
  2. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
  3. <%
  4. String path = request.getContextPath();
  5. String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
  6. %>
  7. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  8. <html>
  9. <head>
  10. <meta charset="utf-8" />
  11. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
  12. <meta name="apple-mobile-web-app-capable" content="yes" />
  13. <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  14. <meta name="format-detection" content="telephone=no" />
  15. <title>测试支付</title>
  16. <link href="../css/css.css?v=1.0" rel="stylesheet" type="text/css">
  17. </head>
  18. <body>
  19. <div class="index_box">
  20. <div class="apply_name">微信js支付测试</div>
  21. <div class="branch_con">
  22. <ul>
  23. <li><span class="name">测试支付信息</span></li>
  24. </ul>
  25. <p class="cz_btn"><a href="javascript:pay();" class="btn_1">立即支付</a></p>
  26. </div>
  27. </div>
  28. <script type="text/javascript" src="../js/zepto.min.js"></script>
  29. <script type="text/javascript" src="../js/common.js"></script>
  30. <script type="text/javascript">
  31. var appId = urlparameter("appId");
  32. var timeStamp = urlparameter("timeStamp");
  33. var nonceStr = urlparameter("nonceStr");
  34. var pg = urlparameter("pg");
  35. var signType = urlparameter("signType");
  36. var paySign = urlparameter("paySign");
  37. function onBridgeReady(){
  38. WeixinJSBridge.invoke(
  39. 'getBrandWCPayRequest', {
  40. "appId" : appId,     //公众号名称,由商户传入
  41. "timeStamp": timeStamp,         //时间戳,自1970年以来的秒数
  42. "nonceStr" : nonceStr, //随机串
  43. "package" : "prepay_id=" + pg,
  44. "signType" : signType,         //微信签名方式:
  45. "paySign" : paySign    //微信签名
  46. },
  47. function(res){
  48. if(res.err_msg == "get_brand_wcpay_request:ok" ) {
  49. alert("支付成功");
  50. }     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
  51. }
  52. );
  53. }
  54. function pay(){
  55. if (typeof WeixinJSBridge == "undefined"){
  56. if( document.addEventListener ){
  57. document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
  58. }else if (document.attachEvent){
  59. document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
  60. document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
  61. }
  62. }else{
  63. onBridgeReady();
  64. }
  65. }
  66. </script>
  67. </body>
  68. </html>

效果如下

转载于:http://blog.csdn.net/u014351782/article/details/52186932

微信支付一 :公众号支付1相关推荐

  1. php微信公众号支付实例教程,php微信支付之公众号支付功能

    这篇文章主要为大家详细介绍了php微信支付之公众号支付功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 网上的很多PHP微信扫码支付接入教程都颇为复杂,且需要配置和引入较多的文件,本人通过整理后 ...

  2. 微信支付、公众号支付、微信APP支付教程

    这两天有朋友问我微信支付的一些事情,我就抽了点时间整理了一下微信支付相关的一些东西,在这里分享给大家,希望能帮助大家少走弯路. 微信支付分为APP支付和公众号支付两大类,其中公众号支付又分为(公众号支 ...

  3. 微信支付 php详解,微信支付之公众号支付详解

    本文主要和大家分享微信支付之公众号支付详解,随着微信支付的流行,大多产品都开发了自己的公众号.小程序等,产品的营销需要支付的支撑,最近做了个微信公号号支付,采坑无数,今天给大家分享一下,希望能帮助到大 ...

  4. APP支付和公众号支付区别在哪?

    PP支付与公众号支付容易搞混淆,尤其对于一些半专业的外行人来说,傻傻分不清. 随着移动支付的盛行,或者说随着微信社交产品的全民普及,再加上消费者被一轮又一轮的支付大战烧脑,再不懂支付的也都了解那么丁点 ...

  5. 什么是APP支付和公众号支付

    APP支付与公众号支付容易搞混淆,尤其对于一些半专业的外行人来说,傻傻分不清. 随着移动支付的盛行,或者说随着微信社交产品的全民普及,再加上消费者被一轮又一轮的支付大战烧脑,再不懂支付的也都了解那么丁 ...

  6. 微信支付(公众号支付)微信公众平台开发教程(5)

    简介 Senparc.Weixin SDK 是由盛派网络(Senparc)团队自主研发的针对微信各模块的 开发套件(C#SDK), 已全面支持微信公众号.微信支付.企业号.开放平台.JSSDK.摇一摇 ...

  7. 【微信开发】---- 公众号支付

    公众号支付就是在微信里面的H5页面唤起微信支付,不用扫码即可付款的功能.做这个功能首先要明确的就是,只有和商户号mch_id匹配的appid才能成功支付.商户号在注册成功的时候就会将相关信息发送到邮箱 ...

  8. 微信h5支付和公众号支付、支付宝h5支付

    1.微信h5支付: 首先是支付参数的构建,这个需要通过后台进行组装,后台会跟微信进行数据的交互,而你所需要做的是拿到返回的数据,然后传递给微信的JSSDK,由微信的JSSDK进行后续操作,比如说先跳转 ...

  9. 微信支付之公众号支付

    经过近一周的敲代码,终于把公众号支付和H5支付实现完成并测试通过,特此分享一些流程,一方面自己记录另一方面给新入门的一点思路 [本文介绍普通商户的公众号支付] 一.基本信息和配置 公众号支付的前提是要 ...

  10. 微信H5支付、非微信H5支付、公众号支付、小程序支付

    文章目录 前言 一.微信H5支付和非微信H5支付 二.公众号支付 三.小程序支付 总结 前言 最近公司又要搞微信支付,大体上就是把app上VIP那一套内容但做成网页版,更方便用户去购买vip,老板就让 ...

最新文章

  1. 找出最接近的相似串(DP思想)
  2. Hibernate Session的Flush模式
  3. 刷脸秒入仓,阿里云云盾实人认证助力心怡科技迎战双11
  4. 云数据库·ApsaraDB 产品6月刊
  5. julia自然常数_Julia中的Sys.KERNEL常数
  6. (36)FPGA打N拍设计(第8天)
  7. DB2计划三招“破甲” IBM在华能否得偿所愿
  8. asp.net中后台javaScrip的使用
  9. iOS开发 ☞ 系统自带字体
  10. coap 返回版本信息_CoAP协议浅析
  11. NXP JN5169使用UART发送数据
  12. 用ftp上传服务器文件大小,ftp服务器上传文件大小
  13. Python爬虫--- 1.5 爬虫实践: 获取百度贴吧内容
  14. self.跟self-什么区别?
  15. 前端如何保存图片?并在相册中查看。
  16. 面渣逆袭:RocketMQ二十三问
  17. hdu4966 朱刘算法
  18. 嵌入式开发(S5PV210)——u-boot的头文件包含问题
  19. 空间射线与三角形相交算法的两种实现
  20. 基于USB转接卡的测试工装

热门文章

  1. 简单典型二阶系统_微波战术通信系统空域抗干扰方法综述
  2. 弧度的定义? 180度(角度)=3.14(3.14弧度)
  3. cookie注入原理详解
  4. 在matlab下安装spm工具
  5. C++ QT有道翻译 爬虫 分析 破解
  6. Flutter | 和小老弟一起玩转Widget
  7. 商场管理系统毕业设计
  8. 发现电脑屏幕总是不自动关闭?看看你是否打开了这些程序……
  9. Scoop包管理工具
  10. IDEA+MySQL+JavaFX之通讯录系统