继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

完美解决微信支付一个app多个签名,多个包名的问题

紫衣仙女
关注TA
已关注
手记 231
粉丝 71
获赞 334

h5支付的资料还真叫个少,不过找到一个好的方式,按着大神的步骤去实现还真就ok了,话不多说,开始准备吧

看一下官方文档还是很必要的,知道必不可少的参数是什么:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1

微信支付的坑很多,特别在平台的设置上

首先需要APPID,微信支付商户号mch_id,API密钥key,Appsecret(secret),说明在这里https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=3_1

然后设置授权域名,在接口设置中就能找到,包括js接口安全域名和网页授权域名:




这个点进去之后会看到最下面两个:js接口安全域名,这个可以设置三个,就是填写你访问页面的域名即可


下面这个是网页授权回调域名,用于你支付完毕后回调的域名,将下载的文件放到服务器的根路径,确保可以访问,我是放在tomcat的webapp中

设置的域名要备案



然后设置支付域名,设置路径:商户平台-->产品中心-->开发配置中设置域名,

如果是公众号支付就设置对应的,要注意的是公众号支付授权域名为请求的前一级,比如你要请求http://xxx/wx/abc,那么你就设置http://xxx/wx即可

h5支付设置h5域名就行,不用后缀,直接写你要设置的域名


partnerkey需要在API中设置,需要安装证书,这个根据提示安装即可,自行设置32位partnerkey


我用的是一个大神的IJPay的springboot版,写成自己的SpringMVC版,后续都会给链接

主要用的的是封装的jar,现在maven库中已经有了,用0.8版本以上的吧,这样jdk兼容问题已经解决



着手代码


  1. public static WxPayApiConfig getApiConfig() {  

  2.         return WxPayApiConfig.New()  

  3.                        .setAppId(appID)  

  4.                        .setMchId(mchID)  

  5.                        .setPaternerKey(partnerKey)  

  6.                        .setPayModel(WxPayApiConfig.PayModel.BUSINESSMODEL);  

  7.     }  





  1.   


  1. /**  

  2.      * 微信H5 支付--------------------好使  

  3.      * 注意:必须再web页面中发起支付且域名已添加到开发配置中  

  4.      */  

  5.     @RequestMapping(value ="/pay.do",method = {RequestMethod.POST,RequestMethod.GET})  

  6.     public void wapPay(HttpServletRequest request,HttpServletResponse response){  

  7.         System.out.println("--pay start--");  

  8.                 String notify_url = "https://你的域名/pay_notify.do";//这是回调地址,方法在下面  

  9.         //获取ip  


  1.     String ip = IpKit.getRealIp(request);  

  2.     if (com.jpay.ext.kit.StrKit.isBlank(ip)) {  

  3.         ip = "127.0.0.1";  

  4.     }  

  5.       

  6.     H5ScencInfo sceneInfo = new H5ScencInfo();  

  7.       

  8.     H5 h5_info = new H5();  

  9.     h5_info.setType("Wap");  

  10.     //此域名必须在商户平台--"产品中心"--"开发配置"中添加  

  11.       

  12.     h5_info.setWap_url("http://www.xxx.com");  

  13.     h5_info.setWap_name("公司官网");  

  14.     sceneInfo.setH5_info(h5_info);  

  15.     WxPayApiConfig wxPayApiConfig=getApiConfig();  

  16.     Map<String, String> params=WxPayApiConfig.New()  

  17.                                        .setAppId(appID)  

  18.                                        .setMchId(mchID)  

  19.                                        .setBody("H5支付测试")  

  20.                                        .setSpbillCreateIp(ip)  

  21.                                        .setTotalFee("520")  

  22.                                        .setTradeType(WxPayApi.TradeType.MWEB)  

  23.                                        .setNotifyUrl(notify_url)  

  24.                                        .setPaternerKey(partnerKey)  

  25.                                        .setOutTradeNo(String.valueOf(System.currentTimeMillis()))  

  26.                                        .setSceneInfo("{\"h5_info\": {\"type\":\"IOS\",\"app_name\": \"mtgg\",\"package_name\": \"com.tencent.tmgp.sgame\"}}")  

  27.                                        .setAttach("H5支付测试")  

  28.                                        .build();  

  29.     String xmlResult = WxPayApi.pushOrder(false,params);  

  30.     Map<String, String> result = PaymentKit.xmlToMap(xmlResult);  

  31.     //返回结果  

  32.     String return_code = result.get("return_code");  

  33.     String return_msg = result.get("return_msg");  

  34.     if (!PaymentKit.codeIsOK(return_code)) {  

  35.         log.error("return_code>"+return_code+" return_msg>"+return_msg);  

  36.         throw new RuntimeException(return_msg);  

  37.     }  

  38.     String result_code = result.get("result_code");  

  39.     if (!PaymentKit.codeIsOK(result_code)) {  

  40.         log.error("result_code>"+result_code+" return_msg>"+return_msg);  

  41.         throw new RuntimeException(return_msg);  

  42.     }  

  43.     // 以下字段在return_code 和result_code都为SUCCESS的时候有返回  

  44.       

  45.     String prepay_id = result.get("prepay_id");  

  46.     String mweb_url = result.get("mweb_url");  

  47.       

  48.     log.info("prepay_id:"+prepay_id+" mweb_url:"+mweb_url);  

  49.     try {  

  50.         response.sendRedirect(mweb_url);  

  51.     } catch (IOException e) {  

  52.         e.printStackTrace();  

  53.     }  

  54. }  

