首先,你得先有微信开发平台帐号密码还须要开通应用,而后还有微信服务商平台商户版帐号(这些我都是给产品经理拿的)html
其次我认为你先去看一看微信开发平台的文档! https://pay.weixin.qq.com/wiki/doc/api/index.html前端
这里有不少种支付,我就采用APP支付来讲了(会了APP支付其实H5支付都差很少的!)git
进来后是这样的,随便看看'APP支付那几篇文章'讲的流程!,看完后知道大概了就能够看看'API列表了'github
咱们后台开发须要关注的就是这三个API了!后端
那我仍是简单介绍一下APP支付的一个业务流程吧(其实文档里简述的了,我就直接贴图了!)api
这些圈圈起来的流程步骤,就是咱们后台要作的了,其余的都是由移动端来实现的,咱们能够不理会,还有步骤6查询订单支付结果,这个可作可不作吧,为了系统更安全些更慎重些也能够去实现,不过我就没有实现了安全
下面就说一下如何对接这个所谓的第三方接口,其实就是跟前端来调用咱们后端接口是同样的,咱们在写接口文档时,有请求地址,请求参数,返回数据以及返回数据格式这4样!微信
只要提供这4种东西,前端就能够来对接咱们后台接口啦!因此,同个道理的,此次是由咱们后台人员去请求微信提供的接口!微信开发
因此文档上都有提供的了,咱们只须要用httpclient来想微信接口那边发送同步请求获取返回结果数据便可,这样听起来貌似很简单!不过还真不是很简单,不少坑的,毕竟是腾讯的文档!mybatis
而后要注意的首先是请求参数,请求参数是否必填这个若是是否的话我就建议不用填上去了,而后签名参数也要去看文档,如何生成签名,还有,参数是要以xml格式形式发送过去,
并且返回结果也是以xml返回回来,因此和微信对接的交互就是xml,这点有点蛋疼呀!
好了,上面说了该怎么去请求第三方接口,想必你们有点懵吧,不知道该如何下手,其实上面的那个请求方式有点难度,小白能够忽略上面那套方式,直接使用微信支付的一个开源jar!
对 你没看错,就这一个,这个jar包里面已经封装好了咱们如何获取签名,如何验签等api方法,并且还不须要咱们去将参数转化成xml格式,它已经封装好了一切了,因此很是方便!
这个jar包能够在这个地址去下载http://www.mvnjar.com/com.github.liyiorg/weixin-popular/2.8.14/detail.html
好了,那上面的介绍看完还有微信jar拿到手后,如今就能够开始来实现了! 我就直接亮代码了!
1 /** 2 * @description:微信支付JAVA-SDK: APP支付,退款 3 * @author:小黑 4 */ 5 @Service 6 public class WechatPayService { 7 private static final Logger LOGGER = LoggerFactory.getLogger(WechatPayService.class); 8 9 /************ 微信开放平台配置 ***************/ 10 11 /** APPID */ 12 private static final String APPID = ""; 13 14 /** 商户号 */ 15 private static final String MCH_ID = ""; 16 17 /** 密钥 */ 18 private static final String PRIVATE_KEY = ""; 19 20 /** 用户订单支付结果异步通知url */ 21 private static final String NOTIFY_URL = ""; 22 23 /** 商户支付证书路径 */ 24 private static final String API_CLIENT_CERT_PATH = ""; 25 26 // 加载商户支付证书文件; 27 static { 28 LocalHttpClient.initMchKeyStore(MCH_ID, API_CLIENT_CERT_PATH); 29 } 30 31 /** 32 * @description:使用微信支付-APP支付方式-统一下单; 33 * @return 支付参数,若是支付失败则返回null 34 * @author:Fanhaojian 35 */ 36 public MchPayApp orderAppPay(PayLog payLog) { 37 38 Unifiedorder unifiedorder = new Unifiedorder(); 39 40 /** APPID */ 41 unifiedorder.setAppid(APPID); 42 43 /** 商户号 */ 44 unifiedorder.setMch_id(MCH_ID); 45 46 /** 随机字符串 */ 47 unifiedorder.setNonce_str(UUID.randomUUID().toString().replaceAll("-", "")); 48 49 /** 商品描述 */ 50 unifiedorder.setBody(payLog.getPayCode()); 51 52 /** 商户订单号 */ 53 unifiedorder.setOut_trade_no(payLog.getPayCode()); 54 55 /** 订单总金额 */ 56 unifiedorder.setTotal_fee(payLog.getPayPrice().multiply(new BigDecimal(100)).intValue() + ""); // 订单总金额,单位为分; 57 58 /** 用户端请求IP地址 */ 59 unifiedorder.setSpbill_create_ip(IpUtils.getClientIp()); 60 61 /** 异步通知回调地址 */ 62 unifiedorder.setNotify_url(NOTIFY_URL); 63 64 /** 交易类型 */ 65 unifiedorder.setTrade_type("APP"); 66 67 LOGGER.warn("微信APP支付--(签名前):" + XMLConverUtil.convertToXML(unifiedorder)); 68 69 /** 获取签名 */ 70 UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, PRIVATE_KEY); 71 72 LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_code):" + unifiedorderResult.getReturn_code()); 73 LOGGER.warn("微信APP支付--支付统一下单接口请求状态(return_msg):" + unifiedorderResult.getReturn_msg()); 74 LOGGER.warn("微信APP支付--支付统一下单接口请求状态(result_code):" + unifiedorderResult.getResult_code()); 75 LOGGER.warn("微信APP支付--支付请求参数封装(签名后):" + XMLConverUtil.convertToXML(unifiedorder)); 76 LOGGER.warn("微信APP支付--支付统一下单接口返回数据:" + FastJSONUtils.getJsonHelper().toJSONString(unifiedorderResult)); 77 78 // 下单结果验签; 79 if(unifiedorderResult.getSign_status() != null && unifiedorderResult.getSign_status()) { 80 LOGGER.warn("微信APP支付验签成功"); 81 return PayUtil.generateMchAppData(unifiedorderResult.getPrepay_id(), APPID, MCH_ID, PRIVATE_KEY); 82 } 83 return null; 84 } 85 86 /** 87 * @description:微信退款业务封装(支付押金退还); 88 * @param PayLog order:支付订单信息 89 * Double refundAmount:退款金额 90 * @return 微信退款接口返回数据 true 退款成功 false 退款失败 91 * @author:FanHaoJian 92 */ 93 public Boolean refundOrder(PayLog order, Double refundAmount) { 94 95 // 调用微信支付退款接口; 96 SecapiPayRefund payRefund = new SecapiPayRefund(); 97 payRefund.setAppid(APPID); 98 payRefund.setMch_id(MCH_ID); 99 payRefund.setNonce_str(UUID.randomUUID().toString().replaceAll("-", "")); 100 payRefund.setOut_trade_no(order.getPayCode());//支付订单号 101 payRefund.setOut_refund_no(order.getRefundCode());//退款单号 102 payRefund.setTotal_fee(order.getPayPrice().multiply(new BigDecimal(100)).intValue());//原订单金额,单位:分; 103 payRefund.setRefund_fee(new BigDecimal(refundAmount).multiply(new BigDecimal(100)).intValue());//退款订单金额,单位:分; 104 105 SecapiPayRefundResult refundResult = PayMchAPI.secapiPayRefund(payRefund, PRIVATE_KEY); 106 107 // 微信支付退款接口返回数据验签; 108 if(refundResult.getSign_status() != null && refundResult.getSign_status()) { 109 LOGGER.warn("微信退款接口--接口请求状态(return_code):" + refundResult.getReturn_code()); 110 LOGGER.warn("微信退款接口--接口请求状态(return_msg):" + refundResult.getReturn_msg()); 111 112 // 退款信息提交成功; 113 if("SUCCESS".equals(refundResult.getReturn_code())) { 114 LOGGER.warn("微信退款接口--接口请求状态(result_code):" + refundResult.getResult_code()); 115 LOGGER.warn("微信退款接口--接口请求状态(err_code):" + refundResult.getErr_code()); 116 LOGGER.warn("微信退款接口--接口请求状态(err_code_des):" + refundResult.getErr_code_des()); 117 118 return Boolean.TRUE; 119 } 120 } 121 122 return Boolean.FALSE; 123 } 124 }
在项目建一个sdk包,而后统一放入sdk,相似这样!
而后建立一个微信支付SDK,将上面代码复制过去,而后看一遍代码里的方法流程,看明白后在改改里面的代码!
而后我简单介绍一下上面的微信支付SDK吧,里面有两个方法,一个是统一下单,一个是退款!
统一下单返回的数据就是要拿给移动端的签名数据,退款返回的数据就是true和false,没什么判断成功仍是失败就好了,成功该作什么,失败该作什么!
OK! 如今说完了统一下单和退款后,还有一个支付通知结果的API,也就是异步通知了!若是你看完了那篇流程图,你就会知道,当移动端调起支付而且支付成功后,微信后台那边会向咱们这边后台发送一个请求过来!
固然微信那边发送请求过来咱们这边的接口,我也直接亮代码了!
1 /** 2 * @description:微信支付异步通知请求URL 3 * @author:小黑 4 */ 5 public class WechatOrderNotify extends ActionSupport { 6 private static final Logger LOGGER = LoggerFactory.getLogger(WechatOrderNotify.class); 7 private static final long serialVersionUID = 1L; 8 9 /** 密钥 */ 10 private static final String PRIVATE_KEY = ""; 11 12 /** 定义应答变量 */ 13 private String xml; 14 15 @Override 16 public String wechatOrderNotify() throws Exception { 17 18 // 解析微信支付异步通知请求参数; 19 HttpServletRequest request = ServletActionContext.getRequest(); 20 String xml = StreamUtils.copyToString(request.getInputStream(), Charset.forName("utf-8")); 21 Map<String, String> params = XMLConverUtil.convertToMap(xml); 22 MchPayNotify payNotify = XMLConverUtil.convertToObject(MchPayNotify.class, xml); 23 24 /** 打印日志信息 */ 25 LOGGER.warn("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$---进入微信支付异步通知请求接口---$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"); 26 LOGGER.warn("微信支付用户订单支付结果异步通知请求参数(xml):" + params); 27 LOGGER.warn("微信支付用户订单支付结果异步通知请求参数(map):" + params); 28 LOGGER.warn("return_code:" + payNotify.getReturn_code()); 29 LOGGER.warn("return_msg:" + params.get("return_msg")); 30 31 /** 校验支付成功仍是失败 */ 32 if("SUCCESS".equals(payNotify.getReturn_code())) { 33 34 /** 获取微信后台返回来的异步通知参数 */ 35 String outTradeNo = payNotify.getOut_trade_no(); // 用户订单号; 36 String tradeNo = payNotify.getTransaction_id(); // 微信交易号; 37 String tradeStatus = payNotify.getResult_code(); // 微信支付状态; 38 Integer totalFee = payNotify.getTotal_fee(); // 支付金额 39 40 /** 获取验签结果 true说明验签成功 false说明验签失败 */ 41 boolean flag = SignatureUtil.validateSign(params, PRIVATE_KEY); 42 43 /** 打印日志信息 */ 44 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知订单号(out_trade_no):" + outTradeNo); 45 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知交易号(trade_no):" + tradeNo); 46 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知交易状态(result_code):" + tradeStatus); 47 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知支付金额(total_fee):" + totalFee); 48 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知验签状态:" + flag); 49 50 /** 根据订单号获取订单支付信息: 支付状态为 '未支付' */ 51 ...此处省略 根据订单号去查订单 我用hibernate的 大家可能用mybatis或者其余,因此本身去查吧! 52 53 /** 支付成功/处理订单业务信息 */ 54 if(flag && "SUCCESS".equals(tradeStatus) && order != null) { 55 56 /** 更新订单支付信息: */ 57 ...此处省略 根据本身项目的业务去处理逻辑! 58 59 /** 封装通知信息 */ 60 MchBaseResult baseResult = new MchBaseResult(); 61 baseResult.setReturn_code("SUCCESS"); 62 baseResult.setReturn_msg("OK"); 63 xml = XMLConverUtil.convertToXML(baseResult); 64 65 /** 支付成功 */ 66 }else if(flag && "SUCCESS".equals(tradeStatus)){ 67 MchBaseResult baseResult = new MchBaseResult(); 68 baseResult.setReturn_code("SUCCESS"); 69 baseResult.setReturn_msg("OK"); 70 xml = XMLConverUtil.convertToXML(baseResult); 71 72 /** 支付失败 */ 73 }else { 74 MchBaseResult baseResult = new MchBaseResult(); 75 baseResult.setReturn_code("FAIL"); 76 baseResult.setReturn_msg("FAIL"); 77 xml = XMLConverUtil.convertToXML(baseResult); 78 } 79 80 /** 支付失败 */ 81 }else { 82 MchBaseResult baseResult = new MchBaseResult(); 83 baseResult.setReturn_code("FAIL"); 84 baseResult.setReturn_msg("FAIL"); 85 xml = XMLConverUtil.convertToXML(baseResult); 86 } 87 LOGGER.warn("微信支付--APP支付方式支付用户订单异步通知返回数据:" + xml); 88 return Results.XML; 89 } 90 91 public String getXml() { 92 return xml; 93 } 94 95 public void setXml(String xml) { 96 this.xml = xml; 97 } 98 }
这里也是直接招搬过去,而后改改代码便可!须要注意的就是这个返回数据xml,你可能要本身定义一下,应答是要这种格式的: