Home  >  Article  >  WeChat Applet  >  WeChat official account payment (2) Implementing a unified ordering interface

WeChat official account payment (2) Implementing a unified ordering interface

高洛峰
高洛峰Original
2017-02-04 11:40:562669browse

The previous article has obtained the user's OpenId

This article mainly calls the unified order API of WeChat public payment

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

Looking at the document, the main process is to encapsulate about 20 parameters in XML format and send them to the interface address provided by WeChat, and then you can obtain The returned content, if successful, contains the prepayment ID required for payment.

The request parameters will not be explained.

Among them, random string: I use UUID to remove the underscore

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

Merchant order number: Each order number can only It is used once, so the timestamp added to the order number of the system is used.

Total amount: cannot be

Notification address: WeChat payment success or failure callback address to the system

Signature:

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

Get signature:

/**
 * 获取签名
 * @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;
 }

Note: The value of Constants.key above is in the API security API key of the merchant account.

Some tool methods: get ip address, convert byte array to hexadecimal string, convert bytes to hexadecimal string

/**
* 将字节数组转换为十六进制字符串
*
* @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 = { &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39; };
 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;
}

In this way, the signature is obtained, the signature and other data in PayInfo are converted into XML format, and passed as parameters to the unified order address.

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

Object to XML

/**
* 扩展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 to Map

@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;
}

The following is the URL to call unified ordering

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() This method is in the first article


If the Map obtained above is successful, there will be

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");

This prepay_id is the prepaid ID. You will need it for payment later.

For more articles related to WeChat public account payment (2) Implementing a unified ordering interface, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn