程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> JAVA實現的微信掃描二維碼支付,java實現

JAVA實現的微信掃描二維碼支付,java實現

編輯:JAVA綜合教程

JAVA實現的微信掃描二維碼支付,java實現


吐槽一下

支付項目采用springMvc+Dubbo架構實現,只對外提供接口。

話說,為什麼微信支付比支付寶來的晚了那麼一點,一句話,那一陣挺忙的,然後就沒有時間整理,最近做完支付寶支付,順便也把微信支付的也整理一下。

這裡再吐槽一下,微信支付的DEMO基本為零,很多代碼都是從網上查找的(也可能我麼有仔細找API)。

前期醞釀准備

掃碼支付,目前來說個人是不可以申請的,包括現在支付寶的即時到帳個人相關業務也取消了。所以這裡必須有一個微信支付商戶平台,具體怎麼申請的,我也不清楚,只是拿來用的。

商戶平台是要配合綁定微信公眾賬號使用的,具體操作申請下來已經綁定了,這裡你也只管用就是了。

什麼是掃碼支付?

場景介紹

用戶掃描商戶展示在各種場景的二維碼進行支付。

步驟1:商戶根據微信支付的規則,為不同商品生成不同的二維碼(如圖6.1),展示在各種場景,用於用戶掃描購買。

步驟2:用戶使用微信“掃一掃”(如圖6.2)掃描二維碼後,獲取商品支付信息,引導用戶完成支付(如圖6.3)。
chapter6_1_1.png
chapter6_1_2.jpgchapter6_1_3.jpg
支付二維碼
圖6.1 支付二維碼
打開微信掃一掃二維碼
圖6.2 打開微信掃一掃二維碼
確認支付頁面
圖6.3 確認支付頁面

步驟(3):用戶確認支付,輸入支付密碼(如圖6.4)。

步驟(4):支付完成後會提示用戶支付成功(如圖6.5),商戶後台得到支付成功的通知,然後進行發貨處理。

用戶確認支付,輸入密碼
圖6.4 用戶確認支付,輸入密碼
支付成功提示
圖6.5 支付成功提示
chapter6_1_4.jpgchapter6_1_5.jpg

如何集成到項目中去?

