WXPay.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. package com.fdkankan.pay.wx.sdk;
  2. import javax.net.ssl.HttpsURLConnection;
  3. import javax.net.ssl.KeyManagerFactory;
  4. import javax.net.ssl.SSLContext;
  5. import java.io.*;
  6. import java.net.HttpURLConnection;
  7. import java.net.URL;
  8. import java.security.KeyStore;
  9. import java.security.SecureRandom;
  10. import java.util.HashMap;
  11. import java.util.Map;
  12. public class WXPay {
  13. private WXPayConfig config;
  14. private WXPayConstants.SignType signType;
  15. private boolean useSandbox;
  16. public WXPay(final WXPayConfig config) {
  17. this(config, WXPayConstants.SignType.MD5, false);
  18. }
  19. public WXPay(final WXPayConfig config, final WXPayConstants.SignType signType) {
  20. this(config, signType, false);
  21. }
  22. public WXPay(final WXPayConfig config, final WXPayConstants.SignType signType, final boolean useSandbox) {
  23. this.config = config;
  24. this.signType = signType;
  25. this.useSandbox = useSandbox;
  26. }
  27. /**
  28. * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign <br>
  29. * 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口
  30. *
  31. * @param reqData
  32. * @return
  33. * @throws Exception
  34. */
  35. public Map<String, String> fillRequestData(Map<String, String> reqData) throws Exception {
  36. reqData.put("appid", config.getAppID());
  37. reqData.put("mch_id", config.getMchID());
  38. reqData.put("nonce_str", WXPayUtil.generateNonceStr());
  39. if (WXPayConstants.SignType.MD5.equals(this.signType)) {
  40. reqData.put("sign_type", WXPayConstants.MD5);
  41. }
  42. else if (WXPayConstants.SignType.HMACSHA256.equals(this.signType)) {
  43. reqData.put("sign_type", WXPayConstants.HMACSHA256);
  44. }
  45. reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType));
  46. return reqData;
  47. }
  48. /**
  49. * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。
  50. *
  51. * @param reqData 向wxpay post的请求数据
  52. * @return 签名是否有效
  53. * @throws Exception
  54. */
  55. public boolean isResponseSignatureValid(Map<String, String> reqData) throws Exception {
  56. // 返回数据的签名方式和请求中给定的签名方式是一致的
  57. return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), this.signType);
  58. }
  59. /**
  60. * 判断支付结果通知中的sign是否有效
  61. *
  62. * @param reqData 向wxpay post的请求数据
  63. * @return 签名是否有效
  64. * @throws Exception
  65. */
  66. public boolean isPayResultNotifySignatureValid(Map<String, String> reqData) throws Exception {
  67. String signTypeInData = reqData.get(WXPayConstants.FIELD_SIGN_TYPE);
  68. WXPayConstants.SignType signType;
  69. if (signTypeInData == null) {
  70. signType = WXPayConstants.SignType.MD5;
  71. }
  72. else {
  73. signTypeInData = signTypeInData.trim();
  74. if (signTypeInData.length() == 0) {
  75. signType = WXPayConstants.SignType.MD5;
  76. }
  77. else if (WXPayConstants.MD5.equals(signTypeInData)) {
  78. signType = WXPayConstants.SignType.MD5;
  79. }
  80. else if (WXPayConstants.HMACSHA256.equals(signTypeInData)) {
  81. signType = WXPayConstants.SignType.HMACSHA256;
  82. }
  83. else {
  84. throw new Exception(String.format("Unsupported sign_type: %s", signTypeInData));
  85. }
  86. }
  87. return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), signType);
  88. }
  89. /**
  90. * 不需要证书的请求
  91. * @param strUrl String
  92. * @param reqData 向wxpay post的请求数据
  93. * @param connectTimeoutMs 超时时间,单位是毫秒
  94. * @param readTimeoutMs 超时时间,单位是毫秒
  95. * @return API返回数据
  96. * @throws Exception
  97. */
  98. public String requestWithoutCert(String strUrl, Map<String, String> reqData,
  99. int connectTimeoutMs, int readTimeoutMs) throws Exception {
  100. String UTF8 = "UTF-8";
  101. String reqBody = WXPayUtil.mapToXml(reqData);
  102. URL httpUrl = new URL(strUrl);
  103. HttpURLConnection httpURLConnection = (HttpURLConnection) httpUrl.openConnection();
  104. httpURLConnection.setDoOutput(true);
  105. httpURLConnection.setRequestMethod("POST");
  106. httpURLConnection.setConnectTimeout(connectTimeoutMs);
  107. httpURLConnection.setReadTimeout(readTimeoutMs);
  108. httpURLConnection.connect();
  109. OutputStream outputStream = httpURLConnection.getOutputStream();
  110. outputStream.write(reqBody.getBytes(UTF8));
  111. // if (httpURLConnection.getResponseCode()!= 200) {
  112. // throw new Exception(String.format("HTTP response code is %d, not 200", httpURLConnection.getResponseCode()));
  113. // }
  114. //获取内容
  115. InputStream inputStream = httpURLConnection.getInputStream();
  116. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8));
  117. final StringBuffer stringBuffer = new StringBuffer();
  118. String line = null;
  119. while ((line = bufferedReader.readLine()) != null) {
  120. stringBuffer.append(line).append("\n");
  121. }
  122. String resp = stringBuffer.toString();
  123. if (stringBuffer!=null) {
  124. try {
  125. bufferedReader.close();
  126. } catch (IOException e) {
  127. e.printStackTrace();
  128. }
  129. }
  130. if (inputStream!=null) {
  131. try {
  132. inputStream.close();
  133. } catch (IOException e) {
  134. e.printStackTrace();
  135. }
  136. }
  137. if (outputStream!=null) {
  138. try {
  139. outputStream.close();
  140. } catch (IOException e) {
  141. e.printStackTrace();
  142. }
  143. }
  144. // if (httpURLConnection!=null) {
  145. // httpURLConnection.disconnect();
  146. // }
  147. return resp;
  148. }
  149. /**
  150. * 需要证书的请求
  151. * @param strUrl String
  152. * @param reqData 向wxpay post的请求数据 Map
  153. * @param connectTimeoutMs 超时时间,单位是毫秒
  154. * @param readTimeoutMs 超时时间,单位是毫秒
  155. * @return API返回数据
  156. * @throws Exception
  157. */
  158. public String requestWithCert(String strUrl, Map<String, String> reqData,
  159. int connectTimeoutMs, int readTimeoutMs) throws Exception {
  160. String UTF8 = "UTF-8";
  161. String reqBody = WXPayUtil.mapToXml(reqData);
  162. URL httpUrl = new URL(strUrl);
  163. char[] password = config.getMchID().toCharArray();
  164. InputStream certStream = config.getCertStream();
  165. KeyStore ks = KeyStore.getInstance("PKCS12");
  166. ks.load(certStream, password);
  167. // 实例化密钥库 & 初始化密钥工厂
  168. KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  169. kmf.init(ks, password);
  170. // 创建SSLContext
  171. SSLContext sslContext = SSLContext.getInstance("TLS");
  172. sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
  173. HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
  174. HttpURLConnection httpURLConnection = (HttpURLConnection) httpUrl.openConnection();
  175. httpURLConnection.setDoOutput(true);
  176. httpURLConnection.setRequestMethod("POST");
  177. httpURLConnection.setConnectTimeout(connectTimeoutMs);
  178. httpURLConnection.setReadTimeout(readTimeoutMs);
  179. httpURLConnection.connect();
  180. OutputStream outputStream = httpURLConnection.getOutputStream();
  181. outputStream.write(reqBody.getBytes(UTF8));
  182. // if (httpURLConnection.getResponseCode()!= 200) {
  183. // throw new Exception(String.format("HTTP response code is %d, not 200", httpURLConnection.getResponseCode()));
  184. // }
  185. //获取内容
  186. InputStream inputStream = httpURLConnection.getInputStream();
  187. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8));
  188. final StringBuffer stringBuffer = new StringBuffer();
  189. String line = null;
  190. while ((line = bufferedReader.readLine()) != null) {
  191. stringBuffer.append(line);
  192. }
  193. String resp = stringBuffer.toString();
  194. if (stringBuffer!=null) {
  195. try {
  196. bufferedReader.close();
  197. } catch (IOException e) {
  198. // e.printStackTrace();
  199. }
  200. }
  201. if (inputStream!=null) {
  202. try {
  203. inputStream.close();
  204. } catch (IOException e) {
  205. // e.printStackTrace();
  206. }
  207. }
  208. if (outputStream!=null) {
  209. try {
  210. outputStream.close();
  211. } catch (IOException e) {
  212. // e.printStackTrace();
  213. }
  214. }
  215. if (certStream!=null) {
  216. try {
  217. certStream.close();
  218. } catch (IOException e) {
  219. // e.printStackTrace();
  220. }
  221. }
  222. // if (httpURLConnection!=null) {
  223. // httpURLConnection.disconnect();
  224. // }
  225. return resp;
  226. }
  227. /**
  228. * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。
  229. * @param xmlStr API返回的XML格式数据
  230. * @return Map类型数据
  231. * @throws Exception
  232. */
  233. public Map<String, String> processResponseXml(String xmlStr) throws Exception {
  234. String RETURN_CODE = "return_code";
  235. String return_code;
  236. Map<String, String> respData = WXPayUtil.xmlToMap(xmlStr);
  237. if (respData.containsKey(RETURN_CODE)) {
  238. return_code = respData.get(RETURN_CODE);
  239. }
  240. else {
  241. throw new Exception(String.format("No `return_code` in XML: %s", xmlStr));
  242. }
  243. if (return_code.equals(WXPayConstants.FAIL)) {
  244. return respData;
  245. }
  246. else if (return_code.equals(WXPayConstants.SUCCESS)) {
  247. if (this.isResponseSignatureValid(respData)) {
  248. return respData;
  249. }
  250. else {
  251. throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr));
  252. }
  253. }
  254. else {
  255. throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr));
  256. }
  257. }
  258. /**
  259. * 作用:提交刷卡支付<br>
  260. * 场景:刷卡支付
  261. * @param reqData 向wxpay post的请求数据
  262. * @return API返回数据
  263. * @throws Exception
  264. */
  265. public Map<String, String> microPay(Map<String, String> reqData) throws Exception {
  266. return this.microPay(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  267. }
  268. /**
  269. * 作用:提交刷卡支付<br>
  270. * 场景:刷卡支付
  271. * @param reqData 向wxpay post的请求数据
  272. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  273. * @param readTimeoutMs 读超时时间,单位是毫秒
  274. * @return API返回数据
  275. * @throws Exception
  276. */
  277. public Map<String, String> microPay(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  278. String url;
  279. if (this.useSandbox) {
  280. url = WXPayConstants.SANDBOX_MICROPAY_URL;
  281. }
  282. else {
  283. url = WXPayConstants.MICROPAY_URL;
  284. }
  285. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  286. return this.processResponseXml(respXml);
  287. }
  288. /**
  289. * 作用:统一下单<br>
  290. * 场景:公共号支付、扫码支付、APP支付
  291. * @param reqData 向wxpay post的请求数据
  292. * @return API返回数据
  293. * @throws Exception
  294. */
  295. public Map<String, String> unifiedOrder(Map<String, String> reqData) throws Exception {
  296. return this.unifiedOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  297. }
  298. /**
  299. * 作用:统一下单<br>
  300. * 场景:公共号支付、扫码支付、APP支付
  301. * @param reqData 向wxpay post的请求数据
  302. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  303. * @param readTimeoutMs 读超时时间,单位是毫秒
  304. * @return API返回数据
  305. * @throws Exception
  306. */
  307. public Map<String, String> unifiedOrder(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  308. String url;
  309. if (this.useSandbox) {
  310. url = WXPayConstants.SANDBOX_UNIFIEDORDER_URL;
  311. }
  312. else {
  313. url = WXPayConstants.UNIFIEDORDER_URL;
  314. }
  315. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  316. return this.processResponseXml(respXml);
  317. }
  318. /**
  319. * 作用:查询订单<br>
  320. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  321. * @param reqData 向wxpay post的请求数据
  322. * @return API返回数据
  323. * @throws Exception
  324. */
  325. public Map<String, String> orderQuery(Map<String, String> reqData) throws Exception {
  326. return this.orderQuery(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  327. }
  328. /**
  329. * 作用:查询订单<br>
  330. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  331. * @param reqData 向wxpay post的请求数据 int
  332. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  333. * @param readTimeoutMs 读超时时间,单位是毫秒
  334. * @return API返回数据
  335. * @throws Exception
  336. */
  337. public Map<String, String> orderQuery(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  338. String url;
  339. if (this.useSandbox) {
  340. url = WXPayConstants.SANDBOX_ORDERQUERY_URL;
  341. }
  342. else {
  343. url = WXPayConstants.ORDERQUERY_URL;
  344. }
  345. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  346. return this.processResponseXml(respXml);
  347. }
  348. /**
  349. * 作用:撤销订单<br>
  350. * 场景:刷卡支付
  351. * @param reqData 向wxpay post的请求数据
  352. * @return API返回数据
  353. * @throws Exception
  354. */
  355. public Map<String, String> reverse(Map<String, String> reqData) throws Exception {
  356. return this.reverse(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  357. }
  358. /**
  359. * 作用:撤销订单<br>
  360. * 场景:刷卡支付<br>
  361. * 其他:需要证书
  362. * @param reqData 向wxpay post的请求数据
  363. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  364. * @param readTimeoutMs 读超时时间,单位是毫秒
  365. * @return API返回数据
  366. * @throws Exception
  367. */
  368. public Map<String, String> reverse(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  369. String url;
  370. if (this.useSandbox) {
  371. url = WXPayConstants.SANDBOX_REVERSE_URL;
  372. }
  373. else {
  374. url = WXPayConstants.REVERSE_URL;
  375. }
  376. String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  377. return this.processResponseXml(respXml);
  378. }
  379. /**
  380. * 作用:关闭订单<br>
  381. * 场景:公共号支付、扫码支付、APP支付
  382. * @param reqData 向wxpay post的请求数据
  383. * @return API返回数据
  384. * @throws Exception
  385. */
  386. public Map<String, String> closeOrder(Map<String, String> reqData) throws Exception {
  387. return this.closeOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  388. }
  389. /**
  390. * 作用:关闭订单<br>
  391. * 场景:公共号支付、扫码支付、APP支付
  392. * @param reqData 向wxpay post的请求数据
  393. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  394. * @param readTimeoutMs 读超时时间,单位是毫秒
  395. * @return API返回数据
  396. * @throws Exception
  397. */
  398. public Map<String, String> closeOrder(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  399. String url;
  400. if (this.useSandbox) {
  401. url = WXPayConstants.SANDBOX_CLOSEORDER_URL;
  402. }
  403. else {
  404. url = WXPayConstants.CLOSEORDER_URL;
  405. }
  406. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  407. return this.processResponseXml(respXml);
  408. }
  409. /**
  410. * 作用:申请退款<br>
  411. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  412. * @param reqData 向wxpay post的请求数据
  413. * @return API返回数据
  414. * @throws Exception
  415. */
  416. public Map<String, String> refund(Map<String, String> reqData) throws Exception {
  417. return this.refund(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  418. }
  419. /**
  420. * 作用:申请退款<br>
  421. * 场景:刷卡支付、公共号支付、扫码支付、APP支付<br>
  422. * 其他:需要证书
  423. * @param reqData 向wxpay post的请求数据
  424. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  425. * @param readTimeoutMs 读超时时间,单位是毫秒
  426. * @return API返回数据
  427. * @throws Exception
  428. */
  429. public Map<String, String> refund(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  430. String url;
  431. if (this.useSandbox) {
  432. url = WXPayConstants.SANDBOX_REFUND_URL;
  433. }
  434. else {
  435. url = WXPayConstants.REFUND_URL;
  436. }
  437. String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  438. return this.processResponseXml(respXml);
  439. }
  440. /**
  441. * 作用:退款查询<br>
  442. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  443. * @param reqData 向wxpay post的请求数据
  444. * @return API返回数据
  445. * @throws Exception
  446. */
  447. public Map<String, String> refundQuery(Map<String, String> reqData) throws Exception {
  448. return this.refundQuery(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  449. }
  450. /**
  451. * 作用:退款查询<br>
  452. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  453. * @param reqData 向wxpay post的请求数据
  454. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  455. * @param readTimeoutMs 读超时时间,单位是毫秒
  456. * @return API返回数据
  457. * @throws Exception
  458. */
  459. public Map<String, String> refundQuery(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  460. String url;
  461. if (this.useSandbox) {
  462. url = WXPayConstants.SANDBOX_REFUNDQUERY_URL;
  463. }
  464. else {
  465. url = WXPayConstants.REFUNDQUERY_URL;
  466. }
  467. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  468. return this.processResponseXml(respXml);
  469. }
  470. /**
  471. * 作用:对账单下载(成功时返回对账单数据,失败时返回XML格式数据)<br>
  472. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  473. * @param reqData 向wxpay post的请求数据
  474. * @return API返回数据
  475. * @throws Exception
  476. */
  477. public Map<String, String> downloadBill(Map<String, String> reqData) throws Exception {
  478. return this.downloadBill(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  479. }
  480. /**
  481. * 作用:对账单下载<br>
  482. * 场景:刷卡支付、公共号支付、扫码支付、APP支付<br>
  483. * 其他:无论是否成功都返回Map。若成功,返回的Map中含有return_code、return_msg、data,
  484. * 其中return_code为`SUCCESS`,data为对账单数据。
  485. * @param reqData 向wxpay post的请求数据
  486. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  487. * @param readTimeoutMs 读超时时间,单位是毫秒
  488. * @return 经过封装的API返回数据
  489. * @throws Exception
  490. */
  491. public Map<String, String> downloadBill(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  492. String url;
  493. if (this.useSandbox) {
  494. url = WXPayConstants.SANDBOX_DOWNLOADBILL_URL;
  495. }
  496. else {
  497. url = WXPayConstants.DOWNLOADBILL_URL;
  498. }
  499. String respStr = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs).trim();
  500. Map<String, String> ret;
  501. // 出现错误,返回XML数据
  502. if (respStr.indexOf("<") == 0) {
  503. ret = WXPayUtil.xmlToMap(respStr);
  504. }
  505. else {
  506. // 正常返回csv数据
  507. ret = new HashMap<String, String>();
  508. ret.put("return_code", WXPayConstants.SUCCESS);
  509. ret.put("return_msg", "sdk");
  510. ret.put("data", respStr);
  511. }
  512. return ret;
  513. }
  514. /**
  515. * 作用:交易保障<br>
  516. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  517. * @param reqData 向wxpay post的请求数据
  518. * @return API返回数据
  519. * @throws Exception
  520. */
  521. public Map<String, String> report(Map<String, String> reqData) throws Exception {
  522. return this.report(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  523. }
  524. /**
  525. * 作用:交易保障<br>
  526. * 场景:刷卡支付、公共号支付、扫码支付、APP支付
  527. * @param reqData 向wxpay post的请求数据
  528. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  529. * @param readTimeoutMs 读超时时间,单位是毫秒
  530. * @return API返回数据
  531. * @throws Exception
  532. */
  533. public Map<String, String> report(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  534. String url;
  535. if (this.useSandbox) {
  536. url = WXPayConstants.SANDBOX_REPORT_URL;
  537. }
  538. else {
  539. url = WXPayConstants.REPORT_URL;
  540. }
  541. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  542. return WXPayUtil.xmlToMap(respXml);
  543. }
  544. /**
  545. * 作用:转换短链接<br>
  546. * 场景:刷卡支付、扫码支付
  547. * @param reqData 向wxpay post的请求数据
  548. * @return API返回数据
  549. * @throws Exception
  550. */
  551. public Map<String, String> shortUrl(Map<String, String> reqData) throws Exception {
  552. return this.shortUrl(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  553. }
  554. /**
  555. * 作用:转换短链接<br>
  556. * 场景:刷卡支付、扫码支付
  557. * @param reqData 向wxpay post的请求数据
  558. * @return API返回数据
  559. * @throws Exception
  560. */
  561. public Map<String, String> shortUrl(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  562. String url;
  563. if (this.useSandbox) {
  564. url = WXPayConstants.SANDBOX_SHORTURL_URL;
  565. }
  566. else {
  567. url = WXPayConstants.SHORTURL_URL;
  568. }
  569. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  570. return this.processResponseXml(respXml);
  571. }
  572. /**
  573. * 作用:授权码查询OPENID接口<br>
  574. * 场景:刷卡支付
  575. * @param reqData 向wxpay post的请求数据
  576. * @return API返回数据
  577. * @throws Exception
  578. */
  579. public Map<String, String> authCodeToOpenid(Map<String, String> reqData) throws Exception {
  580. return this.authCodeToOpenid(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
  581. }
  582. /**
  583. * 作用:授权码查询OPENID接口<br>
  584. * 场景:刷卡支付
  585. * @param reqData 向wxpay post的请求数据
  586. * @param connectTimeoutMs 连接超时时间,单位是毫秒
  587. * @param readTimeoutMs 读超时时间,单位是毫秒
  588. * @return API返回数据
  589. * @throws Exception
  590. */
  591. public Map<String, String> authCodeToOpenid(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
  592. String url;
  593. if (this.useSandbox) {
  594. url = WXPayConstants.SANDBOX_AUTHCODETOOPENID_URL;
  595. }
  596. else {
  597. url = WXPayConstants.AUTHCODETOOPENID_URL;
  598. }
  599. String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
  600. return this.processResponseXml(respXml);
  601. }
  602. } // end class