先给出H5ScencInfo


  1. package com.mtgg.entity;  

  2.   

  3. import com.jfinal.kit.JsonKit;  

  4.   

  5.   

  6. /**  

  7.  * @author Javen  

  8.  */  

  9. public class H5ScencInfo {  

  10.     private H5 h5_info;  

  11.       

  12.     public H5 getH5_info() {  

  13.         return h5_info;  

  14.     }  

  15.       

  16.     public void setH5_info(H5 h5_info) {  

  17.         this.h5_info = h5_info;  

  18.     }  

  19.       

  20.       

  21.     @Override  

  22.     public String toString() {  

  23.         return JsonKit.toJson(h5_info);  

  24.     }  

  25.       

  26.       

  27.     public static class H5{  

  28.         private String type;  

  29.         private String app_name;  

  30.         private String bundle_id;  

  31.         private String package_name;  

  32.         private String wap_url;  

  33.         private String wap_name;  

  34.         public String getType() {  

  35.             return type;  

  36.         }  

  37.         public void setType(String type) {  

  38.             this.type = type;  

  39.         }  

  40.         public String getApp_name() {  

  41.             return app_name;  

  42.         }  

  43.         public void setApp_name(String app_name) {  

  44.             this.app_name = app_name;  

  45.         }  

  46.         public String getBundle_id() {  

  47.             return bundle_id;  

  48.         }  

  49.         public void setBundle_id(String bundle_id) {  

  50.             this.bundle_id = bundle_id;  

  51.         }  

  52.         public String getPackage_name() {  

  53.             return package_name;  

  54.         }  

  55.         public void setPackage_name(String package_name) {  

  56.             this.package_name = package_name;  

  57.         }  

  58.         public String getWap_url() {  

  59.             return wap_url;  

  60.         }  

  61.         public void setWap_url(String wap_url) {  

  62.             this.wap_url = wap_url;  

  63.         }  

  64.         public String getWap_name() {  

  65.             return wap_name;  

  66.         }  

  67.         public void setWap_name(String wap_name) {  

  68.             this.wap_name = wap_name;  

  69.         }  

  70.     }  

  71. }  



注意notify_url要保证能够访问,用域名访问

最后发送mweb_url就可以打开微信进行支付了

给出支付成功的返回


  1.   

  1. @RequestMapping(value = "/pay_notify.do",method={RequestMethod.POST,RequestMethod.GET})  

  2.     @ResponseBody  

  3.     public void pay_notify(HttpServletRequest request,HttpServletResponse response) {  

  4.         // 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7  

  5.         System.out.println("---------------支付回调----------------");  

  6.         String xmlMsg = HttpKit.readData(request);  

  7.         System.out.println("pay notice---------"+xmlMsg);  

  8.         Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);  

  9. //      String appid  = params.get("appid");  

  10. //      //商户号  

  11. //      String mch_id  = params.get("mch_id");  

  12.         String result_code  = params.get("result_code");  

  13. //      String openId      = params.get("openid");  

  14. //      //交易类型  

  15. //      String trade_type      = params.get("trade_type");  

  16. //      //付款银行  

  17. //      String bank_type      = params.get("bank_type");  

  18. //      // 总金额  

  19.         String total_fee     = params.get("total_fee");  

  20.         total_fee = total_fee.substring(0,total_fee.length()-2);  

  21. //      //现金支付金额  

  22. //      String cash_fee     = params.get("cash_fee");  

  23. //      // 微信支付订单号  

  24. //      String transaction_id      = params.get("transaction_id");  

  25. //      // 商户订单号  

  26. //      String out_trade_no      = params.get("out_trade_no");  

  27. //      // 支付完成时间,格式为yyyyMMddHHmmss  

  28. //      String time_end      = params.get("time_end");  

  29.           

  30.         /////////////////////////////以下是附加参数///////////////////////////////////  

  31.           

  32.         String account      = params.get("attach");  

  33.         System.out.println("回调total_fee-->"+total_fee);  

  34.         System.out.println("回调account-->"+account);  

  35. //      String fee_type      = params.get("fee_type");  

  36. //      String is_subscribe      = params.get("is_subscribe");  

  37. //      String err_code      = params.get("err_code");  

  38. //      String err_code_des      = params.get("err_code_des");  

  39.         // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态  

  40.         // 避免已经成功、关闭、退款的订单被再次更新  

  41. //      Order order = Order.dao.getOrderByTransactionId(transaction_id);  

  42. //      if (order==null) {  

  43.         String resXml = "";  

  44.         WxPayApiConfigKit.setThreadLocalWxPayApiConfig(getApiConfig());  

  45.         if(PaymentKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPaternerKey())){  

  46.             if (("SUCCESS").equals(result_code)) {  

  47.                 // TODO 根据商户订单号更改押金状态  

  48.                 System.out.println("成功,存储");  

  49.                   

  50.                 resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  

  51.                         + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  

  52.                   

  53.             } else {  

  54.                 //TODO FAIL支付失败  

  55.                 log.debug("支付失败的回调消息");  

  56.                 resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  

  57.                         + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  

  58.   

  59.             }  

  60.             BufferedOutputStream out = null;  

  61.             try {  

  62.                 out = new BufferedOutputStream(  

  63.                         response.getOutputStream());  

  64.                 out.write(resXml.getBytes());  

  65.                 out.flush();  

  66.                 out.close();  

  67.             } catch (Exception e) {  

  68.                 e.printStackTrace();  

  69.             }  

  70.         }  

  71. //      }  

  72.   

  73.     }  



这里需要注意最后的xml.put(),return PaymentKit.toXml(xml)一定要返回给微信,SUCCESS表示商户接收通知成功并校验成功,这样微信才会知道商户支付成功,否则会不断通知,这样就会重复处理数据,这个错误是致命的


上面回调我改了一下,可以做到闭嘴,不会重复通知




下面就是测试调起微信支付




常见错误:

1、网络环境未能通过安全验证,请稍后再试(IP改变导致的) 
2、商家参数格式有误,请联系商家解决(H5支付的referer为空导致) 
3、商家存在未配置的参数,请联系商家解决(H5支付的域名问题) 
4、支付请求已失效,请重新发起支付(有效期为5分钟) 

5、请在微信外打开订单,进行支付(H5支付不能直接在微信客户端内调起)


我遇到过一次获取code时回调了两次错误,因为code只能用一次,第二次就失效了网上说什么的都有,谁知道怎么完全解决可以留言,感谢

我的demo地址:注意回调不用demo中的,用这篇文档的回调方式,可以闭嘴(包括公众号支付):http://download.csdn.net/download/goligory/10044575

借鉴:http://blog.csdn.net/zyw_java/article/details/77507835,感兴趣可以看他的更多相关支付


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP