java版微信支付/查询/撤销
最近公司接入微信刷卡支付,网上根本没见到很直接的教程(可能眼拙),一直摸滚打爬,加班加点才走通,忍不了必须写一写
微信 刷卡支付/查询/撤销... 必须要有公众号然后去申请,申请自己去看文档,这里主要演示java对接代码
必要准备:
名称 | 变量名 | 示例 | 描述 |
公众账号ID | appid | wx8888888888888888 | 微信分配的公众账号ID,可在微信公众平台-->开发-->基本配置里面查看,商户的微信支付审核通过邮件中也会包含该字段值 |
商户号 | mch_id | 1900000109 | 微信支付分配的商户号 |
子商户号 | sub_mch_id | 1900000109 | 微信支付分配的子商户号,开发者模式下必填 |
证书路径 | certPath | x/xx/apiclient_cert.p12 | 本地证书 |
API密钥 | key |
dyjs3tlWXCs1eBzs5ihGrmK8w0HdvXcR |
保证key不会被泄漏。商户可根据邮件提示登录微信商户平台进行设置。也可按一下路径设置:微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->密钥设置 |
这里用SSM框架
先导入微信的SDK (SKD下载点这里)
配置一个xxx.properties
1 //这里写的数据都是乱写的,不要暴露出去 2 wechat_appid=wx888888888888 3 wechat_mch_id=19000000000190 4 wechat_sub_mch_id=19000000000191 5 wechat_certPath=D:/cert/apiclient_cert.p12 6 wechat_key=adasdfsfwADEdDWw3E344Ee32
7 wechat_httpConnectionTimeoutMs=8000
8 wechat_httpReadTimeoutMs=10000
配置微信初始化的类 WechatPayConstants.java
1 package com.test.bean; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.InputStream; 7 import java.net.InetAddress; 8 9 import org.slf4j.Logger; 10 import org.slf4j.LoggerFactory; 11 12 import com.github.wxpay.sdk.WXPayConfig; 13 //这里要实现微信的配置 14 public class WechatPayConstants implements WXPayConfig{ 15 16 public WechatPayConstants(String appId,String mchId,String subMchId, 17 String certPath,int httpConnectionTimeoutMs,int httpReadTimeoutMs,String key) throws Exception{ 18 try { 19 File file = new File(certPath); 20 InputStream certStream = new FileInputStream(file); 21 this.certData = new byte[(int) file.length()]; 22 certStream.read(this.certData); 23 certStream.close(); 24 } catch (Exception e) { 25 Logger logger = LoggerFactory.getLogger( WechatPayConstants.class); 26 logger.info("文件:"+certPath+"没找到"); 27 } 28 this.openApiDomain = openApiDomain; 29 this.appId = appId; 30 this.mchId = mchId; 31 this.subMchId = subMchId; 32 this.httpConnectionTimeoutMs = httpConnectionTimeoutMs; 33 this.httpReadTimeoutMs = httpReadTimeoutMs; 34 this.key = key; 35 this.serviceIP = InetAddress.getLocalHost().getHostAddress(); 36 } 37 38 private byte[] certData; 39 40 private String appId; 41 42 private String mchId; 43 44 private String subMchId; 45 46 private String serviceIP; 47 48 private int httpConnectionTimeoutMs;//连接超时时间(毫秒) 49 50 private int httpReadTimeoutMs;//读取超时时间(毫秒) 51 52 private String key; 53 @Override 54 public String getAppID() { 55 return appId; 56 } 57 58 @Override 59 public String getMchID() { 60 return mchId; 61 } 62 63 public String getSubMchID() { 64 return subMchId; 65 } 66 67 68 public String getServiceIP(){ 69 return serviceIP; 70 } 71 72 @Override 73 public InputStream getCertStream() { 74 ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData); 75 return certBis; 76 } 77 78 @Override 79 public int getHttpConnectTimeoutMs() { 80 return httpConnectionTimeoutMs; 81 } 82 83 @Override 84 public int getHttpReadTimeoutMs() { 85 return httpReadTimeoutMs; 86 } 87 88 @Override 89 public String getKey() { 90 return key; 91 } 92 93 94 }
配置spring-xxx.xml 进行初始化
1 <bean id="wechatPayConstants" class="com.test.bean.WechatPayConstants"> 2 <constructor-arg index="0" value="${wechat_appid}"/> 3 <constructor-arg index="1" value="${wechat_mch_id}"/> 4 <constructor-arg index="2" value="${wechat_sub_mch_id}"/> 5 <constructor-arg index="3" value="${wechat_certPath}"/> 6 <constructor-arg index="4" value="${wechat_httpConnectionTimeoutMs}"/> 7 <constructor-arg index="5" value="${wechat_httpReadTimeoutMs}"/> 8 <constructor-arg index="6" value="${wechat_key}"/> 9 </bean> 10 11 <bean id="wxPay" class="com.github.wxpay.sdk.WXPay"> 12 <constructor-arg ref="wechatPayConstants"/> 13 </bean>
实现层java代码
1 //这里只给实现方法--刷卡支付 2 @Autowired 3 private WechatPayConstants wechatPayConstants; 4 5 @Autowired 6 WXPay wxPay; 7 8 public String WXPayment(BigDecimal totalFee,authCode,out_trade_no){ 9 10 Map<String, String> request = new HashMap<String,String>(); 11 request.put("appid", wechatPayConstants.getAppID()); 12 request.put("mch_id", wechatPayConstants.getMchID()); 13 request.put("sub_mch_id", wechatPayConstants.getSubMchID()); 14 request.put("nonce_str", System.currentTimeMillis() / 1000 + ""); 15 request.put("body", "xxx店面消费"); 16 request.put("out_trade_no",out_trade_no); 17 request.put("total_fee", totalFee.intValue());//金额单位:分 18 request.put("auth_code", authCode); 19 request.put("spbill_create_ip", wechatPayConstants.getServiceIP()); 20 String sign = ""; 21 try { 22 sign = WXPayUtil.generateSignedXml(request, "sign"); 23 } catch (Exception e) { 24 e.printStackTrace(); 25 } 26 request.put("sign", sign); 27 Map<String, String> response = null; 28 try { 29 response = wxPay.microPay(request); 30 } catch (Exception e) { 31 e.printStackTrace(); 32 throw new Exception("网络错误,请重新支付"); 33 } 34 if (response != null) { 35 String return_code = response.get("return_code"); 36 if (!"SUCCESS".equals(return_code)){ 37 return "通讯失败!" 38 }else{ 39 String result_code = response.get("result_code"); 40 if ("SUCCESS".equals(result_code)) { 41 return "支付成功!"; 42 }else{ 43 String err_code = response.get("err_code"); 44 if ("USERPAYING".equals(err_code)) { 45 //支付中调查询接口 46 return queryWXPayment(out_trade_no,null); 47 }else{ 48 return response.get("err_code_des"); 49 } 50 } 51 } 52 53 }else{ 54 return "网络传输异常"; 55 } 56 57 }
1 //查询 实现 out_trade_no 2 @Override 3 public String queryWXPayment(String out_trade_no,String transaction_id) { 4 Map<String, String> request = new HashMap<String,String>(); 5 request.put("appid", wechatPayConstants.getAppID()); 6 request.put("mch_id", wechatPayConstants.getMchID()); 7 request.put("sub_mch_id", wechatPayConstants.getSubMchID()); 8 request.put("nonce_str", System.currentTimeMillis() / 1000 + ""); 9 request.put("out_trade_no", out_trade_no); 10 if (!StringUtils.isBlank(transaction_id)) { 11 request.put("transaction_id", transaction_id); 12 } 13 String sign = ""; 14 try { 15 sign = WXPayUtil.generateSignedXml(request, "sign"); 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } 19 request.put("sign", sign); 20 Map<String, String> response = null; 21 try { 22 response = wxPay.orderQuery(request); 23 } catch (Exception e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 throw new QtException("订单查询失败"); 27 } 28 if (response != null) { 29 String return_code = response.get("return_code"); 30 String result_code = response.get("result_code"); 31 32 if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) { 33 if ("SUCCESS".equals(response.get("trade_state"))) { 34 return "支付成功"; 35 } 36 37 } else if("REVOKED".equals(response.get("trade_state"))){ 38 return "撤销成功"; 39 }else{ 40 // 41 42 } 43 44 }else{ 45 return "网络通讯异常"; 46 } 47 48 //这里写个超时处理,先判断支付时间和现在时间,再调用查询接口,建议使用短连接,返回支付中给前台,前台判断支付中继续发送查询接口,直到后台判断超时调用撤销接口 49 if(超时){ 50 return cancelWXPayment(out_trade_no,transaction_id); 51 }else{ 52 return "支付中"; 53 } 54 55 }
//撤销 @Override public String cancelWXPayment(String out_trade_no,String transaction_id) { Map<String, String> request = new HashMap<String,String>(); request.put("appid", wechatPayConstants.getAppID()); request.put("mch_id", wechatPayConstants.getMchID()); request.put("sub_mch_id", wechatPayConstants.getSubMchID()); request.put("nonce_str", System.currentTimeMillis() / 1000 + ""); request.put("out_trade_no", out_trade_no); if (!StringUtils.isBlank(transaction_id)) { request.put("transaction_id", transaction_id); } String sign = ""; try { sign = WXPayUtil.generateSignedXml(request, "sign"); } catch (Exception e) { e.printStackTrace(); } request.put("sign", sign); Map<String, String> response = null; try { response = wxPay.reverse(request); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); throw new Exception("撤销失败"); } if (response != null) { String return_code = response.get("return_code"); String result_code = response.get("result_code"); if(!"SUCCESS".equals(result_code)){ queryWXPayment(out_trade_no,transaction_id); }else{ return "撤销成功"; } }else{ return "网络通讯异常"; } }
方法的实现自己定义,我这里图简单,只写了几个需要的,参数最好是一个对象,这里只是简单的举例子,以上