微信支付(统一下单)(自己备忘)

思路:

①将appid、mch_id、nonce_str、body、attach、out_trade_no、total_fee、spbill_create_ip、notify_url、trade_type 这些参数以键值对的形式拼接起来用MD5进行第一次签名

②拼接xml:

例如:

<xml>
   <appid>wx2421b1c4370ec43b</appid>
   <attach>支付测试</attach>
   <body>JSAPI支付测试</body>
   <mch_id>10000100</mch_id>
   <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
   <notify_url>http://wxpay.weixin.qq.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 交个  "https://api.mch.weixin.qq.com/pay/unifiedorder"  在微信 生成一个预支付订单号prepay_id

③将 appid、partner、prepay_id、nonce_str、timestamp、partnerkey、key、package  通过键值对的形式拼接,然后MD5加密处理,和第一步加密方式一样进行第二次签名

④将appid、partnerid、prepayid、package、noncestr、timestamp、sign  传给 调起微信支付功能

注:一些用到的方法

1、MD5  将map 拼接成键值对的串,然后进行加密

 1 /**
 2      * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
 3      */
 4     public String createSign(SortedMap<String, String> packageParams) {
 5         StringBuffer sb = new StringBuffer();
 6         Set es = packageParams.entrySet();
 7         Iterator it = es.iterator();
 8         while (it.hasNext()) {
 9             Map.Entry entry = (Map.Entry) it.next();
10             String k = (String) entry.getKey();
11             String v = (String) entry.getValue();
12             if (null != v && !"".equals(v) && !"sign".equals(k)
13                     && !"key".equals(k)) {
14                 sb.append(k + "=" + v + "&");
15             }
16         }
17         sb.append("key=" + this.getKey());
18         String sign = MD5Util.MD5Encode(sb.toString(), this.charset)
19                 .toUpperCase();
20         return sign;
21
22     }

2、将xml交给 "https://api.mch.weixin.qq.com/pay/unifiedorder"  解析生成 预支付订单

如果参数提交失败,会在try里的 if 中 返回  开发的时候建议打断点,我是存session ,然后返回错误信息msg

 1 /**
 2    *description:获取预支付id
 3    *@param urls
 4    *@param xmlParam
 5    *@return
 6    * @author ex_yangxiaoyi
 7    * @see
 8    */
 9   public static String getPayNo(String url,String xmlParam){
10       Subject currentUser = SecurityUtils.getSubject();
11       Session session = currentUser.getSession();
12
13       DefaultHttpClient client = new DefaultHttpClient();
14       client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
15       HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
16       String prepay_id = "";
17      try {
18          httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
19          HttpResponse response = httpclient.execute(httpost);
20          String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
21         if(jsonStr.indexOf("FAIL")!=-1){
22             session.setAttribute("error_msg", jsonStr);
23             return prepay_id;
24         }
25         Map map = doXMLParse(jsonStr);
26         prepay_id  = (String) map.get("prepay_id");
27     } catch (Exception e) {
28         // TODO Auto-generated catch block
29         e.printStackTrace();
30     }
31     return prepay_id;
32   }
33   
1     public static InputStream String2Inputstream(String str) {
2         return new ByteArrayInputStream(str.getBytes());
3     }

3、xml解析

 1 /**
 2      * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
 3      * @param strxml
 4      * @return
 5      * @throws JDOMException
 6      * @throws IOException
 7      */
 8     public static Map doXMLParse(String strxml) throws Exception {
 9         if(null == strxml || "".equals(strxml)) {
10             return null;
11         }
12
13         Map m = new HashMap();
14         InputStream in = String2Inputstream(strxml);
15         SAXBuilder builder = new SAXBuilder();
16         Document doc = builder.build(in);
17         Element root = doc.getRootElement();
18         List list = root.getChildren();
19         Iterator it = list.iterator();
20         while(it.hasNext()) {
21             Element e = (Element) it.next();
22             String k = e.getName();
23             String v = "";
24             List children = e.getChildren();
25             if(children.isEmpty()) {
26                 v = e.getTextNormalize();
27             } else {
28                 v = getChildrenText(children);
29             }
30
31             m.put(k, v);
32         }
33
34         //关闭流
35         in.close();
36
37         return m;
38     }
 1 /**
 2      * 获取子结点的xml
 3      * @param children
 4      * @return String
 5      */
 6     public static String getChildrenText(List children) {
 7         StringBuffer sb = new StringBuffer();
 8         if(!children.isEmpty()) {
 9             Iterator it = children.iterator();
10             while(it.hasNext()) {
11                 Element e = (Element) it.next();
12                 String name = e.getName();
13                 String value = e.getTextNormalize();
14                 List list = e.getChildren();
15                 sb.append("<" + name + ">");
16                 if(!list.isEmpty()) {
17                     sb.append(getChildrenText(list));
18                 }
19                 sb.append(value);
20                 sb.append("</" + name + ">");
21             }
22         }
23
24         return sb.toString();
25     }

4、微信回调函数

 1 /**
 2      * 微信支付 回调函数
 3      */
 4     @RequestMapping("/notify")
 5     @ResponseBody
 6     protected void notify(HttpServletRequest request,
 7             HttpServletResponse response) throws Exception {
 8
 9         PageData pd=new PageData();
10         logBefore(logger, "微信支付  回调函数");
11         //把如下代码贴到的你的处理回调的servlet 或者.do 中即可明白回调操作
12         logger.info("微信支付回调数据开始");
13         //示例报文
14         //String xml = "<xml><appid><![CDATA[wxb4dc385f953b356e]]></appid><bank_type><![CDATA[CCB_CREDIT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[1228442802]]></mch_id><nonce_str><![CDATA[1002477130]]></nonce_str><openid><![CDATA[o-HREuJzRr3moMvv990VdfnQ8x4k]]></openid><out_trade_no><![CDATA[1000000000051249]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[1269E03E43F2B8C388A414EDAE185CEE]]></sign><time_end><![CDATA[20150324100405]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[JSAPI]]></trade_type><transaction_id><![CDATA[1009530574201503240036299496]]></transaction_id></xml>";
15         String inputLine;
16         String notityXml = "";
17         String resXml = "";
18
19         try {
20             while ((inputLine = request.getReader().readLine()) != null) {
21                 notityXml += inputLine;
22             }
23             request.getReader().close();
24         } catch (Exception e) {
25             e.printStackTrace();
26         }
27
28         System.out.println("接收到的报文:" + notityXml);
29
30         BufferedWriter writer = new BufferedWriter(new FileWriter(new File("c:\\ResultXml.txt"),true));
31          //
32          writer.write(DateUtil.getTime()+notityXml+"\r\n");
33          writer.close();
34
35         Map m = parseXmlToList2(notityXml);
36         WxPayResult wpr = new WxPayResult();
37         wpr.setAppid(m.get("appid").toString());
38         wpr.setBankType(m.get("bank_type").toString());
39         wpr.setCashFee(m.get("cash_fee").toString());
40         wpr.setFeeType(m.get("fee_type").toString());
41         wpr.setIsSubscribe(m.get("is_subscribe").toString());
42         wpr.setMchId(m.get("mch_id").toString());
43         wpr.setNonceStr(m.get("nonce_str").toString());
44         wpr.setOpenid(m.get("openid").toString());
45         wpr.setOutTradeNo(m.get("out_trade_no").toString());
46         wpr.setResultCode(m.get("result_code").toString());
47         wpr.setReturnCode(m.get("return_code").toString());
48         wpr.setSign(m.get("sign").toString());
49         wpr.setTimeEnd(m.get("time_end").toString());
50         wpr.setTotalFee(m.get("total_fee").toString());
51         wpr.setTradeType(m.get("trade_type").toString());
52         wpr.setTransactionId(m.get("transaction_id").toString());
53
54         if("SUCCESS".equals(wpr.getResultCode())){
55             //支付成功
56             resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
57             + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
58             //修改订单状态
59             pd.put("WX_ORDER", wpr.getOutTradeNo());
60             wxPayService.editStatusByOutId(pd);
61             //保存订单信息
62             pd.put("WX_ORDER_ID", UuidUtil.get32UUID());//微信订单主键ID
63             pd.put("OPEN_ID", wpr.getOpenid());//用户的OPEN_ID
64             pd.put("MCH_ID", wpr.getMchId());//商户号
65             pd.put("NONCE_STR", wpr.getNonceStr());//随机字符串
66             pd.put("SIGN", wpr.getSign());//SIGN
67             pd.put("CASH_FEE", wpr.getCashFee());//现金支付金额
68             pd.put("TOTAL_FEE", wpr.getTotalFee());//总金额
69             pd.put("BANK_TYPE", wpr.getBankType());//付款银行
70             pd.put("TRADE_TYPE", wpr.getTradeType());//交易类型
71             pd.put("RESULT_CODE", wpr.getResultCode());//业务结果
72             pd.put("TRANSACTION_ID", wpr.getTotalFee());//微信支付订单号
73             pd.put("TIME_END", wpr.getTimeEnd());//微信支付完成时间
74             wxPayService.saveWxOrder(pd);
75         }else{
76             resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
77             + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
78         }
79
80         System.out.println("微信支付回调数据结束");
81
82         BufferedOutputStream out = new BufferedOutputStream(
83                 response.getOutputStream());
84         out.write(resXml.getBytes());
85         out.flush();
86         out.close();
87
88     }
89     

解析微信通知xml

 1 /**
 2      * description: 解析微信通知xml
 3      *
 4      * @param xml
 5      * @return
 6      * @author ex_yangxiaoyi
 7      * @see
 8      */
 9     @SuppressWarnings({ "unused", "rawtypes", "unchecked" })
10     private static Map parseXmlToList2(String xml) {
11         Map retMap = new HashMap();
12         try {
13             StringReader read = new StringReader(xml);
14             // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
15             InputSource source = new InputSource(read);
16             // 创建一个新的SAXBuilder
17             SAXBuilder sb = new SAXBuilder();
18             // 通过输入源构造一个Document
19             Document doc = (Document) sb.build(source);
20             Element root = doc.getRootElement();// 指向根节点
21             List<Element> es = root.getChildren();
22             if (es != null && es.size() != 0) {
23                 for (Element element : es) {
24                     retMap.put(element.getName(), element.getValue());
25                 }
26             }
27         } catch (Exception e) {
28             e.printStackTrace();
29         }
30         return retMap;
31     }

