Java开发微信支付流程及容易入坑的点

本文详细介绍了Java开发微信支付的步骤,包括获取支付功能权限、配置支付授权目录、生成prepay_id、创建签名等关键环节,并着重指出在签名过程中易犯的错误,如I的大小写问题和参数一致性等。
摘要由CSDN通过智能技术生成

本人琢磨微信支付好几天了,终于完成了,下面是开发微信支付的流程:

1.先要有认证后的微信服务号,然后申请开通微信支付功能,通过之后,腾讯会跟你发一封邮件,如下图:

 2.配置好微信支付的支付授权目录(配置错误,支付时微信会返回:http://ki.hdh.com/kjjk/jh未注册错误)

3.我们要参照微信传的参数,如下图:

4.生成prepay_id(在WeiXinUtils工具类里)

String getPrepayId = WeiXinUtils.getPayOrderByWeiXin(openid,String.valueOf(sumPrice*100),userIp,url,body,num+timeStamp);

 

 
  1. public static String getPayOrderByWeiXin(String opentId, String total_fee, String userIp, String notifyUrl, String body, String orderNumber) {

  2. SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();

  3. parameters.put("appid", APP_ID);

  4. System.out.println("appid:"+APP_ID);

  5. parameters.put("mch_id", MCH_ID);

  6. System.out.println("mch_id:"+MCH_ID);

  7. parameters.put("nonce_str", nonceStr);

  8. System.out.println("nonce_str:"+"HZNAONAOCOM");

  9. parameters.put("body", body);

  10. System.out.println("body:"+body);

  11. parameters.put("out_trade_no", orderNumber);

  12. System.out.println("out_trade_no:"+orderNumber);

  13. parameters.put("total_fee", total_fee.substring(0, total_fee.indexOf(".")));

  14. System.out.println("total_fee="+total_fee.substring(0, total_fee.indexOf(".")));

  15. parameters.put("spbill_create_ip", userIp);

  16. System.out.println("spbill_create_ip="+userIp);

  17. parameters.put("notify_url",notifyUrl );

  18. System.out.println("notify_url="+notifyUrl);

  19. parameters.put("trade_type", "JSAPI");

  20. System.out.println("trade_type=JSAPI");

  21. parameters.put("openid", opentId);

  22. System.out.println("openid="+opentId);

  23. String sign = Sign.createSign("UTF-8", parameters);

  24. System.out.println("sign="+sign);

  25. parameters.put("sign", sign);

  26.  
  27. String requestXML = Utils.getRequestXml(parameters);

  28. System.out.println("requestXML="+requestXML);

  29. String result = PostRequest.httpsRequest(unifiedOrder, "POST", requestXML);

  30. System.out.println("prepay_id="+result);

  31. return getPrepayId(result);

  32. }

 

5.工具类

 

 
  1. package com.naonao.cmall.utils;

  2.  
  3. import java.io.UnsupportedEncodingException;

  4. import java.security.MessageDigest;

  5. import java.security.NoSuchAlgorithmException;

  6. import java.util.Formatter;

  7. import java.util.HashMap;

  8. import java.util.Iterator;

  9. import java.util.Map;

  10. import java.util.Set;

  11. import java.util.SortedMap;

  12. import java.util.UUID;

  13.  
  14. import org.springframework.cache.annotation.Cacheable;

  15.  
  16. import com.naonao.cmall.utils.http.HttpClient;

  17.  
  18. public class Sign {

  19.  
  20. @Cacheable(value="baseCache")

  21. public static String getToken() {

  22. String s = HttpClient.sendGet(

  23. "https://api.weixin.qq.com/cgi-bin/token",

  24. "grant_type=client_credential&appid=" + WeiXinUtils.APP_ID

  25. + "&secret=" + WeiXinUtils.APP_SECRET);

  26. HashMap<String, Object> json = JsonUtil.stringToTObj(s, HashMap.class);

  27. String token = json.get("access_token").toString();

  28.  
  29. return token;

  30. }

  31.  
  32. @Cacheable(value="baseCache")

  33. public static String getTicket() {

  34. String token = Sign.getToken();

  35.  
  36. String s1 = HttpClient.sendGet(

  37. "https://api.weixin.qq.com/cgi-bin/ticket/getticket",

  38. "access_token=" + token + "&type=jsapi");

  39. HashMap<String, Object> json1 = JsonUtil

  40. .stringToTObj(s1, HashMap.class);

  41. return json1.get("ticket").toString();

  42. }

  43.  
  44. public static String getNonceStr() {

  45. return create_timestamp();

  46. }

  47.  
  48. //chatSet SHA-1 or MD5

  49. public static Map<String, String> sign(String url, String chatSet) {

  50. Map<String, String> ret = new HashMap<String, String>();

  51. String nonce_str = create_nonce_str();

  52. String timestamp = create_timestamp();

  53. String string1;

  54. String signature = "";

  55. String jsapi_ticket = getTicket();

  56.  
  57. // 注意这里参数名必须全部小写,且必须有序

  58. string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str

  59. + "×tamp=" + timestamp + "&url=" + url;

  60. // System.out.println(string1);

  61.  
  62. try {

  63. MessageDigest crypt = MessageDigest.getInstance(chatSet);

  64. crypt.reset();

  65. crypt.update(string1.getBytes("UTF-8"));

  66. signature = byteToHex(crypt.digest());

  67. } catch (NoSuchAlgorithmException e) {

  68. e.printStackTrace();

  69. } catch (UnsupportedEncodingException e) {

  70. e.printStackTrace();

  71. }

  72.  
  73. ret.put("url", url);

  74. ret.put("jsapi_ticket", jsapi_ticket);

  75. ret.put("nonceStr", nonce_str);

  76. ret.put("timestamp", timestamp);

  77. ret.put("signature", signature);

  78. for (Map.Entry entry : ret.entrySet()) {

  79. System.out.println(entry.getKey() + ", " + entry.getValue());

  80. }

  81. return ret;

  82. }

  83.  
  84. private static String byteToHex(final byte[] hash) {

  85. Formatter formatter = new Formatter();

  86. for (byte b : hash) {

  87. formatter.format("%02x", b);

  88. }

  89. String result = formatter.toString();

  90. formatter.close();

  91. return result;

  92. }

  93.  
  94. private static String create_nonce_str() {

  95. return UUID.randomUUID().toString();

  96. }

  97.  
  98. private static String create_timestamp() {

  99. return Long.toString(System.currentTimeMillis() / 1000);

  100. }

  101.  
  102. public static String createSign(String characterEncoding, SortedMap<Object, Object> parameters) {

  103. StringBuffer sb = new StringBuffer();

  104. Set es = parameters.entrySet();

  105. Iterator it = es.iterator();

  106. while (it.hasNext()) {

  107. Map.Entry entry = (Map.Entry) it.next();

  108. String k = (String) entry.getKey();

  109. Object v = entry.getValue();

  110. if (null != v && !"".equals(v) && !"sign".equals(k)

  111. && !"key".equals(k)) {

  112. sb.append(k + "=" + v + "&");

  113. }

  114. }

  115. sb.append("key=" + WeiXinUtils.APP_KEY);

  116. String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();

  117. return sign;

  118. }

  119.  
  120. public static String paySign(String characterEncoding, SortedMap<Object, Object> parameters) {

  121. StringBuffer sb = new StringBuffer();

  122. Set es = parameters.entrySet();

  123. Iterator it = es.iterator();

  124. while (it.hasNext()) {

  125. Map.Entry entry = (Map.Entry) it.next();

  126. String k = (String) entry.getKey();

  127. Object v = entry.getValue();

  128. if (null != v && !"".equals(v) && !"sign".equals(k)

  129. && !"key".equals(k)) {

  130. sb.append(k + "=" + v + "&");

  131. }

  132. }

  133. //sb.replace(sb.length()-1, sb.length(), "?");

  134. sb.append("key=" + WeiXinUtils.APP_KEY);

  135. //sb.append("params=value");

  136. System.out.println(sb);

  137. String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();

  138. return sign;

  139. }

  140. }

 
  1. package com.naonao.cmall.utils;

  2.  
  3. import java.io.UnsupportedEncodingException;

  4. import java.lang.reflect.Method;

  5. import java.math.BigDecimal;

  6. import java.security.MessageDigest;

  7. import java.security.NoSuchAlgorithmException;

  8. import java.text.DecimalFormat;

  9. import java.text.SimpleDateFormat;

  10. import java.util.Arrays;

  11. import java.util.Calendar;

  12. import java.util.Collection;

  13. import java.util.Date;

  14. import java.util.Iterator;

  15. import java.util.List;

  16. import java.util.Map;

  17. import java.util.Random;

  18. import java.util.Set;

  19. import java.util.SortedMap;

  20.  
  21. import javax.servlet.http.HttpServletRequest;

  22.  
  23. public class Utils {

  24. // MD5加密

  25. public static String getMd5(String plainText) {

  26. try {

  27. MessageDigest md = MessageDigest.getInstance("MD5");

  28. md.update(plainText.getBytes());

  29. byte b[] = md.digest();

  30.  
  31. int i;

  32.  
  33. StringBuffer buf = new StringBuffer("");

  34. for (int offset = 0; offset < b.length; offset++) {

  35. i = b[offset];

  36. if (i < 0)

  37. i += 256;

  38. if (i < 16)

  39. buf.append("0");

  40. buf.append(Integer.toHexString(i));

  41. }

  42. // 32

  43. return buf.toString();

  44. // 16

  45. // return buf.toString().substring(8, 24);

  46. } catch (NoSuchAlgorithmException e) {

  47. e.printStackTrace();

  48. return null;

  49. }

  50.  
  51. }

  52.  
  53. public static String getRemortIP(HttpServletRequest request) {

  54. if (request.getHeader("x-forwarded-for") == null) {

  55. return request.getRemoteAddr();

  56. }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值