首先,你得先有微信開發平臺帳號密碼還須要開通應用,而後還有微信服務商平臺商戶版帳號(這些我都是給產品經理拿的)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,你可能要本身定義一下,應答是要這種格式的: