The Way to Fill the Pit with Wechat Small Program Service Provider Model
Having read the posts of this predecessor, I have come out of the deep pit and added a few easy mistakes by the way: https://blog.csdn.net/qq_18881987/article/details/94428628.
This post discusses the unified backstage order and secondary signature. As for the api on the small program side, the backstage parameter transfer is basically no big problem.
Firstly, download the official sdk of Hangdad's Weixin and import it into the program as follows:
Next, modify the verification method of wxpay class in sdk, and change it to md5 verification. Hangdad's HMACSHA256 has been reporting signature errors.
Next, look at the official documents of Wechat.
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_sl_api.php?chapter=9_1
Explain each parameter one by one
data.put("appid", Service Util. AppID); // Appid of the public number of the service provider
data.put("mch_id", ServiceUtil.MchID); // Service Provider Business Number (allocated by Wechat Payment Platform)
data.put("sub_mch_id", ServiceUtil.sub_mch_id); // Special Merchant Business Number (Distributed by Wechat Payment Platform)
data.put("sub_appid", ServiceUtil.sub_appid); // Appid of the special merchant applet
data.put("nonce_str", nonce_str); // Random String
data.put("body", body); // Fill in your own type of payment for the order I wrote here
data.put("out_trade_no", serno);//own order number
data.put("total_fee", price); // price
data.put("spbill_create_ip", spbill_create_ip);//address
data.put("notify_url", "127.0.0.1"); //callback address
data.put("trade_type", "JSAPI"); //authentication
data.put("sub_openid", openId); // This parameter I'll haw.
data.put("sign", PayUtil.createSign(data,nonce_str)); signature
data.put("sign_type", "MD5"); signature verification method
sub_openid
After two hours of continuous testing, this parameter is... openid... I read some posts from my predecessors and said that this should be re-passed by wx before payment. login method acquisition. I got the same results here. No matter put it directly in the parameters, we find that it can pass...
Paste me the way to get this parameter.
package com.hsdsoft.wx; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import com.hdsoft.util.ServiceUtil; import com.hdsoft.util.StringUtil; public class WeChatGetOpenid { public static String interfaceUtil(String path,String data) { String openId=""; try { URL url = new URL(path); //Open the connection between url and url HttpURLConnection conn = (HttpURLConnection) url.openConnection(); PrintWriter out = null; //Request mode // conn.setRequestMethod("POST"); // // Setting Common Request Properties conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); //Set whether to output to httpUrlConnection, whether to read from httpUrlConnection, and whether to send a post request must set these two //The most common Http requests are get and post. Get requests can get static pages, or they can put parameters behind URL strings and pass them to servlet s. //The difference between post and get is that the parameters of post are not placed in the URL string, but in the body of the http request. conn.setDoOutput(true); conn.setDoInput(true); //Get the output stream corresponding to the URLConnection object out = new PrintWriter(conn.getOutputStream()); //Send request parameters, that is, data out.print(data); //Buffer data out.flush(); //Get the input stream corresponding to the URLConnection object InputStream is = conn.getInputStream(); //Constructing a character stream cache BufferedReader br = new BufferedReader(new InputStreamReader(is)); String str = ""; while ((str = br.readLine()) != null) { openId=str; } //Closed flow is.close(); //disconnect, preferably written, when the underlying tcp socket link is idle. If it is being used by other threads, it will not be cut off. //Fixed multi-threading, if not disconnected, links will increase until no information can be sent or received. It's normal to write disconnect. conn.disconnect(); } catch (Exception e) { e.printStackTrace(); } return openId; } public static String GetOpenID(String appid,String appsecret,String Code) { //Temporary login credentials String URL = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+appsecret+"&js_code="+Code+"&grant_type=authorization_code"; String openId=interfaceUtil(URL, ""); return openId; } public static String getSubOpenId() { return null; } }
Looking at the explanations in the official documents, I just want to talk about his uncle.
Let's talk about it here. All keys used are keys in the service provider's Wechat payment platform.
If your signature algorithm and key are all right, the unified order should be completed at this moment.
The idea here is that in the Wechat platform (Wechat Payment Platform) of the special merchant, the appid of the special merchant applet must be added to the appid authorization.
Service Provider Configuration: Service Provider Function
Return map set to applet after unifying order
Map<String, String> rMap = wxpay.unifiedOrder(data); System.out.println("Unified single interface return: " + rMap); String return_code = (String) rMap.get("return_code"); String result_code = (String) rMap.get("result_code"); String nonceStr = WXPayUtil.generateNonceStr(); resultMap.put("nonceStr", nonceStr); Long timeStamp = System.currentTimeMillis() / 1000; if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) { String prepayid = rMap.get("prepay_id"); System.out.println("prepayid= "+prepayid); resultMap.put("package", "prepay_id="+prepayid); resultMap.put("signType", "MD5"); //The returned timestamp is converted to a string, otherwise the widget will report a signature error if it calls the wx.requestPayment method. resultMap.put("timeStamp", timeStamp + ""); //Sign again, which is used to call the wx.requesetPayment method on the widget side resultMap.put("appId",ServiceUtil.sub_appid); Map resultMap1=new HashMap(); resultMap1.put("appId",ServiceUtil.sub_appid); resultMap1.put("timeStamp",timeStamp + ""); resultMap1.put("nonceStr",nonceStr); resultMap1.put("package","prepay_id="+prepayid); resultMap1.put("signType","MD5"); String sign = WXPayUtil.generateSignature(resultMap1,ServiceUtil.service_key); resultMap.put("paySign", sign); return resultMap;
Note that the appid given here is the appid of the current applet, which is the sub_appid I wrote in the parameter description earlier.
key is a service provider. Don't make a mistake.
This is the end of the road to fill the pit.