首先,你得先有微信開發平台賬號密碼還需要開通應用,然后還有微信服務商平台商戶版賬號(這些我都是給產品經理拿的)
其次我認為你先去看一看微信開發平台的文檔! https://pay.weixin.qq.com/wiki/doc/api/index.html

這里有很多種支付,我就采用APP支付來說了(會了APP支付其實H5支付都差不多的!)

進來后是這樣的,隨便看看'APP支付那幾篇文章'講的流程!,看完后知道大概了就可以看看'API列表了'

我們后台開發需要關注的就是這三個API了!
那我還是簡單介紹一下APP支付的一個業務流程吧(其實文檔里簡述的了,我就直接貼圖了!)


這些圈圈起來的流程步驟,就是我們后台要做的了,其他的都是由移動端來實現的,我們可以不理會,還有步驟6查詢訂單支付結果,這個可做可不做吧,為了系統更安全些更慎重些也可以去實現,不過我就沒有實現了
下面就說一下如何對接這個所謂的第三方接口,其實就是跟前端來調用我們后端接口是一樣的,我們在寫接口文檔時,有請求地址,請求參數,返回數據以及返回數據格式這4樣!
只要提供這4種東西,前端就可以來對接我們后台接口啦!所以,同個道理的,這次是由我們后台人員去請求微信提供的接口!


所以文檔上都有提供的了,我們只需要用httpclient來想微信接口那邊發送同步請求獲取返回結果數據即可,這樣聽起來貌似很簡單!不過還真不是很簡單,很多坑的,畢竟是騰訊的文檔!
然后要注意的首先是請求參數,請求參數是否必填這個如果是否的話我就建議不用填上去了,然后簽名參數也要去看文檔,如何生成簽名,還有,參數是要以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,你可能要自己定義一下,應答是要這種格式的:


