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

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

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. }

  57. return request.getHeader("x-forwarded-for");

  58. }

  59.  
  60. public static String encode(String str) {

  61. try {

  62. return java.net.URLEncoder.encode(str, "UTF-8");

  63. } catch (UnsupportedEncodingException e) {

  64. // TODO Auto-generated catch block

  65. e.printStackTrace();

  66. }

  67. return str;

  68. }

  69.  
  70. public static String getRequestXml(SortedMap<Object, Object> parameters) {

  71. StringBuffer sb = new StringBuffer();

  72. sb.append("<xml>");

  73. Set es = parameters.entrySet();

  74. Iterator it = es.iterator();

  75. while (it.hasNext()) {

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

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

  78. String v = (String) entry.getValue();

  79. if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k)

  80. || "sign".equalsIgnoreCase(k)) {

  81. sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");

  82. } else {

  83. sb.append("<" + k + ">" + v + "</" + k + ">");

  84. }

  85. }

  86. sb.append("</xml>");

  87. return sb.toString();

  88. }

  89.  
  90. public static String getOutTradeNo(Integer userId, Integer shopId) {

  91. return userId + "c" + shopId + "c" + (new Date()).getTime();

  92. }

  93.  
  94. /**

  95. * 利用反射实现对象之间属性复制

  96. *

  97. * @param from

  98. * @param to

  99. */

  100. public static void copyProperties(Object from, Object to) throws Exception {

  101. copyPropertiesExclude(from, to, null);

  102. }

  103.  
  104. /**

  105. * 复制对象属性

  106. *

  107. * @param from

  108. * @param to

  109. * @param excludsArray

  110. * 排除属性列表

  111. * @throws Exception

  112. */

  113. public static void copyPropertiesExclude(Object from, Object to,

  114. String[] excludsArray) throws Exception {

  115. List<String> excludesList = null;

  116. if (excludsArray != null && excludsArray.length > 0) {

  117. excludesList = Arrays.asList(excludsArray); // 构造列表对象

  118. }

  119. Method[] fromMethods = from.getClass().getDeclaredMethods();

  120. Method[] toMethods = to.getClass().getDeclaredMethods();

  121. Method fromMethod = null, toMethod = null;

  122. String fromMethodName = null, toMethodName = null;

  123. for (int i = 0; i < fromMethods.length; i++) {

  124. fromMethod = fromMethods[i];

  125. fromMethodName = fromMethod.getName();

  126. if (!fromMethodName.contains("get"))

  127. continue;

  128. // 排除列表检测

  129. if (excludesList != null

  130. && excludesList.contains(fromMethodName.substring(3)

  131. .toLowerCase())) {

  132. continue;

  133. }

  134. toMethodName = "set" + fromMethodName.substring(3);

  135. toMethod = findMethodByName(toMethods, toMethodName);

  136. if (toMethod == null)

  137. continue;

  138. Object value = fromMethod.invoke(from, new Object[0]);

  139. if (value == null)

  140. continue;

  141. // 集合类判空处理

  142. if (value instanceof Collection) {

  143. Collection newValue = (Collection) value;

  144. if (newValue.size() <= 0)

  145. continue;

  146. }

  147. toMethod.invoke(to, new Object[] { value });

  148. }

  149. }

  150.  
  151. /**

  152. * 对象属性值复制,仅复制指定名称的属性值

  153. *

  154. * @param from

  155. * @param to

  156. * @param includsArray

  157. * @throws Exception

  158. */

  159. public static void copyPropertiesInclude(Object from, Object to,

  160. String[] includsArray) throws Exception {

  161. List<String> includesList = null;

  162. if (includsArray != null && includsArray.length > 0) {

  163. includesList = Arrays.asList(includsArray); // 构造列表对象

  164. } else {

  165. return;

  166. }

  167. Method[] fromMethods = from.getClass().getDeclaredMethods();

  168. Method[] toMethods = to.getClass().getDeclaredMethods();

  169. Method fromMethod = null, toMethod = null;

  170. String fromMethodName = null, toMethodName = null;

  171. for (int i = 0; i < fromMethods.length; i++) {

  172. fromMethod = fromMethods[i];

  173. fromMethodName = fromMethod.getName();

  174. if (!fromMethodName.contains("get"))

  175. continue;

  176. // 排除列表检测

  177. String str = fromMethodName.substring(3);

  178. if (!includesList.contains(str.substring(0, 1).toLowerCase()

  179. + str.substring(1))) {

  180. continue;

  181. }

  182. toMethodName = "set" + fromMethodName.substring(3);

  183. toMethod = findMethodByName(toMethods, toMethodName);

  184. if (toMethod == null)

  185. continue;

  186. Object value = fromMethod.invoke(from, new Object[0]);

  187. if (value == null)

  188. continue;

  189. // 集合类判空处理

  190. if (value instanceof Collection) {

  191. Collection newValue = (Collection) value;

  192. if (newValue.size() <= 0)

  193. continue;

  194. }

  195. toMethod.invoke(to, new Object[] { value });

  196. }

  197. }

  198.  
  199. /**

  200. * 从方法数组中获取指定名称的方法

  201. *

  202. * @param methods

  203. * @param name

  204. * @return

  205. */

  206. public static Method findMethodByName(Method[] methods, String name) {

  207. for (int j = 0; j < methods.length; j++) {

  208. if (methods[j].getName().equals(name))

  209. return methods[j];

  210. }

  211. return null;

  212. }

  213.  
  214. /**

  215. * map 转 Bean

  216. *

  217. * @param map

  218. * @param cls

  219. * @return

  220. */

  221. public static Object map2Bean(Map map, Class cls) {

  222. Object obj = null;

  223. try {

  224. obj = cls.newInstance();

  225. } catch (Exception e) {

  226. e.printStackTrace();

  227. }

  228. // 取出bean里的所有方法

  229. Method[] methods = cls.getMethods();

  230. for (int i = 0; i < methods.length; i++) {

  231. // 取方法名

  232. String method = methods[i].getName();

  233. // 取出方法的类型

  234. Class[] cc = methods[i].getParameterTypes();

  235. if (cc.length != 1)

  236. continue;

  237.  
  238. // 如果方法名没有以set开头的则退出本次for

  239. if (method.indexOf("set") < 0)

  240. continue;

  241. // 类型

  242. String type = cc[0].getSimpleName();

  243.  
  244. try {

  245. // 转成小写

  246. // Object value = method.substring(3).toLowerCase();

  247. Object value = method.substring(3, 4).toLowerCase()

  248. + method.substring(4);

  249. // 如果map里有该key

  250. if (map.containsKey(value) && map.get(value) != null) {

  251. // 调用其底层方法

  252. setValue(type, map.get(value), i, methods, obj);

  253. }

  254. } catch (Exception e) {

  255. e.printStackTrace();

  256. }

  257. }

  258. return obj;

  259. }

  260.  
  261. /**

  262. * 调用底层方法设置值

  263. */

  264. private static void setValue(String type, Object value, int i,

  265. Method[] method, Object bean) {

  266. if (value != null && !value.equals("")) {

  267. try {

  268. if (type.equals("String")) {

  269. // 第一个参数:从中调用基础方法的对象 第二个参数:用于方法调用的参数

  270. method[i].invoke(bean, new Object[] { value });

  271. } else if (type.equals("int") || type.equals("Integer")) {

  272. method[i].invoke(bean, new Object[] { new Integer(""

  273. + value) });

  274. } else if (type.equals("double") || type.equals("Double")) {

  275. method[i].invoke(bean,

  276. new Object[] { new Double("" + value) });

  277. } else if (type.equals("float") || type.equals("Float")) {

  278. method[i].invoke(bean,

  279. new Object[] { new Float("" + value) });

  280. } else if (type.equals("long") || type.equals("Long")) {

  281. method[i].invoke(bean,

  282. new Object[] { new Long("" + value) });

  283. } else if (type.equals("boolean") || type.equals("Boolean")) {

  284. method[i].invoke(bean,

  285. new Object[] { Boolean.valueOf("" + value) });

  286. } else if (type.equals("BigDecimal")) {

  287. method[i].invoke(bean, new Object[] { new BigDecimal(""

  288. + value) });

  289. } else if (type.equals("Date")) {

  290. Date date = null;

  291. if (value.getClass().getName().equals("java.util.Date")) {

  292. date = (Date) value;

  293. } else {

  294. String format = ((String) value).indexOf(":") > 0 ? "yyyy-MM-dd hh:mm:ss"

  295. : "yyyy-MM-dd";

  296. SimpleDateFormat sf = new SimpleDateFormat();

  297. sf.applyPattern(format);

  298. date = sf.parse((String) (value));

  299. }

  300. if (date != null) {

  301. method[i].invoke(bean, new Object[] { date });

  302. }

  303. } else if (type.equals("byte[]")) {

  304. method[i].invoke(bean,

  305. new Object[] { new String(value + "").getBytes() });

  306. }

  307. } catch (Exception e) {

  308. System.out

  309. .println("将linkHashMap 或 HashTable 里的值填充到javabean时出错,请检查!");

  310. e.printStackTrace();

  311. }

  312. }

  313. }

  314.  
  315. /** 计算年龄 */

  316. public static String getAge(Date birthDay) throws Exception {

  317. Calendar cal = Calendar.getInstance();

  318.  
  319. if (cal.before(birthDay)) {

  320. throw new IllegalArgumentException(

  321. "The birthDay is before Now.It's unbelievable!");

  322. }

  323.  
  324. int yearNow = cal.get(Calendar.YEAR);

  325. int monthNow = cal.get(Calendar.MONTH) + 1;

  326. int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);

  327.  
  328. cal.setTime(birthDay);

  329. int yearBirth = cal.get(Calendar.YEAR);

  330. int monthBirth = cal.get(Calendar.MONTH);

  331. int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

  332.  
  333. int age = yearNow - yearBirth;

  334.  
  335. if (monthNow <= monthBirth) {

  336. if (monthNow == monthBirth) {

  337. // monthNow==monthBirth

  338. if (dayOfMonthNow < dayOfMonthBirth) {

  339. age--;

  340. }

  341. } else {

  342. // monthNow>monthBirth

  343. age--;

  344. }

  345. }

  346.  
  347. return age + "";

  348. }

  349.  
  350. public static String getStringByFloat(Float d1) {

  351. DecimalFormat Formator = new DecimalFormat("###.##");

  352. return Formator.format(d1);

  353. }

  354. }

 
  1. package com.naonao.cmall.utils.http;

  2.  
  3. import java.io.BufferedReader;

  4. import java.io.DataOutputStream;

  5. import java.io.IOException;

  6. import java.io.InputStream;

  7. import java.io.InputStreamReader;

  8. import java.io.OutputStream;

  9. import java.io.OutputStreamWriter;

  10. import java.net.ConnectException;

  11. import java.net.HttpURLConnection;

  12. import java.net.URL;

  13. import java.net.URLConnection;

  14. import java.util.HashMap;

  15. import java.util.Map;

  16.  
  17. import javax.net.ssl.HttpsURLConnection;

  18. import javax.net.ssl.SSLContext;

  19. import javax.net.ssl.SSLSocketFactory;

  20. import javax.net.ssl.TrustManager;

  21.  
  22. import org.slf4j.Logger;

  23. import org.slf4j.LoggerFactory;

  24.  
  25. import com.alibaba.fastjson.JSONObject;

  26. import com.naonao.cmall.utils.MyX509TrustManager;

  27. public class PostRequest {

  28.  
  29. private static final Logger log = LoggerFactory

  30. .getLogger(PostRequest.class);

  31. public static String GET_URL = "";

  32.  
  33. public static String POST_URL = "";

  34.  
  35. public static String readContentFromGet() throws IOException {

  36. String getURL = GET_URL;

  37. URL getUrl = new URL(getURL);

  38. // 根据拼凑的URL,打开连接,URL.openConnection函数会根据URL的类型,

  39. // 返回不同的URLConnection子类的对象,这里URL是一个http,因此实际返回的是HttpURLConnection

  40. HttpURLConnection connection = (HttpURLConnection) getUrl

  41. .openConnection();

  42. // 进行连接,但是实际上get request要在下一句的connection.getInputStream()函数中才会真正发到

  43. // 服务器

  44. connection.connect();

  45. // 取得输入流,并使用Reader读取

  46. BufferedReader reader = new BufferedReader(new InputStreamReader(

  47. connection.getInputStream(), "utf-8"));// 设置编码,否则中文乱码

  48. String line = "";

  49. String lines = "";

  50. while ((line = reader.readLine()) != null) {

  51. // line = new String(line.getBytes(), "utf-8");

  52. lines += line.trim();

  53. }

  54. reader.close();

  55. // 断开连接

  56. connection.disconnect();

  57. return lines;

  58. }

  59.  
  60. public static void contentFromGet() throws IOException {

  61. String getURL = GET_URL;

  62. URL getUrl = new URL(getURL);

  63. // 根据拼凑的URL,打开连接,URL.openConnection函数会根据URL的类型,

  64. // 返回不同的URLConnection子类的对象,这里URL是一个http,因此实际返回的是HttpURLConnection

  65. HttpURLConnection connection = (HttpURLConnection) getUrl

  66. .openConnection();

  67. // 进行连接,但是实际上get request要在下一句的connection.getInputStream()函数中才会真正发到

  68. // 服务器

  69. connection.connect();

  70. }

  71.  
  72. public static String readContentFromPost() throws IOException {

  73. // Post请求的url,与get不同的是不需要带参数

  74. URL postUrl = new URL(POST_URL);

  75. // 打开连接

  76. HttpURLConnection connection = (HttpURLConnection) postUrl

  77. .openConnection();

  78. // Output to the connection. Default is

  79. // false, set to true because post

  80. // method must write something to the

  81. // connection

  82. // 设置是否向connection输出,因为这个是post请求,参数要放在

  83. // http正文内,因此需要设为true

  84. connection.setDoOutput(true);

  85. // Read from the connection. Default is true.

  86. connection.setDoInput(true);

  87. // Set the post method. Default is GET

  88. connection.setRequestMethod("POST");

  89. // Post cannot use caches

  90. // Post 请求不能使用缓存

  91. connection.setUseCaches(false);

  92. // This method takes effects to

  93. // every instances of this class.

  94. // URLConnection.setFollowRedirects是static函数,作用于所有的URLConnection对象。

  95. // connection.setFollowRedirects(true);

  96.  
  97. // This methods only

  98. // takes effacts to this

  99. // instance.

  100. // URLConnection.setInstanceFollowRedirects是成员函数,仅作用于当前函数

  101. connection.setInstanceFollowRedirects(true);

  102. // Set the content type to urlencoded,

  103. // because we will write

  104. // some URL-encoded content to the

  105. // connection. Settings above must be set before connect!

  106. // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的

  107. // 意思是正文是urlencoded编码过的form参数,下面我们可以看到我们对正文内容使用URLEncoder.encode

  108. // 进行编码

  109. connection.setRequestProperty("Content-Type",

  110. "application/x-www-form-urlencoded");

  111. // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,

  112. // 要注意的是connection.getOutputStream会隐含的进行connect。

  113. connection.connect();

  114. DataOutputStream out = new DataOutputStream(

  115. connection.getOutputStream());

  116. // The URL-encoded contend

  117. // 正文,正文内容其实跟get的URL中'?'后的参数字符串一致

  118. // String content =

  119. // "key=j0r53nmbbd78x7m1pqml06u2&type=1&[email protected]" +

  120. // "&activatecode=" + URLEncoder.encode("久酷博客", "utf-8");

  121. // DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写道流里面

  122. // out.writeBytes(content);

  123. out.flush();

  124. out.close(); // flush and close

  125. BufferedReader reader = new BufferedReader(new InputStreamReader(

  126. connection.getInputStream(), "utf-8"));// 设置编码,否则中文乱码

  127. String line = "";

  128. String lines = "";

  129. while ((line = reader.readLine()) != null) {

  130. // line = new String(line.getBytes(), "utf-8");

  131. lines += line.trim();

  132. }

  133. reader.close();

  134. connection.disconnect();

  135. return lines;

  136. }

  137.  
  138. /**

  139. * 经纬度

  140. *

  141. * @param lng

  142. * @param lat

  143. * @return

  144. */

  145. public static Map<String, String> getAddressByLatlat(String lng, String lat) {

  146. String str = "http://api.map.baidu.com/geocoder?output=json&location="

  147. + lat + "," + lng + "&key=37492c0ee6f924cb5e934fa08c6b167";

  148. Map<String, String> map = new HashMap<String, String>();

  149. try {

  150. PostRequest.POST_URL = str;

  151. String line = PostRequest.readContentFromPost();

  152. JSONObject jsonObj = JSONObject.parseObject(line);

  153. String result = jsonObj.getString("result");

  154. JSONObject jsonObj2 = JSONObject.parseObject(result);

  155. String cityCode = jsonObj2.getString("cityCode");

  156. String formattedAddress = jsonObj2.getString("formatted_address");

  157. JSONObject jsonObj3 = JSONObject.parseObject(jsonObj2

  158. .getString("addressComponent"));

  159. String city = jsonObj3.getString("city");

  160. map.put("cityCode", cityCode);

  161. map.put("formattedAddress", formattedAddress);

  162. map.put("city", city);

  163. } catch (IOException e) {

  164. e.printStackTrace();

  165. }

  166. return map;

  167. }

  168.  
  169. /**

  170. * 城市

  171. *

  172. * @param city

  173. * @return

  174. */

  175. public static Map<String, String> getAddressByCity(String city) {

  176. String str = "http://api.map.baidu.com/geocoder/v2/?ak=E4805d16520de693a3fe707cdc962045&callback=renderOption&output=json&address="

  177. + city + "&city=" + city;

  178. Map<String, String> map = new HashMap<String, String>();

  179. try {

  180. PostRequest.POST_URL = str;

  181. String line = PostRequest.readContentFromPost();

  182. JSONObject jsonObj = JSONObject.parseObject(line);

  183. String result = jsonObj.getString("result");

  184. JSONObject jsonObj2 = JSONObject.parseObject(result);

  185. String cityCode = jsonObj2.getString("cityCode");

  186. String formattedAddress = jsonObj2.getString("formatted_address");

  187. map.put("cityCode", cityCode);

  188. map.put("formattedAddress", formattedAddress);

  189. map.put("city", city);

  190. } catch (IOException e) {

  191. e.printStackTrace();

  192. }

  193. return map;

  194. }

  195.  
  196. /**

  197. * 城市

  198. *

  199. * @param city

  200. * @return

  201. */

  202. public static Map<String, String> getQQMessages(String access_token,

  203. String openid) {

  204. String qqUrl = "https://graph.qq.com/user/get_user_info?oauth_consumer_key=100330589&access_token="

  205. + access_token + "&openid=" + openid + "&format=json";

  206. Map<String, String> map = new HashMap<String, String>();

  207. try {

  208. PostRequest.GET_URL = qqUrl;

  209. String line = PostRequest.readContentFromGet();

  210. JSONObject jsonObj = JSONObject.parseObject(line);

  211. String nickname = jsonObj.getString("nickname");

  212. String gender = jsonObj.getString("gender");

  213. String url = jsonObj.getString("figureurl_qq_1");

  214. map.put("nickname", nickname);

  215. map.put("gender", gender);

  216. map.put("url", url);

  217. map.put("openid", openid);

  218. } catch (IOException e) {

  219. e.printStackTrace();

  220. }

  221. return map;

  222. }

  223.  
  224. public static void main(String[] args) {

  225. PostRequest.GET_URL="http://mc-storage.b0.upaiyun.com/song_lib/lrc/20140702/Y2014060133.txt";

  226. String line;

  227. try {

  228. line = PostRequest.readContentFromGet();

  229. System.out.println(line);

  230. } catch (IOException e) {

  231. e.printStackTrace();

  232. }

  233. }

  234.  
  235.  
  236. /**

  237. * 用传统的URI类进行请求

  238. * @param urlStr

  239. */

  240. public static String post(String urlStr,String xmlInfo) {

  241. String line = "";

  242. try {

  243. URL url = new URL(urlStr);

  244. URLConnection con = url.openConnection();

  245. con.setDoOutput(true);

  246. con.setRequestProperty("Pragma:", "no-cache");

  247. con.setRequestProperty("Cache-Control", "no-cache");

  248. con.setRequestProperty("Content-Type", "text/xml");

  249.  
  250. OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());

  251. // System.out.println("xmlInfo=" + xmlInfo);

  252. out.write(new String(xmlInfo.getBytes("UTF-8")));

  253. out.flush();

  254. out.close();

  255. BufferedReader br = new BufferedReader(new InputStreamReader(con

  256. .getInputStream()));

  257. for (line = br.readLine(); line != null; line = br.readLine()) {

  258. line+=line;

  259. }

  260. } catch (Exception e) {

  261. e.printStackTrace();

  262. }

  263. return line;

  264. }

  265.  
  266. /**

  267. * 发送https请求

  268. * @param requestUrl 请求地址

  269. * @param requestMethod 请求方式(GET、POST)

  270. * @param outputStr 提交的数据

  271. * @return 返回微信服务器响应的信息

  272. */

  273. public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {

  274. try {

  275. // 创建SSLContext对象,并使用我们指定的信任管理器初始化

  276. TrustManager[] tm = { new MyX509TrustManager() };

  277. SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");

  278. sslContext.init(null, tm, new java.security.SecureRandom());

  279. // 从上述SSLContext对象中得到SSLSocketFactory对象

  280. SSLSocketFactory ssf = sslContext.getSocketFactory();

  281. URL url = new URL(requestUrl);

  282. HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();

  283. conn.setSSLSocketFactory(ssf);

  284. conn.setDoOutput(true);

  285. conn.setDoInput(true);

  286. conn.setUseCaches(false);

  287. // 设置请求方式(GET/POST)

  288. conn.setRequestMethod(requestMethod);

  289. conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");

  290. // 当outputStr不为null时向输出流写数据

  291. if (null != outputStr) {

  292. OutputStream outputStream = conn.getOutputStream();

  293. // 注意编码格式

  294. outputStream.write(outputStr.getBytes("UTF-8"));

  295. outputStream.close();

  296. }

  297. // 从输入流读取返回内容

  298. InputStream inputStream = conn.getInputStream();

  299. InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");

  300. BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

  301. String str = null;

  302. StringBuffer buffer = new StringBuffer();

  303. while ((str = bufferedReader.readLine()) != null) {

  304. buffer.append(str);

  305. }

  306. // 释放资源

  307. bufferedReader.close();

  308. inputStreamReader.close();

  309. inputStream.close();

  310. inputStream = null;

  311. conn.disconnect();

  312. return buffer.toString();

  313. } catch (ConnectException ce) {

  314. log.error("连接超时:{}", ce);

  315. } catch (Exception e) {

  316. log.error("https请求异常:{}", e);

  317. }

  318. return null;

  319. }

  320.  
  321. /**

  322. * 发送HttpPost请求

  323. *

  324. * @param strURL

  325. * 服务地址

  326. * @param params

  327. * json字符串,例如: "{ \"id\":\"12345\" }" ;其中属性名必须带双引号<br/>

  328. * @return 成功:返回json字符串<br/>

  329. */

  330. public static String postByJson(String strURL, String params) {

  331. System.out.println(strURL);

  332. System.out.println(params);

  333. try {

  334. URL url = new URL(strURL);// 创建连接

  335. HttpURLConnection connection = (HttpURLConnection) url

  336. .openConnection();

  337. connection.setDoOutput(true);

  338. connection.setDoInput(true);

  339. connection.setUseCaches(false);

  340. connection.setInstanceFollowRedirects(true);

  341. connection.setRequestMethod("POST"); // 设置请求方式

  342. connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式

  343. connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式

  344. connection.connect();

  345. OutputStreamWriter out = new OutputStreamWriter(

  346. connection.getOutputStream(), "UTF-8"); // utf-8编码

  347. out.append(params);

  348. out.flush();

  349. out.close();

  350. // 读取响应

  351. int length = (int) connection.getContentLength();// 获取长度

  352. InputStream is = connection.getInputStream();

  353. if (length != -1) {

  354. byte[] data = new byte[length];

  355. byte[] temp = new byte[512];

  356. int readLen = 0;

  357. int destPos = 0;

  358. while ((readLen = is.read(temp)) > 0) {

  359. System.arraycopy(temp, 0, data, destPos, readLen);

  360. destPos += readLen;

  361. }

  362. String result = new String(data, "UTF-8"); // utf-8编码

  363. System.out.println(result);

  364. return result;

  365. }

  366. } catch (IOException e) {

  367. // TODO Auto-generated catch block

  368. e.printStackTrace();

  369. }

  370. return "error"; // 自定义错误信息

  371. }

  372.  
  373. }

 
  1. package com.naonao.cmall.utils;

  2.  
  3. import java.io.IOException;

  4. import java.net.URLEncoder;

  5. import java.text.SimpleDateFormat;

  6. import java.util.Date;

  7. import java.util.HashMap;

  8. import java.util.Map;

  9. import java.util.SortedMap;

  10. import java.util.TreeMap;

  11.  
  12. import org.jdom.JDOMException;

  13. import org.slf4j.Logger;

  14. import org.slf4j.LoggerFactory;

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

  17. import com.naonao.cmall.utils.http.PostRequest;

  18.  
  19. public class WeiXinUtils {

  20. private static final Logger log = LoggerFactory.getLogger(WeiXinUtils.class);

  21.  
  22. /** 微信开发平台应用appid */

  23. public static final String APP_ID = "***";

  24.  
  25. /**

  26. *

  27. */

  28. //public static final String noncestr="***";

  29. /** 微信开发平台应用appsecret */

  30. public static final String APP_SECRET = "***";

  31. /**

  32. * 随机字符串

  33. */

  34. public static final String nonceStr="***";

  35.  
  36. /** 商户号 */

  37. public static final String MCH_ID = "***";

  38.  
  39. // 应用对应的密钥

  40. public static final String APP_KEY = "***";

  41.  
  42. // 微信公众号api

  43. public static final String REDIRECT_URI = "***"; // 授权回调

  44. public static final String PAY_URI = "***";// 支付回调

  45. public static final String SCOPE = "snsapi_userinfo";

  46. public static String GetOpenIdRequest = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&grant_type=authorization_code";

  47. public static String unifiedOrder = "https://api.mch.weixin.qq.com/pay/unifiedorder";

  48.  
  49. /**

  50. * weixin地址封装

  51. *

  52. * @return

  53. */

  54. public static String getCodeRequest(String url) {

  55. String GetCodeRequest = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";

  56.  
  57. String result = null;

  58. GetCodeRequest = GetCodeRequest.replace("APPID", urlEnodeUTF8(APP_ID));

  59. GetCodeRequest = GetCodeRequest.replace("SCOPE", SCOPE);

  60. GetCodeRequest = GetCodeRequest.replace("REDIRECT_URI", urlEnodeUTF8(REDIRECT_URI));

  61. GetCodeRequest = GetCodeRequest.replace("STATE", url);

  62. result = GetCodeRequest;

  63. log.info("================================");

  64. log.info(url);

  65. log.info(GetCodeRequest);

  66. log.info("================================");

  67. return result;

  68. }

  69.  
  70. /**

  71. * weixin地址封装

  72. *

  73. * @return

  74. */

  75. public static String getOpenIdRequest() {

  76. String result = null;

  77. GetOpenIdRequest = GetOpenIdRequest.replace("APPID", urlEnodeUTF8(APP_ID));

  78. GetOpenIdRequest = GetOpenIdRequest.replace("SECRET", urlEnodeUTF8(APP_SECRET));

  79. result = GetOpenIdRequest;

  80. return result;

  81. }

  82.  
  83. /**

  84. * 链接转码

  85. *

  86. * @param str

  87. * @return

  88. */

  89. public static String urlEnodeUTF8(String str) {

  90. String result = str;

  91. try {

  92. result = URLEncoder.encode(str, "UTF-8");

  93. } catch (Exception e) {

  94. log.error("WeiXinUtils getCodeRequest urlEnodeUTF8:{}", str);

  95. e.printStackTrace();

  96. }

  97. return result;

  98. }

  99.  
  100. /**

  101. * 通过code获取openId

  102. *

  103. * @param codeResult

  104. * @return

  105. */

  106. public static String getOpenId(String codeResult) {

  107. String openid = "";

  108. try {

  109. String openIdUrl = WeiXinUtils.getOpenIdRequest();

  110. PostRequest.GET_URL = openIdUrl + "&code=" + codeResult;

  111. String s = PostRequest.readContentFromGet();

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

  114. if (json != null && json.get("openid") != null) {

  115. openid = json.get("openid").toString();

  116. }

  117. } catch (IOException e) {

  118. e.printStackTrace();

  119. }

  120. return openid;

  121. }

  122.  
  123. /**

  124. * 微信支付

  125. *

  126. * @param opentId

  127. * @param total_fee

  128. * @param userIp

  129. * @param notifyUrl

  130. * @param body

  131. * @param orderNumber

  132. * @return

  133. */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  159.  
  160. String requestXML = Utils.getRequestXml(parameters);

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

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

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

  164. return getPrepayId(result);

  165. }

  166.  
  167.  
  168. /*

  169. * paySign

  170. */

  171. public static String getPaySignByWeiXin(String timeStamp, String nonceStr, String _package) {

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

  173. parameters.put("appId", APP_ID);

  174. System.out.println("appId="+APP_ID);

  175. parameters.put("timeStamp", timeStamp);

  176. System.out.println("timeStamp="+timeStamp);

  177. parameters.put("nonceStr", nonceStr);

  178. System.out.println("nonceStr="+nonceStr);

  179. parameters.put("package", _package);

  180. System.out.println("package="+_package);

  181. parameters.put("signType", "MD5");

  182. System.out.println("signType=MD5");

  183. //parameters.put("key", APP_KEY);

  184. String sign = Sign.paySign("UTF-8", parameters);

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

  186. return sign;

  187. }

  188.  
  189. private static String getPrepayId(String xml) {

  190. String prepay_id = "";

  191. try {

  192. Map map = XMLUtil.doXMLParse(xml);

  193. prepay_id = map.get("prepay_id").toString();

  194. } catch (JDOMException e) {

  195. e.printStackTrace();

  196. } catch (IOException e) {

  197. e.printStackTrace();

  198. }

  199. return prepay_id;

  200. }

  201.  
  202. /**

  203. * 微信下载文件

  204. *

  205. * @param name 本地文件名称

  206. * @param media_id 微信图片ID

  207. * @return

  208. */

  209. public static String downloadFile(String name,String media_id) {

  210. String downloadFile="http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";

  211. String token=Sign.getToken();

  212. downloadFile=downloadFile.replace("ACCESS_TOKEN", token);

  213. downloadFile=downloadFile.replace("MEDIA_ID", media_id);

  214. String path=Config.getMediaImgPath();

  215. Date now = new Date();

  216. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");

  217. path+=dateFormat.format(now)+"/"+name;

  218. try {

  219. HttpUtil.downloadFile(path, downloadFile);

  220. } catch (IOException e) {

  221. e.printStackTrace();

  222. }

  223. return path;

  224. }

  225.  
  226.  
  227.  
  228. }

