L'article précédent a obtenu l'OpenId de l'utilisateur
Cet article appelle principalement l'API de commande unifiée du paiement public WeChat
Adresse API : https://pay.weixin.qq com/. wiki/doc/api/jsapi.php?chapter=9_1
En regardant le document, le processus principal consiste à encapsuler environ 20 paramètres au format XML et à les envoyer à l'adresse d'interface fournie par WeChat, puis vous peut obtenir Le contenu retourné, en cas de succès, contient l'identifiant de prépaiement
requis pour le paiement. Les paramètres de la demande ne seront pas expliqués.
Parmi eux, une chaîne aléatoire : j'utilise l'UUID pour supprimer le trait de soulignement
public static String create_nonce_str() { return UUID.randomUUID().toString().replace("-",""); }
Numéro de commande du marchand : chaque numéro de commande Il ne peut être utilisé une seule fois, donc l'horodatage ajouté au numéro de commande du système est utilisé.
Montant total : ne peut pas être
Adresse de notification : adresse de rappel du paiement WeChat au système en cas de succès ou d'échec
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; }
Obtenir la 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; }
Remarque : La valeur de Constants.key ci-dessus est le mot de passe de l'API de sécurité de l'API de le numéro de commerçant dans la clé.
Quelques méthodes d'outils : obtenir l'adresse IP, convertir un tableau d'octets en chaîne hexadécimale, convertir des octets en chaîne hexadécimale
/** * 将字节数组转换为十六进制字符串 * * @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; }
De cette manière, la signature est obtenue, la signature et les autres données de PayInfo sont converties au format XML et transmises en tant que paramètres à l'adresse de commande unifiée.
PayInfo pi = pu.createPayInfo(bo,"...",""); String sign = pu.getSign(pi); pi.setSign(sign);
Objet vers 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 vers 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; }
Ce qui suit est l'URL pour appeler l'ordre unifié
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; }
La méthode httpsRequest() est dans Chapitre 1 Dans l'article
si la carte obtenue ci-dessus est réussie, il y aura
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");
dedans
Ce prepay_id est l'identifiant de paiement prepay_id. Vous en aurez besoin pour le paiement plus tard.
Pour plus d'articles liés au paiement par compte public WeChat (2) réalisant une interface de commande unifiée, veuillez faire attention au site Web PHP chinois !