The previous article has obtained the user's OpenId
This article mainly calls the unified single API for 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 into XML format and send them to the interface address given by WeChat, and then you can get the returned content. If it is successful, there will be the prepayment ID required for payment.
The request parameters will not be explained.
Among them, random string: I used UUID to draw the middle line
public static String create_nonce_str() { return UUID.randomUUID().toString().replace("-",""); }Merchant Order Number: Each order number can only be used once, so the time stamp added to the system's order number is used.
Total amount: Cannot be
Notification address: The address of the callback to the system after successful or failed WeChat payment
sign:
import java.io.Serializable; public class PayInfo implements Serializable{ private static final long serialVersionUID = L; private String appid; private St ring 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 o penid; //The following is the get,set method} /** * Create a unified single xml java object* @param bizOrder system Business order number in * @param ip User's ip address* @param openId User's 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().repl ace("-", "")); payInfo.setBody(" Here is the body of some white rice"); payInfo.setAttach(bizOrder.getId()); payInfo.setOut_trade_no(bizOrder.getOrderCode().concat("A").concat(DateFormatUtils.for mat(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 the signature:
/** * 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() +"&nonc e_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; //This key pays attention to MessageDigest md = MessageDigest.getInst ance("MD"); md.reset(); md.update (signTemp.getBytes("UTF-")); String sign = CommonUtil.byteToStr(md.digest()).toUpperCase(); return sign; } Note: The above Constants.key value is in the merchant API secure API key.
Some tool methods: get the ip address, convert the byte array to hexadecimal string, convert the byte to hexadecimal string
/** * Convert byte array 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; } /** * Convert bytes to hexadecimal string* * @param btyes * @retu rn */ 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; } /** * Get the ip address* @param request * @return */ public static String getIpAddr(HttpServletRe quest 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; } This way, the signature is obtained, and the signature and other data in PayInfo are converted into XML format, and passed to the unified single address as parameters.
PayInfo pi = pu.createPayInfo(bo,"...",""); String sign = pu.getSign(pi); pi.setSign(sign);
Object to XML
/** * Extend xstream to support CDATA */ private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { re turn new PrettyPrintWriter(out) { //Add CDATA tag boolean cdata = true; @SuppressWarnings("rawtypes") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } protected void writeText(Quic kWriter writer, String text) { if (cdata) { writer.write("< ![CDATA["); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } } }; } }); public static String payInfoToXML(PayIn fo 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<St ring, 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 the unified order
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, Str ing> result = new HashMap<>(); try { StringBuffer buffer = httpsRequest(requestUrl, requestMethod, outputStr); result = MessageUtil.parseXml(buffer.toString()); } catch (ConnectException ce) { log.err or("Connection timeout:"+ce.getMessage()); } catch ( Exception e) { log.error("https request exception: "+ece.getMessage()); } return result; } The method httpsRequest() is in the first article
If the map obtained above succeeds, 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 "Unified single error!"; } }else{ return "Unified single error!"; } String prepay_Id = map.get("prepay_id");This prepay_id is the prepay ID. Pay later requires it.