java开发微信公众号支付(JSAPI)
https://www.cnblogs.com/gopark/p/9394951.html,这篇文章写的已经很详细了。
下面写一下自己的思路:
1.首先下载demo,地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
2.demo中很多方法对于公众号支付用不到,不需要全都看
3.主要是获取11个参数,放到Map中,用demo里提供WXPayUtil.mapToXml方法转为XML格式,通过post方法请求微信端的统一下单接口,后台收到微信传过来的XML字符串,通过WXPayUtil.xmlToMap方法转为Map,根据key值,获取prepay_id(预支付ID),再把需要的6个参数放到Map中,发送给前台,前台根据prepay_id,唤起微信支付,完成付款。
4.11个参数跟6个参数在controller里面都有写,重点的是:openid
5.查看订单,取消订单等其他功能,后续接触到再进行更新
下面放上自己写的controller
1 package com.github.wxpay.controller; 2 3 import com.github.wxpay.sdk.WXPayConstants; 4 import com.github.wxpay.sdk.WXPayUtil; 5 import com.github.wxpay.util.Constant; 6 import com.github.wxpay.util.HttpRequestUtil; 7 import com.github.wxpay.util.OrderUtil; 8 import org.springframework.web.bind.annotation.RequestMethod; 9 import org.springframework.web.bind.annotation.ResponseBody; 10 11 import javax.servlet.http.HttpServletRequest; 12 import javax.servlet.http.HttpSession; 13 import java.util.HashMap; 14 import java.util.Map; 15 import org.springframework.web.bind.annotation.RequestMapping; 16 import com.github.wxpay.sdk.WXPayConstants.SignType; 17 18 public class WxPayController { 19 20 /** 21 * 22 * @Description 微信浏览器内微信支付/公众号支付(JSAPI) 23 */ 24 @RequestMapping(value = "/orders",method = RequestMethod.GET) 25 @ResponseBody 26 public Map orders(HttpServletRequest request){ 27 try { 28 Map<String, String> paramMap = new HashMap<String, String>(); 29 HttpSession session = request.getSession(); 30 String wxopenid = session.getAttribute("openid") == null ? null : session.getAttribute("openid").toString(); 31 //在商户平台的账户中心下:需要用户自行下载证书及安装 32 String key = Constant.signCustomerKey; 33 String ip = request.getHeader("x-forwarded-for"); 34 35 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 36 ip = request.getHeader("Proxy-Client-IP"); 37 } 38 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 39 ip = request.getHeader("WL-Proxy-Client-IP"); 40 } 41 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 42 ip = request.getRemoteAddr(); 43 } 44 if (ip.indexOf(",") != -1) { 45 String[] ips = ip.split(","); 46 ip = ips[0].trim(); 47 } 48 paramMap.put("appid", Constant.APPIDS[0]); 49 paramMap.put("mch_id", ""); 50 paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); 51 paramMap.put("body", "测试订单XX矿泉水"); 52 paramMap.put("openid", wxopenid); 53 paramMap.put("out_trade_no", OrderUtil.orderNumber()); 54 paramMap.put("spbill_create_ip", ip); 55 paramMap.put("total_fee", "0.01"); 56 paramMap.put("notify_url", "http://127.0.0.1:8080/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp");// 此路径是微信服务器调用支付结果通知路径 57 paramMap.put("trade_type", "JSAPI"); 58 String sign = WXPayUtil.generateSignature(paramMap,key,SignType.MD5); 59 paramMap.put("sign", sign); 60 61 // 将所有参数(map)转xml格式 62 String mapToXml = WXPayUtil.mapToXml(paramMap); 63 System.out.println(mapToXml); 64 // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder 65 String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; 66 // 发送post请求"统一下单接口"返回预支付id:prepay_id 67 String xmlStr = HttpRequestUtil.sendPost(unifiedorder_url,mapToXml); 68 69 Map<String,String> XmlToMap = WXPayUtil.xmlToMap(xmlStr); 70 // 以下内容是返回前端页面的json数据 71 String prepay_id = ""; // 预支付ID 72 if (xmlStr.indexOf("SUCCESS") != -1) { 73 Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); 74 prepay_id = map.get("prepay_id"); 75 } 76 Map<String, String> payMap = new HashMap<String, String>(); 77 XmlToMap.put("appId", Constant.APPIDS[0]); 78 XmlToMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+""); 79 XmlToMap.put("nonceStr", WXPayUtil.generateNonceStr()); 80 XmlToMap.put("signType", "MD5"); 81 XmlToMap.put("package", "prepay_id=" + prepay_id); 82 String paySign = WXPayUtil.generateSignature(payMap, key); 83 payMap.put("paySign", paySign); 84 return XmlToMap; 85 }catch (Exception e){ 86 e.printStackTrace(); 87 } 88 return null; 89 } 90 } 91
httpRequest工具:
1 package com.github.wxpay.util; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.PrintWriter; 7 import java.net.URLConnection; 8 import java.util.List; 9 import java.net.URL; 10 import java.util.Map; 11 12 public class HttpRequestUtil { 13 /** 14 * 向指定URL发送GET方法的请求 15 * 16 * @param url 17 * 发送请求的URL 18 * @param param 19 * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 20 * @return URL 所代表远程资源的响应结果 21 */ 22 public static String sendGet(String url, String param) { 23 String result = ""; 24 BufferedReader in = null; 25 try { 26 String urlNameString = url + "?" + param; 27 URL realUrl = new URL(urlNameString); 28 // 打开和URL之间的连接 29 URLConnection connection = realUrl.openConnection(); 30 // 设置通用的请求属性 31 connection.setRequestProperty("accept", "*/*"); 32 connection.setRequestProperty("connection", "Keep-Alive"); 33 connection.setRequestProperty("user-agent", 34 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 35 // 建立实际的连接 36 connection.connect(); 37 // 获取所有响应头字段 38 Map<String, List<String>> map = connection.getHeaderFields(); 39 // 遍历所有的响应头字段 40 for (String key : map.keySet()) { 41 System.out.println(key + "--->" + map.get(key)); 42 } 43 // 定义 BufferedReader输入流来读取URL的响应 44 in = new BufferedReader(new InputStreamReader( 45 connection.getInputStream())); 46 String line; 47 while ((line = in.readLine()) != null) { 48 result += line; 49 } 50 } catch (Exception e) { 51 System.out.println("发送GET请求出现异常!" + e); 52 e.printStackTrace(); 53 } 54 // 使用finally块来关闭输入流 55 finally { 56 try { 57 if (in != null) { 58 in.close(); 59 } 60 } catch (Exception e2) { 61 e2.printStackTrace(); 62 } 63 } 64 return result; 65 } 66 67 /** 68 * 向指定 URL 发送POST方法的请求 69 * 70 * @param url 71 * 发送请求的 URL 72 * @param param 73 * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 74 * @return 所代表远程资源的响应结果 75 */ 76 public static String sendPost(String url, String param) { 77 PrintWriter out = null; 78 BufferedReader in = null; 79 String result = ""; 80 try { 81 URL realUrl = new URL(url); 82 // 打开和URL之间的连接 83 URLConnection conn = realUrl.openConnection(); 84 // 设置通用的请求属性 85 conn.setRequestProperty("accept", "*/*"); 86 conn.setRequestProperty("connection", "Keep-Alive"); 87 conn.setRequestProperty("user-agent", 88 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); 89 // 发送POST请求必须设置如下两行 90 conn.setDoOutput(true); 91 conn.setDoInput(true); 92 // 获取URLConnection对象对应的输出流 93 out = new PrintWriter(conn.getOutputStream()); 94 // 发送请求参数 95 out.print(param); 96 // flush输出流的缓冲 97 out.flush(); 98 // 定义BufferedReader输入流来读取URL的响应 99 in = new BufferedReader( 100 new InputStreamReader(conn.getInputStream())); 101 String line; 102 while ((line = in.readLine()) != null) { 103 result += line; 104 } 105 } catch (Exception e) { 106 System.out.println("发送 POST 请求出现异常!"+e); 107 e.printStackTrace(); 108 } 109 //使用finally块来关闭输出流、输入流 110 finally{ 111 try{ 112 if(out!=null){ 113 out.close(); 114 } 115 if(in!=null){ 116 in.close(); 117 } 118 } 119 catch(IOException ex){ 120 ex.printStackTrace(); 121 } 122 } 123 return result; 124 } 125 }
随机数工具:
package com.github.wxpay.util; import com.github.wxpay.sdk.WXPayUtil; public class OrderUtil { public static String orderNumber(){ int r1 = (int)(Math.random()*10); int r2 = (int)(Math.random()*10); long now = WXPayUtil.getCurrentTimestampMs(); String paymentID = String.valueOf(r1)+String.valueOf(r2)+String.valueOf(now); return paymentID; } }