6.获取paysSign(签名的appId中的'I'大写,不然会报错,之前我这里卡了好长时间,getPaySignByWeiXin在WeiXinUtils方法里)
String paySign=WeiXinUtils.getPaySignByWeiXin(timeStamp, nonceStr, "prepay_id="+getPrepayId);

7.程序的入口

 
  1. /**

  2. * 微信支付

  3. */

  4. public ModelAndView WeixinPay(String cmd, JSONObject request,HttpServletRequest httprequest, HttpServletResponse response) {

  5. //"appId": "<%= appId %>", //公众号名称,由商户传入

  6. //"timeStamp": "<%= timeStamp %>", //时间戳

  7. //"nonceStr": "<%= nonceStr %>", //随机串

  8. //"package": "<%= package %>", //扩展包

  9. //"signType": "MD5", //微信签名方式:1.sha1

  10. //"paySign": "<%= paySign %>" //微信签名

  11. //String accessToken="";

  12. //String ticket="";

  13. String body="";

  14. String num="";

  15. Double sumPrice=0.0;

  16. String userIp =Utils.getRemortIP(httprequest);

  17. //if(userIp==""||userIp==null)

  18. //userIp="127.0.0.1";

  19. String timeStamp= Long.toString(new Date().getTime()/1000);

  20. String nonceStr=WeiXinUtils.nonceStr; //"HZNAONAOCOM";

  21. String openid =request.getString("openid");

  22. String url = request.getString("url");

  23. JSONArray ordernumlist = request.getJSONArray("ordernum");

  24. if(StringUtils.isBlank(openid)||StringUtils.isBlank(url)||ordernumlist==null)

  25. return writeNotParameters(cmd);

  26. if(openid==""||openid==null)

  27. openid="orLhutxu-XEXWPAB-1DewmJ89w8g";

  28. if(url==""||url==null)

  29. url="http://hznaonao.com/c_mall/pay.jsp";//调用JS接口页面的完整URL

  30. //订单号

  31. String[] numlist=new String[100];

  32. for(int i=0;i<ordernumlist.size();i++){

  33. Object obj=ordernumlist.get(i);

  34. //JSONObject obj = ordernumlist.getJSONObject(i);

  35. //String ordernum=obj.getString("ordernum");

  36. numlist[i]=obj.toString();

  37. num=num+obj;

  38. }

  39. for(int j=0;j<numlist.length;j++){

  40. if(numlist[j]==null)

  41. break;

  42. TOrder order=orderService.findOrderByNumber(numlist[j]);

  43. List<TOrderGoods> ordergoods=orderGoodsService.findOrderGoodsByNumber(numlist[j]);

  44. System.out.println(Double.parseDouble(order.getSumPrice()));

  45. sumPrice=sumPrice+Double.parseDouble(order.getSumPrice());

  46. for(int i=0;i<ordergoods.size();i++){

  47. body=body+","+ordergoods.get(i).getGoodsName();

  48. }

  49. }

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

  52. System.out.println(getPrepayId);

  53.  
  54. String paySign=WeiXinUtils.getPaySignByWeiXin(timeStamp, nonceStr, "prepay_id="+getPrepayId);

  55. System.out.println(paySign);

  56.  
  57. WeiXinVO v =new WeiXinVO();

  58. v.setAppId(WeiXinUtils.APP_ID);

  59. v.setTimeStamp(timeStamp);

  60. v.setNonceStr(nonceStr);

  61. v.set_package("prepay_id="+getPrepayId);

  62. v.setSignType("MD5");

  63. v.setPaySign(paySign);

  64. v.setUrl(url);

  65. System.out.println("appId="+WeiXinUtils.APP_ID);

  66. System.out.println("timeStamp="+timeStamp);

  67. System.out.println("nonceStr="+nonceStr);

  68. System.out.println("package=prepay_id="+getPrepayId);

  69. System.out.println("signType=MD5");

  70. System.out.println("paySign="+paySign);

  71.  
  72.  
  73. return writeJson(cmd, SUCCESS_CODE, "查询成功", v);

  74. }

8.注意paySign签名的timeStamp、nonceStr与最后发送给微信的timeStamp、nonceStr要一致,MD5加密的sign要转化成大写。
 

9.调起微信支付,把appId,timeStamp,nonceStr,package,signType,paySign返回给微信,就OK了,另外回调页面下次再贴代码。

猜你喜欢

转载自blog.csdn.net/qq_40285302/article/details/82497740