1: Early WeChat payment literacy knowledge
The prerequisite is that there is already an official account that has applied for the WeChat payment function, and then we need to obtain the official account APPID and WeChat merchant account. This can be found on the WeChat official account and WeChat payment merchant platform respectively. In fact, after you successfully apply for the payment function, WeChat will forward the Mail to you via email. With this information, we can go to the WeChat payment service support page: https://pay.weixin.qq.com/service_provider/index.shtml
Open this page and click the link [Development Document] in the upper right corner to enter the API document description page, which looks like the following
Choose the red circle to scan the code to pay, which means we need to do the access method. Move the mouse to the above and prompt you to view the development document. If you don’t know how to view this, you can take a shower and go to bed. You are really not suitable for a programmer. The address is as follows:
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 You will see after opening in your browser
The content we focus on and read is already marked with a red ellipse. First, read the protocol specifications in [Interface Rules]. Just kidding, if you don’t read this, you want to do WeChat payment. This is like you want to pick up girls. You have to collect some basic background information first and understand the characteristics of the other party, otherwise how can you communicate below. It turns out that only programmers who can pick up girls are good salesmen. After going off topic, we will look at the cases and specifications in [Scene Introduction]. Just look at the LOGO of WeChat Pay. This is to finally put it on our own QR code payment webpage, which looks more professional. Afterwards, focus on [Mode 2]
Here we are going to use the mode 2 method to realize the PC page scanning code payment function.
The official explanation of mode 2 by WeChat is as follows: "The merchant backend system first calls the unified single interface of WeChat Pay, the WeChat backend system returns the link parameter code_url, the merchant backend system generates a QR code picture with the code_url value, and the user scans the code code client and initiates payment. Note: the validity period of code_url is 2 hours, and after the expiration, you cannot initiate payment." If you understand, we must first call WeChat to provide a unified single interface and get a key information code_url (as for what the hell is this code_url, I don’t know), and then we generate a QR code through our own program. I use Google’s zxing library here. Then just display the QR code on your PC web page. In this way, the terminal user will pay by scanning the code and the payment will be completed. You must be very excited to see this. You find that WeChat payment is so simple. There is another thing we don’t know yet. The customers know that they have paid, but our server side doesn’t know yet. With the IQ of WeChat developers, they have thought of this problem for a long time. So when you call the unified single interface, there is a required parameter that is the callback URL. That is, if the client successfully pays, WeChat will submit some data to our own server through this URL, and then we parse the data in the background to complete our own operations. Only then can we know whether the customer has really paid through WeChat. This way the whole process is over, and this is Pattern 2. WeChat uses a timing diagram to represent this process.
It is complicated to express and seems to be difficult. To summarize, what our server should do is as follows:
1. Pass the correct parameters (of course, our callback URL) and signature verification through unified single interface, and get the corresponding data of code_url from the return data.
2. Based on the code_url data, we generate a QR code image and display it on the browser web page.
3. Add our own business logic processing in the URL of the callback.
The literacy is over now, and you finally know what kind of process to pay by scanning the code. Let’s take a look at its relevant API usage and do a good job of processing every step.
Two: Development process
Before developing the code, please prepare a few things first.
1. Add ZXing's maven dependency
2. Add jdom's maven dependency
3. Download the Java version SDK demo program, the address is here
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1
We need MD5Util.java and XMLUtil.java two files
4. We use HttpClient version 4.5.1, remember to add Maven dependencies
After the above preparations are done, continue reading:
First, we need to call WeChat’s unified single interface. When we click on the unified single in [API List], we will see a page like this:
Taking the actual situation of my call as an example, the following parameters are necessary. For everyone's convenience, I have turned it into a POJO object. The code is as follows:
public class UnifiedorderDto implements WeiXinConstants {private String appid;private String body;private String device_info;private String mch_id;private String nonce_str;private String notify_url;private String openId;private String out_trade_no;private String spbill_create_ip;private int total_fee;private String trade_type;private String product_id;private String sign;public UnifiedorderDto() {this.appid = APPID;this.mch_id = WXPAYMENTACCOUNT;this.device_info = DEVICE_INFO_WEB;this.notify_url = CALLBACK_URL;this.trade_type = TRADE_TYPE_NATIVE;}public String getAppid() {return appid;}public void setAppid(String appid) {this.appid = appid;}public String getBody() {return body;}public void setBody(String body) {this.body = body;}public String getDevice_info() {return device_info;}public void setDevice_info(String device_info) {this.device_info = device_info;}public String getMch_id() {return mch_id;}public void setMch_id(String mch_id) {this.mch_id = mch_id;}public String getNonce_str() {return nonce_str;}public void setNonce_str(String nonce_str) {this.nonce_str = nonce_str;}public String getNotify_url() {return notify_url;}public void setNotify_url(String notify_url) {this.notify_url = notify_url;}public String getOpenId() {return openId;}public void setOpenId(String openId) {this.openId = openId;}public String getOut_trade_no() {return out_trade_no;}public void setOut_trade_no(String out_trade_no) {this.out_trade_no = out_trade_no;}public String getSpbill_create_ip() {return spbill_create_ip;}public void setSpbill_create_ip(String spbill_create_ip) {this.spbill_create_ip = spbill_create_ip;}public int getTotal_fee() {return total_fee;}public void setTotal_fee(int total_fee) {this.total_fee = total_fee;}public String getTrade_type() {return trade_type;}public void setTrade_type(String trade_type) {this.trade_type = trade_type;}public String getSign() {return sign;}public void setSign(String sign) {this.sign = sign;}public String getProduct_id() {return product_id;}public void setProduct_id(String product_id) {this.product_id = product_id;}public String generateXMLContent() {String xml = "<xml>" +"" + this.appid + "</appid>" + "" + this.body + "" + "<device_info>WEB</device_info>" + "<mch_id>" + this.mch_id + "</mch_id>" + "<nonce_str>" + this.nonce_str + "</nonce_str>" +"<notify_url>" + this.notify_url + "</notify_url>" + "<out_trade_no>" + this.out_trade_no + "</out_trade_no>" + "<product_id>" + this.product_id + "</product_id>" +"<spbill_create_ip>" + this.spbill_create_ip+ "</spbill_create_ip>" +"<total_fee>" + String.valueOf(this.total_fee) + "</total_fee>" + "<trade_type>" + this.trade_type + "</trade_type>" + "<sign>" + this.sign + "</sign>" + "</xml>";return xml;}public String makeSign() {String content ="appid=" + this.appid + "&body=" + this.body + "&device_info=WEB" + "&mch_id=" + this.mch_id + "&nonce_str=" + this.nonce_str + "?ify_url=" + this.notify_url +"&out_trade_no=" + this.out_trade_no + "&product_id=" + this.product_id + "&spbill_create_ip=" + this.spbill_create_ip+"&total_fee=" + String.valueOf(this.total_fee) +"&trade_type=" + this.trade_type;content = content + "&key=" + WeiXinConstants.MD5_API_KEY;String signature = WeiXinPaymentUtil.MD5Encode(content, "utf-8");return signature.toUpperCase();}}The explanation of each member variable can be found in the description of [Unified Single Interface].
After this, we need to fill in the content we set, call the interface to get the return data, get the code_url data, and generate a two-dimensional picture based on it, return the image address to the PC web page, and then it will be displayed. Here we will make a special note that when we click on WeChat payment, we will call our own backend SpringMVC Controller through ajax method, and then complete the unified single interface analysis of WeChat through HTTPClient in the corresponding method of the Controller to obtain the XML data returned by code_url, and then generate the QR code and return it to the front page. The code implemented in Controller is as follows:
Map<string,object> result=new HashMap<string,object>();UnifiedorderDto dto = new UnifiedorderDto();if(cash == null || "".equals(cash)) {result.put("error", "cash could not be zero");return result;}int totalfee = 100*Integer.parseInt(cash);logger.info("total recharge cash : " + totalfee);dto.setProduct_id(String.valueOf(System.currentTimeMillis()));dto.setBody("repair");dto.setNonce_str(String.valueOf(System.nanoTime()));LoginInfo loginInfo = LoginInfoUtil.getLoginInfo();// through our background order number + UUID, the identity identification flag dto.setOut_trade_no("Your order number + key information, it is sent back after WeChat callback, you can verify");dto.setTotal_fee(totalfee);dto.setSpbill_create_ip("127.0.0.1");// generate signedto.setSign(dto.makeSign());logger.info("sign : " + dto.makeSign());logger.info("xml content : " + dto.generateXMLContent());try {HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost post = new HttpPost(WeiXinConstants.UNIFIEDORDER_URL);post.addHeader("Content-Type", "text/xml; charset=UTF-8");StringEntity xmlEntity = new StringEntity(dto.generateXMLContent(), ContentType.TEXT_XML);post.setEntity(xmlEntity);HttpResponse httpResponse = httpClient.execute(post);String responseXML = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");logger.info("response xml content : " + responseXML);// parse CODE_URL CONTENTMap<string, string=""> resultMap = (Map<string, string="">)XMLUtil.doXMLParse(responseXML);logger.info("response code_url : " + resultMap.get("code_url"));String codeurl = resultMap.get("code_url");if(codeurl != null && !"".equals(codeurl)) {String imageurl = generateQrcode(codeurl);result.put("QRIMAGE", imageurl);}post.releaseConnection();} catch(Exception e) {e.printStackTrace();}result.put("success", "1");return result;</string,></string,></string,object></string,object>The code that generates the QR code is as follows:
private String generateQrcode(String codeurl) {File folder = new File(basePath + "qrcode");if(!foldler.exists()) {foldler.mkdirs();}String f_name = UUIDUtil.uuid() + ".png";try {File f = new File(basePath + "qrcode", f_name);FileOutputStream fio = new FileOutputStream(f);MultiFormatWriter multiFormatWriter = new MultiFormatWriter();Map hints = new HashMap();hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); //Set the character set encoding type BitMatrix bitMatrix = null;bitMatrix = multiFormatWriter.encode(codeurl, BarcodeFormat.QR_CODE, 300, 300, hints);BufferedImage image = toBufferedImage(bitMatrix);//Output QR code image stream ImageIO.write(image, "png", fio);return ("qrcode/" + f_name);} catch (Exception e1) {e1.printStackTrace();return null;} }At this time, after scanning the WeChat QR code on the client, we will use the callback to make the URL and return the data to us. We will complete our own processing in the callback method. It is important to note here that your callback interface must be implemented through the HTTP POST method, otherwise XML data will not be accepted. The code for the callback processing is as follows:
@RequestMapping(value = "/your_callback_url", method = RequestMethod.POST)@ResponseBodypublic void finishPayment(HttpServletRequest request, HttpServletResponse response) {try { logger.info("start to callback from weixin server: " + request.getRemoteHost());Map<string, string=""> resultMap = new HashMap<string, string="">();InputStream inputStream = request.getInputStream();// Read the input stream SAXBuilder saxBuilder= new SAXBuilder();Document document = saxBuilder.build(inputStream);// Get the xml root element Element root = document.getRootElement();// Get all child nodes of the root element List list = root.getChildren();Iterator it = list.iterator();while(it.hasNext()) {Element e = (Element) it.next();String k = e.getName();String v = "";List children = e.getChildren();if(children.isEmpty()) {v = e.getTextNormalize();} else {v = XMLUtil.getChildrenText(children);} resultMap.put(k, v);}// Verify the signature! ! ! /*String[] keys = resultMap.keySet().toArray(new String[0]);Arrays.sort(keys);String kvparams = "";for(int i=0; i<keys.length; i++)="" {="" if(keys[i].equals("sign"))="" continue;="" }="" Signature algorithm="" if(i="=" 0)="" kvparams="" +="(keys[i]" "=" + resultMap.get(keys[i]));} else {kvparams += (" &"="" keys[i]="" &key=" + WeiXinConstants.MD5_API_KEY;String md5esign = WeiXinPaymentUtil.MD5Encode(esign, " utf-8");="" if(!md5esign.equals(resultmap.get("sign")))="" return;="" }*="" Close stream="" Free resource="" inputstream.close();="" inputstream="null;" string="" returncode="resultMap.get("return_code");" outtradeno="resultMap.get("out_trade_no");" in units of division="" int="" nfee="Integer.parseInt(resultMap.get("total_fee"));" logger.info("out="" trade="" no="" :="" outtradeno);="" logger.info("total_fee="" nfee);="" business processing process="" if("success".equals(returncode))="" todo:="" your="" business="" process="" add="" here="" response.getwriter().print(xmlutil.getretresultxml(resultmap.get("return_code"),="" resultmap.get("return_code")));="" else="" resultmap.get("return_msg")));="" catch(ioexception="" ioe)="" ioe.printstacktrace();="" catch="" (jdomexception="" e1)="" e1.printstacktrace();="" }Remember to use the two classes of xmlutil and md5util used in the official Java version of WeChat demo. The demo code can be found on its official demo page. The relevant maven dependencies are as follows:
<dependency><groupid>jdom</groupid>jdom</artifactid><version>1.1</version></dependency><dependency><groupid>com.google.zxing</groupid>core</artifactid><version>3.3.0</version></dependency>
Finally, I need to pay special attention to the signature. I directly downloaded the Java version of the Demo program from the official WeChat website to obtain it, because this is the best choice to ensure that the MD5 signature is consistent. For the specific algorithm for generating signatures, you can view the official WeChat document. Here we strongly recommend that you must explain the official API. 90% of the various problems you encounter in development are because you do not read the official documents, but trust someone’s blog! This is the real purpose and purpose of my writing this article. According to the official documents, I implemented it with my Java code. Scan the QR code on WeChat PC web pages and pay for payment will definitely fly in your WEB application.
The above is the Java SpringMVC implementation of PC web page WeChat QR code payment (full version) introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!