ConfigUtil參數配置:

  1. import java.util.Map;
  2. import java.util.ResourceBundle;
  3. import java.util.SortedMap;
  4. import java.util.TreeMap;
  5. /**
  6. * 相關配置參數
  7. * 創建者 張志朋
  8. * 創建時間 2016年9月28日
  9. *
  10. */
  11. public class ConfigUtil {
  12. /**
  13. * 服務號相關信息
  14. */
  15. public final static String APP_ID = "2016";//服務號的應用ID
  16. public final static String APP_SECRET = "2016";//服務號的應用密鑰
  17. public final static String TOKEN = "weixinCourse";//服務號的配置token
  18. public final static String MCH_ID = "2016";//商戶號
  19. public final static String API_KEY = "2016";//API密鑰
  20. public final static String SIGN_TYPE = "MD5";//簽名加密方式
  21. public final static String CERT_PATH = "apiclient_cert.p12";//微信支付證書存放路徑地址
  22. static ResourceBundle resource = ResourceBundle.getBundle("config");
  23. //微信支付統一接口的回調action
  24. public final static String NOTIFY_URL = resource.getString("WEIXIN_NOTIFY_URL");
  25. /**
  26. * 微信基礎接口地址
  27. */
  28. //獲取token接口(GET)
  29. public final static String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
  30. //oauth2授權接口(GET)
  31. public final static String OAUTH2_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
  32. //刷新access_token接口(GET)
  33. public final static String REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
  34. // 菜單創建接口(POST)
  35. public final static String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
  36. // 菜單查詢(GET)
  37. public final static String MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
  38. // 菜單刪除(GET)
  39. public final static String MENU_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
  40. /**
  41. * 微信支付接口地址
  42. */
  43. //微信支付統一接口(POST)
  44. public final static String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
  45. //微信退款接口(POST)
  46. public final static String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
  47. //訂單查詢接口(POST)
  48. public final static String CHECK_ORDER_URL = "https://api.mch.weixin.qq.com/pay/orderquery";
  49. //關閉訂單接口(POST)
  50. public final static String CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/pay/closeorder";
  51. //退款查詢接口(POST)
  52. public final static String CHECK_REFUND_URL = "https://api.mch.weixin.qq.com/pay/refundquery";
  53. //對賬單接口(POST)
  54. public final static String DOWNLOAD_BILL_URL = "https://api.mch.weixin.qq.com/pay/downloadbill";
  55. //短鏈接轉換接口(POST)
  56. public final static String SHORT_URL = "https://api.mch.weixin.qq.com/tools/shorturl";
  57. //接口調用上報接口(POST)
  58. public final static String REPORT_URL = "https://api.mch.weixin.qq.com/payitil/report";
  59. public static void commonParams(SortedMap<Object, Object> packageParams){
  60. // 賬號信息
  61. String appid = ConfigUtil.APP_ID; // appid
  62. String mch_id = ConfigUtil.MCH_ID; // 商業號
  63. // 生成隨機字符串
  64. String currTime = PayCommonUtil.getCurrTime();
  65. String strTime = currTime.substring(8, currTime.length());
  66. String strRandom = PayCommonUtil.buildRandom(4) + "";
  67. String nonce_str = strTime + strRandom;
  68. packageParams.put("appid", appid);// 公眾賬號ID
  69. packageParams.put("mch_id", mch_id);// 商戶號
  70. packageParams.put("nonce_str", nonce_str);// 隨機字符串
  71. }
  72. /**
  73. * 該接口主要用於掃碼原生支付模式一中的二維碼鏈接轉成短鏈接(weixin://wxpay/s/XXXXXX),減小二維碼數據量,提升掃描速度和精確度。
  74. * @Author 張志朋
  75. * @param urlCode void
  76. * @Date 2016年10月26日
  77. * 更新日志
  78. * 2016年10月26日 張志朋 首次創建
  79. *
  80. */
  81. @SuppressWarnings("rawtypes")
  82. public static void shorturl(String urlCode){
  83. try {
  84. String key = ConfigUtil.API_KEY; // key
  85. SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
  86. ConfigUtil.commonParams(packageParams);
  87. packageParams.put("long_url", urlCode);// URL鏈接
  88. String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
  89. packageParams.put("sign", sign);// 簽名
  90. String requestXML = PayCommonUtil.getRequestXml(packageParams);
  91. String resXml = HttpUtil.postData(ConfigUtil.SHORT_URL, requestXML);
  92. Map map = XMLUtil.doXMLParse(resXml);
  93. String returnCode = (String) map.get("return_code");
  94. if("SUCCESS".equals(returnCode)){
  95. String resultCode = (String) map.get("return_code");
  96. if("SUCCESS".equals(resultCode)){
  97. urlCode = (String) map.get("short_url");
  98. }
  99. }
  100. } catch (Exception e) {
  101. e.printStackTrace();
  102. }
  103. }

參數必填項 APP_ID 和APP_SECRET 是從微信公眾號裡面獲取的,而MCH_ID和API_KEY是從商戶平台獲取的。CERT_PATH 證書可選,但是如果做退款接口必須要使用證書。NOTIFY_URL 為回調地址,自定義路徑,但是一定要微信平台可以調用到你的url。

如何生成二維碼訂單?

API文檔地址

文檔有詳細的參數說明,具體生成需要xml解析,這裡就不放了,好多的說,有需要的可以留言。

支付回調:

  1. /**
  2. * 二維碼支付
  3. * 創建者 張志朋
  4. * 創建時間 2016年10月31日
  5. *
  6. */
  7. @Controller
  8. @RequestMapping(value = "weixin")
  9. public class WeixinPayController {
  10. @Autowired
  11. private IWeixinPayService weixinpayBack;
  12. /**
  13. * 微信支付回調
  14. * @Author 張志朋
  15. * @param request
  16. * @param response
  17. * @throws Exception void
  18. * @Date 2016年9月28日
  19. * 更新日志
  20. * 2016年9月28日 張志朋 首次創建
  21. *
  22. */
  23. @SuppressWarnings({ "unchecked", "rawtypes" })
  24. @RequestMapping(value = "pay")
  25. public void weixin_notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
  26. LogUtil.info("支付成功回調");
  27. // 讀取參數
  28. InputStream inputStream = request.getInputStream();
  29. StringBuffer sb = new StringBuffer();
  30. String s;
  31. BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
  32. while ((s = in.readLine()) != null) {
  33. sb.append(s);
  34. }
  35. in.close();
  36. inputStream.close();
  37. // 解析xml成map
  38. Map<String, String> m = new HashMap<String, String>();
  39. m = XMLUtil.doXMLParse(sb.toString());
  40. // 過濾空 設置 TreeMap
  41. SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
  42. Iterator it = m.keySet().iterator();
  43. while (it.hasNext()) {
  44. String parameter = (String) it.next();
  45. String parameterValue = m.get(parameter);
  46. String v = "";
  47. if (null != parameterValue) {
  48. v = parameterValue.trim();
  49. }
  50. packageParams.put(parameter, v);
  51. }
  52. // 賬號信息
  53. String key = ConfigUtil.API_KEY; // key
  54. // 判斷簽名是否正確
  55. if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
  56. // ------------------------------
  57. // 處理業務開始
  58. // ------------------------------
  59. String resXml = "";
  60. if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
  61. // 這裡是支付成功
  62. String orderNo = (String) packageParams.get("out_trade_no");
  63. String attach = (String) packageParams.get("attach");
  64. //回調K12
  65. LogUtil.info(attach+"(訂單號:"+orderNo+"付款成功)");
  66. // 通知微信.異步確認成功.必寫.不然會一直通知後台.八次之後就認為交易失敗了.
  67. resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
  68. weixinpayBack.updateAccOrder(orderNo);
  69. } else {
  70. LogUtil.info("支付失敗,錯誤信息:" + packageParams.get("err_code"));
  71. resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[報文為空]]></return_msg>" + "</xml> ";
  72. }
  73. // ------------------------------
  74. // 處理業務完畢
  75. // ------------------------------
  76. BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
  77. out.write(resXml.getBytes());
  78. out.flush();
  79. out.close();
  80. } else {
  81. LogUtil.info("通知簽名驗證失敗");
  82. }
  83. }
  84. }

大體就這個樣子,後續的可能就是安全優化了。涉及到錢可不是小問題。

原文地址:http://blog.52itstyle.com/archives/180

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved