Let’s first look at the effect of cash red envelopes issued by the official account:
It is necessary to call the interface of the merchant platform. The interface distribution rules are as follows:
1. Send frequency limit - default 1800/min
2. The upper limit of the number of sends - calculated according to the default 1800/min
3. Amount upper limit - Depending on the incoming scene id, the default upper limit can be set and applied for in the merchant platform product settings, with a maximum of no more than 4,999 yuan per unit
4. What other restrictions on "quantity" are there? - The maximum number of times the user receives that day is 10 by default
5. If the quantity cannot meet our needs, how can we increase each upper limit? --The maximum amount limit and the maximum number of times the user receives on the same day can be set on the merchant platform
Note- When the red envelope amount is greater than 200, the request parameter scene_id must be passed, and the parameter description is shown below.
Note 2 - According to regulatory requirements, two conditions must be met when applying for cash red envelopes for newly applied merchant accounts: 1. The entry time exceeds 90 days 2. Continuous normal transactions for 30 days.
Request Url https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
Whether a certificate is required is (see the merchant certificate for details)
Request method POST
Request data example:
<xml><sign><![CDATA[E1EE61A91C8E90F299DE6AE075D60A2D]]></sign><mch_billno><![CDATA[0010010404201411170000046545]]></mch_billno><mch_id><![CDATA[888]]></mch_id><wxappid><![CDATA[wxcbda96de0b165486]]></wxap pid><send_name><![CDATA[send_name]]></send_name><re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid><total_amount><![CDATA[200]]></total_amount><total_num><![CDATA[1]]></total_num><wishing><![CD ATA[Congratulations on getting rich]]></wishing><client_ip><![CDATA[127.0.0.1]]></client_ip><act_name><![CDATA[New Year Red Envelope]]></act_name><remark><![CDATA[New Year Red Envelope]]></remark><scene_id><![CDATA[PRODUCT_2]]></scene_id><consume_mch_id><![CDATA[10 000097]]></consume_mch_id><nonce_str><![CDATA[50780e0cca98c8c8e814883e5caa672e]]></nonce_str><risk_info>posttime%3d123123412%26clientversion%3d234134%26mobile%3d122344545%26deviceid%3dIOS</risk_info></xml>
The interface requires the call to the merchant platform's certificate, and the certificate needs to be downloaded from the merchant platform:
Then use the certificate in the interface. First, we create a new WeixinSSL class
@Componentpublic class WeiXinSSL { /** * Certificate type*/ @Value("${werchant.storekey}") private String storekey; /** * File path*/ @Value("${werchant.ssLfile}") private String ssLfile; /** * Merchant number*/ @Value("${werchant.merchantNumber}") private String merchantNumber; public String getStorekey() { return storekey; } public void setStorekey(String storekey) { this.storekey = storekey; } public String getSsLfile() { return ssLfile; } public void setSsLfile(String ssLfile) { this.ssLfile = ssLfile; } public String getMerchantNumber() { return merchantNumber; } public void setMerchantNumber(String merchantNumber) { this.merchantNumber = merchantNumber; } }Encapsulate the HttpClientSSL class to implement https request to add a certificate:
@Componentpublic class HttpClientSSL { @Autowired private WeiXinSSL weiXinSSL; // Request timeout (milliseconds) 5 seconds public static RequestConfig requestConfig; // Response timeout (milliseconds) 60 seconds public static int HTTP_RESPONSE_TIMEOUT = 60 * 1000; // httpClient character encoding public static String encoding = "UTF-8"; public static RequestConfig getRequestConfig() { return RequestConfig.custom().setConnectTimeout(5 * 1000) .setConnectionRequestTimeout(HTTP_RESPONSE_TIMEOUT).build(); } public static void setRequestConfig(RequestConfig requestConfig) { HttpClientSSL.requestConfig = requestConfig; } /** * https request forgery certificate* @return */ public CloseableHttpClient defaultSSLClient() { SSLContext sslContext = null; try { new SSLContextBuilder().loadTrustMaterial(null,new TrustStrategy(){ @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { return false; } }); } catch (NoSuchAlgorithmException | KeyStoreException e) { e.printStackTrace(); } SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext); return HttpClients.custom().setSSLSocketFactory(factory).build(); } /** * https request to add certificate* @return */ public CloseableHttpClient defaultSSLClientFile() { if (this.weiXinSSL == null){ return this.defaultSSLClient(); } FileInputStream inputStream = null; KeyStore keyStore = null; try { // Ssl type keyStore = KeyStore.getInstance(weiXinSSL.getStorekey()); // ssl file inputStream = new FileInputStream(weiXinSSL.getSsLfile()); // Set the ssl password keyStore.load(inputStream,weiXinSSL.getMerchantNumber().toCharArray()); } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e1) { e1.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } SSLContext sslContext = null; try { sslContext = SSLContexts.custom().loadKeyMaterial(keyStore,weiXinSSL.getMerchantNumber().toCharArray()).build(); } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { e.printStackTrace(); } SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); return HttpClients.custom().setSSLSocketFactory(factory).build(); } /** * Encapsulate method to send requests* @throws UnsupportedEncodingException */ public String send(String url, String data, CloseableHttpClient closeableHttpClient) throws UnsupportedEncodingException { CloseableHttpClient client = closeableHttpClient; HttpPost httpPost = new HttpPost(URLDecoder.decode(url, encoding)); httpPost.addHeader("Connection", "keep-alive"); httpPost.addHeader("Accept", "*/*"); httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); httpPost.addHeader("Host", "api.mch.weixin.qq.com"); httpPost.addHeader("X-Requested-With", "XMLHttpRequest"); httpPost.addHeader("Cache-Control", "max-age=0"); httpPost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) "); httpPost.setConfig(this.getRequestConfig());// Set timeout CloseableHttpResponse response = null; // Put the parameter in StringEntity entity = new StringEntity(data, encoding); entity.setContentEncoding(encoding); entity.setContentType("application/xml"); httpPost.setEntity(entity); try { response = client.execute(httpPost); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity httpEntity = (HttpEntity) response.getEntity(); if (response != null) { return EntityUtils.toString(httpEntity,encoding); } } } catch (IOException e) { e.printStackTrace(); } return null; }} In this way, we encapsulate an entity class that requests the certificate with https, and then we generate the WeChat red envelope interface requested:
Parameter signature of https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack:
/*** Red envelope parameter entity class* @throws UnsupportedEncodingException */@Componentpublic class SendRedPack implements Serializable{ /** * */ private static final long serialVersionUID = -1000489228099916099L; private String nonce_str;// Random string private String sign;// Signature private String mch_billno;// Merchant order number private String mch_id;// Merchant number private String wxappid;// Public account private String send_name;// Merchant name private String re_openid;// User private int total_amount;// Payment amount unit: private int total_num;// Total number of red envelopes private String wishing;// Red envelope blessing private String client_ip;// Ip address private String act_name;// Activity name private String remark;// Notes public String getNonce_str() { return nonce_str; } public void setNonce_str(String nonce_str) { this.nonce_str = nonce_str; } public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public String getMch_billno() { return mch_billno; } public void setMch_billno(String mch_billno) { this.mch_billno = mch_billno; } public String getMch_id() { return mch_id; } public void setMch_id(String mch_id) { this.mch_id = mch_id; } public String getWxappid() { return wxappid; } public void setWxappid(String wxappid) { this.wxappid = wxappid; } public String getSend_name() { return send_name; } public void setSend_name(String send_name) { this.send_name = send_name; } public String getRe_openid() { return re_openid; } public void setRe_openid(String re_openid) { this.re_openid = re_openid; } public int getTotal_amount() { return total_amount; } public void setTotal_amount(int total_amount) { this.total_amount = total_amount; } public int getTotal_num() { return total_num; } public void setTotal_num(int total_num) { this.total_num = total_num; } public String getWishing() { return wishing; } public void setWishing(String wishing) { this.wishing = wishing; } public String getClient_ip() { return client_ip; } public void setClient_ip(String client_ip) { this.client_ip = client_ip; } public String getAct_name() { return act_name; } public void setAct_name(String act_name) { this.act_name = act_name; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; }}Next is the controller that sends the red packet:
/** * Red envelope controller* @author zengliang */@Controller@RequestMapping(value="/redenveLopesReceive")public class RedEnvelopesReceiveController { //WeChat unique identifier @Value("${weixin.appid}") private String appid; //WeChat developer password identifier @Value("${weixin.appsecret}") public String appsecret; @Autowired private SendRedPack sendredpack; @Autowired private HttpClientSSL httpclientssl; /** * Send XML parameters* @author zengliang */ @ResponseBody @RequestMapping(value="/sendXml") public String sendXml(String openid,Long redenveLopes_id,String mch_billno){ RedenveLopes redenve = redenveLopesService.findOne(redenveLopes_id); XMLUtil xmlUtil= new XMLUtil(); sendredpack.setAct_name(redenve.getAct_name()); sendredpack.setNonce_str(xmlUtil.random()); sendredpack.setRe_openid(openid); sendredpack.setClient_ip(redenve.getClient_ip()); sendredpack.setMch_billno(mch_billno); sendredpack.setMch_id(redenve.getMch_id()); String xx = redenve.getRemark(); sendredpack.setRemark(StringUtils.isEmpty(xx) == false?xx:"empty"); sendredpack.setSend_name(redenve.getSend_name()); sendredpack.setTotal_amount(redenve.getTotal_amount()); sendredpack.setTotal_num(redenve.getTotal_num()); sendredpack.setWishing(redenve.getWishing()); sendredpack.setWxappid(redenve.getWxappidxx()); //Generate signature String params = this.createSendRedPackOrderSign(sendredpack,redenve.getStore_key()); sendredpack.setSign(params); xmlUtil.xstream().alias("xml",sendredpack.getClass()); //Extend xstream to support CDATA block String requestXml = xmlUtil.xstream().toXML(sendredpack); String result; try { result = httpclientssl.send("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack", requestXml,httpclientssl.defaultSSLClientFile()); System.out.println("Successful return value"+result); return result; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; }/** * Generate signature* @param redPack * @return */ public String createSendRedPackOrderSign(SendRedPack redPack,String storekey){ StringBuffer sign = new StringBuffer(); sign.append("act_name=").append(redPack.getAct_name()); sign.append("&client_ip=").append(redPack.getClient_ip()); sign.append("&re_billno=").append(redPack.getMch_billno()); sign.append("&remark=").append(redPack.getMch_id()); sign.append("&send_str=").append(redPack.getNonce_str()); sign.append(redPack.getNonce_str()); sign.append("&re_openid=").append(redPack.getRe_openid()); sign.append("&remark=").append(redPack.getRemark()); sign.append("&send_name=").append(redPack.getSend_name()); sign.append("&total_amount=").append(redPack.getTotal_amount()); sign.append("&total_num=").append(redPack.getTotal_num()); sign.append("&wishing=").append(redPack.getWishing()); sign.append("&wxappid=").append(redPack.getWxappid()); sign.append("&key=").append(storekey); return DigestUtils.md5Hex(sign.toString()).toUpperCase(); }}Then we need to use a tool class to parse XML to parse XML returned by WeChat to parse XML
/** * Parsing XML tool class * @author zengliang */@Componentpublic class XMLUtil { /** * Parsing XML returned by WeChat * @param xml * @return * @throws Exception */ @SuppressWarnings("unchecked") public Map<String, String> parseXml(String xml)throws Exception { Map<String,String> map = new HashMap<String,String>(); Document doc = null; try { doc = DocumentHelper.parseText(xml); // Convert the string to XML Element rootElt = doc.getRootElement(); // Get the root node List<Element> list = rootElt.elements();// Get all nodes under the root node for (Element element : list) { //Tranquility node map.put(element.getName(), element.getText()); //The name of the node is the map key, and the text is the map value } } catch (DocumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return map; } /** * Extend xstream to support CDATA block*/ private XStream xstream = new XStream(new XppDriver(new NoNameCoder()) { @Override public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // Add CDATA mark to all xml nodes for conversions boolean cdata = true; @Override @SuppressWarnings("rawtypes") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } @Override public String encodeNode(String name) { return name; } @Override protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write("<![CDATA["); writer.write(text); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } } }; } }); private XStream inclueUnderlineXstream = new XStream(new DomDriver(null,new XmlFriendlyNameCoder("_-", "_"))); public XStream getXstreamInclueUnderline() { return inclueUnderlineXstream; } public XStream xstream() { return xstream; } /** * Generate random number* @return */ public String random(){ String random = UUID.randomUUID().toString().replace("-", ""); return random; }}Then we call the sendXML method to send red envelopes to the user.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.