时间: 2024-12-18 06:27:10

微信支付(统一下单)(自己备忘)的相关文章

在.net core上,Web网站调用微信支付-统一下单接口(xml传参)一直返回错误:mch_id参数格式错误

这是 微信支付-统一下单 接口文档 一.问题描述 在调用统一下单接口时,报mch_id参数格式错误,但商户ID确实是10位数字正确的,可就是一直报这个错误 返回的错误xml如下: 二.排错过程 1.多次对比官网xml格式,确认生成的xml是否有误 2.检查生成的xml是否带有空格.字段是否拼写有误,检查生成的xml是否有缺少或多字符 官方的xml: 我开发过程中生成的xml: 对比发现,我生成的xml参数比官方的参数多了CDATA等着字符,但CDATA标签是用于说明数据不被XML解析器解析的,不

微信支付-----统一下单action

public class PayAction extends BaseAction { public String JsapiPay(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)throws Exception { PrintWriter out = response.getWriter(); //商品描述  商品或支付单简要描述 String bo

关于微信支付预下单【统一下单】“操作超时”问题

问题描述: 在微信公众号开发中时常遇到使用微信支付的情况,之前一直注意到微信支付统一下单接口响应特别慢,经常出现"操作超时"的情况,最初为解决因操作超时使用户无法一次完成支付便用了个最多3次的递归,无法一次完成支付问题是解决了但根源问题还是存在,客户端响应还是很慢. 解决方法: 如果你用的是阿里的服务器,那无疑是DNS的问题,将服务器的DNS配置为腾讯公共DNS:119.29.29.29 ,之后的速度会提升很多! 关于微信统一下单: 请访问微信支付官方文档:https://pay.we

微信JSAPI支付 统一下单 (.net后台)

交流QQ群  ASP.NET鹰组 460845632  我会倾囊相授 我们要做微信支付当配置好微信微信商户和支付配置之后我们首先应该看   https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1# 这是微信统一下单的参数,我将这个参数做成了一个数据模型 当做好这个数据模型之后仔细看一下里面那些参数是必须的,支付金额要注意,微信是按分来计算的 接下来我们就要生成签名,我这写好了个类  生成签名后 返回提交的值.....先给大家看

关于微信服务商统一下单需要注意的几个问题

1.服务商要在服务商平台-->特约商户管理中添加商户信息,审核通过后获得特约商户号和登录密码 2.对子商户进行开发配置"推荐关注"和"特约商户APPID设置"如果商户没有自己的公众号可以不填 3.支付权限-->公众号支付中要设置JSAPI支付授权目录 4.子商户的商户号sub_mch_id为必填 appid:服务商的appid mch_id:服务商商户号 key:服务商的支付秘钥   (此处需要特别注意,整个统一下单的参数中不需要子商户的key) 5.差

微信支付-公众号支付,统一下单,调起微信支付,回调验证

参考:http://www.jianshu.com/p/a172a1b69fdd http://www.jianshu.com/p/1ae0ef652f63 http://www.jb51.net/article/76110.htm http://www.tangshuang.net/2359.html http://wyong.blog.51cto.com/1115465/1692322 常见问题http://kf.qq.com/faq/140225MveaUz150413VNj6nm.htm

支付宝APP支付 统一下单 php服务端 tp5

/*支付宝第三方支付 * *生成APP支付订单信息 * @param number uid 用户id * @param string token 用户token * @param number oid 订单id * @param string title 标题 * @param string body 商品描述 * @parma float money 金额 * @param number ordernum 订单编号 */ 支付包官方文档 https://docs.open.aliyun.com

玩转小程序支付之付款(统一下单)

小程序的业务流程如下 商户系统和微信支付系统主要交互说明: 步骤1:用户在商户APP中选择商品,提交订单,选择微信支付. 步骤2:商户后台收到用户支付单,调用微信支付统一下单接口.参见[统一下单API]. 步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP.参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package.注意:package的值格式为Sign=WXPay 步骤4:商户APP调起

Android微信支付SDK开发

一.准备工作 1.开发平台及SDK下载 微信开放平台 https://open.weixin.qq.com 下载SDK 微信支付Demo下载 http://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1 2.创建应用 创建移动应用获取 AppID  AppSecret 要获取支付功能还需要开发者资质认证,300RMB/年的费用,貌似是开放平台中唯一要收费的- 3.AndroidMainfest文件修改 权限 <uses-permission

Android微信支付SDK开发笔记

一.准备工作 1.开发平台及SDK下载 微信开放平台 https://open.weixin.qq.com 下载SDK 微信支付Demo下载 http://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1 2.创建应用 创建移动应用获取 AppID  AppSecret 要获取支付功能还需要开发者资质认证,300RMB/年的费用,貌似是开放平台中唯一要收费的… 3.AndroidMainfest文件修改 权限声明: <uses-permiss