一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 微信公眾號支付(二)實現統一下單接口

微信公眾號支付(二)實現統一下單接口

2020-01-04 17:04mrr JAVA教程

本篇文章主要給大家介紹調用微信公眾支付的統一下單API,通過參數封裝為xml格式并發送到微信給的接口地址就可以獲得返回內容,需要的朋友可以參考下本文

上一篇已經獲取到了用戶的OpenId

這篇主要是調用微信公眾支付的統一下單API

API地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

看文檔,主要流程就是把20個左右的參數封裝為XML格式發送到微信給的接口地址,然后就可以獲取到返回的內容了,如果成功里面就有支付所需要的預支付ID

請求參數就不解釋了。

其中,隨機字符串:我用的是UUID去中劃線

?
1
2
3
public static String create_nonce_str() {
return UUID.randomUUID().toString().replace("-","");
}

商戶訂單號:每個訂單號只能使用一次,所以用的是系統的訂單號加的時間戳。

總金額:不能為

通知地址:微信支付成功或失敗回調給系統的地址

簽名

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.io.Serializable;
 public class PayInfo implements Serializable{
 private static final long serialVersionUID = L;
 private String appid;
 private String mch_id;
 private String device_info;
 private String nonce_str;
 private String sign;
 private String body;
 private String attach;
 private String out_trade_no;
 private int total_fee;
 private String spbill_create_ip;
 private String notify_url;
 private String trade_type;
 private String openid;
 //下面是get,set方法
 }
 
 
 /**
 * 創建統一下單的xml的java對象
 * @param bizOrder 系統中的業務單號
 * @param ip 用戶的ip地址
 * @param openId 用戶的openId
 * @return
 */
 public PayInfo createPayInfo(BizOrder bizOrder,String ip,String openId) {
  PayInfo payInfo = new PayInfo();
  payInfo.setAppid(Constants.appid);
  payInfo.setDevice_info("WEB");
  payInfo.setMch_id(Constants.mch_id);
  payInfo.setNonce_str(CommonUtil.create_nonce_str().replace("-", ""));
  payInfo.setBody("這里是某某白米飯的body");
  payInfo.setAttach(bizOrder.getId());
  payInfo.setOut_trade_no(bizOrder.getOrderCode().concat("A").concat(DateFormatUtils.format(new Date(), "MMddHHmmss")));
  payInfo.setTotal_fee((int)bizOrder.getFeeAmount());
  payInfo.setSpbill_create_ip(ip);
  payInfo.setNotify_url(Constants.notify_url);
  payInfo.setTrade_type("JSAPI");
  payInfo.setOpenid(openId);
  return payInfo;
 }

獲取簽名:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * 獲取簽名
 * @param payInfo
 * @return
 * @throws Exception
 */
 public String getSign(PayInfo payInfo) throws Exception {
  String signTemp = "appid="+payInfo.getAppid()
   +"&attach="+payInfo.getAttach()
   +"&body="+payInfo.getBody()
   +"&device_info="+payInfo.getDevice_info()
   +"&mch_id="+payInfo.getMch_id()
   +"&nonce_str="+payInfo.getNonce_str()
   +"¬ify_url="+payInfo.getNotify_url()
   +"&openid="+payInfo.getOpenid()
   +"&out_trade_no="+payInfo.getOut_trade_no()
   +"&spbill_create_ip="+payInfo.getSpbill_create_ip()
   +"&total_fee="+payInfo.getTotal_fee()
   +"&trade_type="+payInfo.getTrade_type()
   +"&key="+Constants.key; //這個key注意
 MessageDigest md = MessageDigest.getInstance("MD");
 md.reset();
 md.update(signTemp.getBytes("UTF-"));
 String sign = CommonUtil.byteToStr(md.digest()).toUpperCase();
 return sign;
 }

注意:上面的Constants.key取值在商戶號API安全的API密鑰中。

一些工具方法:獲取ip地址,將字節數組轉換為十六進制字符串,將字節轉換為十六進制字符串

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* 將字節數組轉換為十六進制字符串
*
* @param byteArray
* @return
*/
public static String byteToStr(byte[] byteArray) {
 String strDigest = "";
 for (int i = ; i < byteArray.length; i++) {
 strDigest += byteToHexStr(byteArray[i]);
 }
 return strDigest;
}
/**
* 將字節轉換為十六進制字符串
*
* @param btyes
* @return
*/
public static String byteToHexStr(byte bytes) {
 char[] Digit = { '', '', '', '', '', '', '', '', '', '', 'A', 'B', 'C', 'D', 'E', 'F' };
 char[] tempArr = new char[];
 tempArr[] = Digit[(bytes >>> ) & XF];
 tempArr[] = Digit[bytes & XF];
 String s = new String(tempArr);
 return s;
}
/**
* 獲取ip地址
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
 InetAddress addr = null;
 try {
 addr = InetAddress.getLocalHost();
 } catch (UnknownHostException e) {
 return request.getRemoteAddr();
 }
 byte[] ipAddr = addr.getAddress();
 String ipAddrStr = "";
 for (int i = ; i < ipAddr.length; i++) {
 if (i > ) {
  ipAddrStr += ".";
 }
 ipAddrStr += ipAddr[i] & xFF;
 }
 return ipAddrStr;
}

這樣就獲取了簽名,把簽名與PayInfo中的其他數據轉成XML格式,當做參數傳遞給統一下單地址。

?
1
2
3
PayInfo pi = pu.createPayInfo(bo,"...","");
String sign = pu.getSign(pi);
pi.setSign(sign);

對象轉XML

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 擴展xstream使其支持CDATA
*/
private static XStream xstream = new XStream(new XppDriver() {
 public HierarchicalStreamWriter createWriter(Writer out) {
 return new PrettyPrintWriter(out) {
  //增加CDATA標記
  boolean cdata = true;
  @SuppressWarnings("rawtypes")
  public void startNode(String name, Class clazz) {
  super.startNode(name, clazz);
  }
  protected void writeText(QuickWriter writer, String text) {
  if (cdata) {
   writer.write("<![CDATA[");
   writer.write(text);
   writer.write("]]>");
  } else {
   writer.write(text);
  }
  }
 };
 }
});
public static String payInfoToXML(PayInfo pi) {
 xstream.alias("xml", pi.getClass());
 return xstream.toXML(pi);
}

xml轉Map

?
1
2
3
4
5
6
7
8
9
10
@SuppressWarnings("unchecked")
public static Map<String, String> parseXml(String xml) throws Exception {
 Map<String, String> map = new HashMap<String, String>();
 Document document = DocumentHelper.parseText(xml);
 Element root = document.getRootElement();
 List<Element> elementList = root.elements();
 for (Element e : elementList)
 map.put(e.getName(), e.getText());
 return map;
}

下面就是調用統一下單的URL了

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
log.info(MessageUtil.payInfoToXML(pi).replace("__", "_"));
   Map<String, String> map = CommonUtil.httpsRequestToXML("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", MessageUtil.payInfoToXML(pi).replace("__", "_").replace("<![CDATA[", "").replace("]]>", ""));
 log.info(map);
 
 public static Map<String, String> httpsRequestToXML(String requestUrl, String requestMethod, String outputStr) {
  Map<String, String> result = new HashMap<>();
  try {
  StringBuffer buffer = httpsRequest(requestUrl, requestMethod, outputStr);
  result = MessageUtil.parseXml(buffer.toString());
  } catch (ConnectException ce) {
  log.error("連接超時:"+ce.getMessage());
  } catch (Exception e) {
  log.error("https請求異常:"+ece.getMessage());
  }
  return result;
 }

httpsRequest()這個方法在第一篇中

上面獲取到的Map如果成功的話,里面就會有

?
1
2
3
4
5
6
7
8
9
10
String return_code = map.get("return_code");
 if(StringUtils.isNotBlank(return_code) && return_code.equals("SUCCESS")){
   String return_msg = map.get("return_msg");
 if(StringUtils.isNotBlank(return_msg) && !return_msg.equals("OK")) {
   return "統一下單錯誤!";
 }
 }else{
   return "統一下單錯誤!";
 }
 String prepay_Id = map.get("prepay_id");

這個prepay_id就是預支付的ID。后面支付需要它。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩欧美高清视频 | 青柠影视在线播放观看高清 | 91短视频破解版 | 国产视频久久久久 | 久久r视频 | japanesexxxx日本妞 | 色小孩导航 | 久久久久青草大香线综合精品 | 日韩性大片免费 | 欧美午夜精品久久久久久黑人 | 日韩高清在线观看 | 欧美日韩国产亚洲一区二区三区 | www.日本视频 | 黑帮少爷爱上我第8集最新 荷兰精品女人性hd 和日本免费不卡在线v | 女主被男主为催奶药h | 国产午夜小视频 | 精品久久久久久久久久香蕉 | 故意短裙公车被强好爽在线播放 | 国产第一页在线视频 | 男人吃奶动态图 | 亚洲精品视频观看 | 久久婷婷五月综合色丁香 | 亚洲AV蜜桃永久无码精品红樱桃 | 国产一级在线观看 | 精品久久免费观看 | 精品欧美小视频在线观看 | 污文啊好棒棒啊好了 | 色综合天天综合网国产人 | 2015台湾永久免费平台 | yellow视频在线观看 | 国产黄频 | 亚洲精品一区二区久久久久 | 久久精品亚洲牛牛影视 | 欧美一级在线视频 | 动态图啪啪120秒免费看 | 太紧太深了受不了黑人 | 亚洲AV无码国产精品午夜久久 | 国产精品久久久久jk制服 | 天使萌痴汉在线中文字幕 | 国产亚洲玖玖玖在线观看 | 国产成人精品一区二区不卡 |