当前位置:网站首页>Wechat payment -jsapi: code implementation (payment asynchronous callback, Chinese parameter solution)
Wechat payment -jsapi: code implementation (payment asynchronous callback, Chinese parameter solution)
2022-07-03 15:24:00 【Don't wear perfume】
The conditions required for wechat payment have been configured , The next step is to implement ( The following is for reference only )
One , Preparation before implementation
①, Read official payment documents , Mainly business process https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4
②, official demo download https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
③,js Payment request method selection ( I chose chooseWXPay, Choose this according to your own situation )
1. Merchant platform : Web page through JavaScript call getBrandWCPayRequest Interface , Initiate wechat payment request
2. Public platform : call chooseWXPay Realization

3. Difference between them : choice getBrandWCPayRequest Words , The payment page does not need to introduce any js, choose chooseWXPay Words , Need to introduce JS file
Two , Code implementation

1. Front end page core code
①, introduce js
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>②,config Interface injection authority verification (requestUrl Is the routing address of the current page )
var reUrl =window.location.href; $.ajax({
url: "/wxPay/getWXConfig?requestUrl="+encodeURIComponent(reUrl),
dataType: "json",
async: false,
type: "GET",
success: function (data) {
wx.config({
debug: false, // Turn on debugging mode , Call all api The return value of will be on the client side alert come out , To see the parameters passed in , Can be in pc End open , The parameter information will go through log play , Only in pc Only when the end is printed .
appId: data.appId, // Required , The only sign of official account number
timestamp:data.timestamp, // Required , Generate signature timestamp
nonceStr: data.nonceStr, // Required , Generate a random string of signatures
signature: data.signature,// Required , Signature
jsApiList: ['chooseWXPay'] // Required , Required JS Interface list
});
}
});geWxConfig The implementation method of can refer to : Wechat sharing development : Code implementation [ front end + Back end ]( Two )
③, Payment calls the unified order interface ( Please define the back-end interface according to your business )
<button style="width:90%; margin-left:5%; margin-bottom:20px; height:40px;line-height:40px;background-color:#4395FF;color:white;border:none; font-size:11pt;font-weight:bold " onclick="SaveOrWxPay();"> Save and pay </button> function SaveOrWxPay() {
$.ajax({
url: "/wxPay/pay2?openId="+ GetPar("token")+"&totalFee="+$("#labTotalCost").text()+"&operationNO="+$("#labOperationNO").text()+"&userName="+$("#UserName").val()+"&userPhone="+$("#UserPhone").val(),
dataType: "json",
async: false,
type: "GET",
success: function (data) {
wx.chooseWXPay({
timestamp: data.timeStamp, // Payment signature time stamp , Pay attention to wechat jssdk All uses in timestamp Fields are all lowercase . But the latest version of the payment background generation signature uses timeStamp The field name should be capitalized S character
nonceStr: data.nonceStr, // Payment signature random string , Not longer than 32 position
package: data.package, // Returned by unified payment interface prepay_id Parameter values , The submission format is as follows :prepay_id=\*\*\*)
signType: data.signType, // Signature method , The default is 'SHA1', To use the new version of payment, you need to transfer in 'MD5'
paySign: data.paySign, // Payment signature
success: function (res) {
// Click here after successful payment [ complete ] After the callback , It can be processed according to its own business needs
},
});
}
});
}2. Back end core code

According to the unified order API, The necessary parameters are :
appid: Public accounts ID mch_id: Merchant number nonce_str: Random string sign: Signature
body: Commodity Description out_trade_no: Merchant order number total_fee: Bid price amount spbill_create_ip: terminal IP
trade_type: Type of transaction openid: User ID , Authorized to log in to official account to obtain
notify_url: Notice address ( We can process the business logic after successful payment in this , For example, modify the payment status )
①openid For reference Wechat authorized login : Mobile [unionid]( One ), Modify yourself
② Next is the core code about payment
/**
* @description: Wechat payment - Unified order
* @author: lvyq
* @date: 2020/9/16 16:30
* @version 1.0
*/
@ApiOperation(value = " Wechat payment - Unified order ")
@RequestMapping(value = "/pay2", method = {RequestMethod.POST, RequestMethod.GET})
public Object Orders(HttpServletRequest request, String openId, String tradeNo, String totalFee,String operationNO,String userName,String userPhone) {
CommonUtils commonUtils = new CommonUtils();
totalFee=String.format("%.0f", Float.valueOf(totalFee)*100);
//TODO The order number is temporarily self generated
tradeNo = new CommonUtils().getRandomStringByLength(32);
String nonce_str = WXPayUtil.generateNonceStr();
try {
Map<String, String> paraMap = new HashMap<>();
// Get request ip Address
String ip = commonUtils.getIPAddress(request);
paraMap.put("appid", appid);
paraMap.put("mch_id", mchid);
paraMap.put("nonce_str", nonce_str);
// Signature
String sign = WXPayUtil.generateSignature(paraMap, paternerKey);
paraMap.put("sign", sign);
paraMap.put("body", " Maintenance and management service fee settlement ");
paraMap.put("out_trade_no", tradeNo);
paraMap.put("total_fee", totalFee);
paraMap.put("spbill_create_ip", ip);
// TODO Payment asynchronous callback address
// Transcode Chinese here
String RuserName=URLEncoder.encode(userName, "UTF-8");
paraMap.put("notify_url", commonUtils.getDomainName(request).toString() + "/wxPay/callback2/"+operationNO+"/"+RuserName+"/"+userPhone);
System.out.print("notify_url==="+commonUtils.getDomainName(request).toString() + "/wxPay/callback2/"+operationNO+"/"+RuserName+"/"+userPhone);
paraMap.put("trade_type", "JSAPI");
paraMap.put("openid", openId);
paraMap.put("sign_type", "MD5");
// Put all the parameters (map) turn xml Format
// String xml = WXPayUtil.mapToXml(paraMap);
String xml = WXPayUtil.generateSignedXml(paraMap, paternerKey);
// send out post request " Unified order interface " Back to pre payment id:prepay_id
String xmlStr = HttpRequest.sendPost(unifiedorderUrl, xml);
String prepay_id = "";// Advance payment id
if (xmlStr.indexOf("SUCCESS") != -1) {
Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
prepay_id = (String) map.get("prepay_id");
}
Map<String, String> payMap = new HashMap<String, String>();
payMap.put("appId", appid);
payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
payMap.put("nonceStr", WXPayUtil.generateNonceStr());
payMap.put("signType", "MD5");
payMap.put("package", "prepay_id=" + prepay_id);
String paySign = WXPayUtil.generateSignature(payMap, paternerKey);
payMap.put("paySign", paySign);
return payMap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @description: Payment callback address
* @author: lvyq
* @date: 2020/9/17 16:06
* @version 1.0
*/
@ApiOperation(value = " Payment callback address ")
@RequestMapping(value = "/callback2/{operationNO}/{userName}/{userPhone}", method = {RequestMethod.POST, RequestMethod.GET})
public String CallBack(HttpServletRequest request, HttpServletResponse response,@PathVariable("operationNO") String operationNO,@PathVariable("userName") String userName,@PathVariable("userPhone") String userPhone) throws Exception {
InputStream is = null;
// decode
String RuserName=URLDecoder.decode(userName,"UTF-8");
System.out.print("RuserName==="+RuserName+"userName=="+userName);
try {
// Get the requested stream information ( This is from wechat xml All formats can only be read using streams )
is = request.getInputStream();
String xml = commonUtils.nputStream2String(is);
// Sent by wechat xml turn map
Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);
if (WXPayUtil.isSignatureValid(notifyMap,paternerKey)) {
if (notifyMap.get("return_code").equals("SUCCESS")) {
if (notifyMap.get("result_code").equals("SUCCESS")) {
//TODO Business code , Add, delete, modify and check the data ...
}
}
}else {
// Signature error , If there is no sign Field , It is also considered to be a signature error
}
// Tell the wechat server that it has received the message , Prevent repeated callback on wechat
response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}③, Attached below commonUtil Part of the code
package com.jmdz.util;
import com.alibaba.fastjson.JSONObject;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.util.Random;
/**
* @description: Public tools
* @author: lvyq
* @date: 2020/9/15 11:35
* @version 1.0
*/
public class CommonUtils {
/**
* @description: Access to domain name ( agreement + domain name )
* @author: lvyq
* @date: 2020/9/15 11:36
* @version 1.0
*/
public String getDomainName(HttpServletRequest request){
// return request.getServerName()+":"+request.getServerPort();
return request.getScheme()+"://"+request.getServerName();
}
public String getIPAddress(HttpServletRequest request){
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (ip.indexOf(",") != -1) {
String[] ips = ip.split(",");
ip = ips[0].trim();
}
return ip;
}
public static String getRandomStringByLength(int length) {
String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
public static String nputStream2String(InputStream in) {
InputStreamReader reader = null;
try {
reader = new InputStreamReader(in, "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
BufferedReader br = new BufferedReader(reader);
StringBuilder sb = new StringBuilder();
String line = "";
try {
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}
③.HttpRequest
package com.jmdz.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
public class HttpRequest {
/**
* Assign to URL send out GET Method request
*
* @param url
* Send requested URL
* @param param
* Request parameters , Request parameter should be name1=value1&name2=value2 In the form of .
* @return URL Response result of the remote resource represented
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
System.out.println(urlNameString);
URL realUrl = new URL(urlNameString);
// Open and URL Connection between
URLConnection connection = realUrl.openConnection();
// Set common request properties
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// Establish the actual connection
connection.connect();
// Get all response header fields
Map<String, List<String>> map = connection.getHeaderFields();
// Traverse all response header fields
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// Definition BufferedReader Input stream to read URL Response
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println(" send out GET Exception in request !" + e);
e.printStackTrace();
}
// Use finally Block to close the input stream
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* Assign to URL send out POST Method request
*
* @param url
* Send requested URL
* @param param
* Request parameters , Request parameter should be name1=value1&name2=value2 In the form of .
* @return Response result of the remote resource represented
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// Open and URL Connection between
URLConnection conn = realUrl.openConnection();
// Set 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)");
// send out POST The request must be set to the following two lines
conn.setDoOutput(true);
conn.setDoInput(true);
// obtain URLConnection Object corresponding output stream
out = new PrintWriter(conn.getOutputStream());
// Send request parameters
out.print(param);
// flush Buffering of output streams
out.flush();
// Definition BufferedReader Input stream to read URL Response
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println(" send out POST Exception in request !"+e);
e.printStackTrace();
}
// Use finally Block to close the output stream 、 Input stream
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}
④,WXPayUtil ( This official website provides demo There is , Just use it . I won't post code )
3、 ... and , See the effect




============================== Split line ==============================

1. in order to notify_url The interface accepts parameters , Our interface adopts restful. Forge a without parameters url
2. If the callback address contains Chinese, you cannot callback the address , Therefore, when placing a unified order , Code Chinese parameters , Decode when receiving
边栏推荐
- Redis lock Optimization Practice issued by gaobingfa
- Redis cache penetration, cache breakdown, cache avalanche solution
- Win10 enterprise 2016 long term service activation tutorial
- Halcon与Winform学习第二节
- VS2017通过IP调试驱动(双机调试)
- Visual upper system design and development (Halcon WinForm) -3 Image control
- 使用Tengine解决负载均衡的Session问题
- [combinatorics] permutation and combination (set permutation, step-by-step processing example)
- Jvm-03-runtime data area PC, stack, local method stack
- [transformer] Introduction - the original author of Harvard NLP presented the annotated transformer in the form of line by line implementation in early 2018
猜你喜欢

el-switch 赋值后状态不变化

软件逆向破解入门系列(1)—xdbg32/64的常见配置及功能窗口
![[pytorch learning notes] datasets and dataloaders](/img/c0/9cd539caff34db3cccc44505bbe3c5.png)
[pytorch learning notes] datasets and dataloaders

Jvm-02-class loading subsystem
![[transform] [NLP] first proposed transformer. The 2017 paper](/img/33/f639ab527d5adedfdc39f8d8117c3e.png)
[transform] [NLP] first proposed transformer. The 2017 paper "attention is all you need" by Google brain team

Creation and destruction of function stack frames

Halcon and WinForm study section 2

Leasing cases of the implementation of the new regulations on the rental of jointly owned houses in Beijing

Matplotlib drawing label cannot display Chinese problems

String functions that you need to know
随机推荐
C语言刷题~Leetcode与牛客网简单题
qt使用QZxing生成二维码
Popular understanding of decision tree ID3
开启 Chrome 和 Edge 浏览器多线程下载
Calibre LVL
Idea does not specify an output path for the module
使用JMeter对WebService进行压力测试
求字符串函数和长度不受限制的字符串函数的详解
Concurrency-02-visibility, atomicity, orderliness, volatile, CAS, atomic class, unsafe
Dataframe returns the whole row according to the value
Redis主从、哨兵、集群模式介绍
Relationship between truncated random distribution and original distribution
redis缓存穿透,缓存击穿,缓存雪崩解决方案
Tensorflow realizes verification code recognition (II)
Halcon and WinForm study section 2
在MapReduce中利用MultipleOutputs输出多个文件
需要知道的字符串函数
[combinatorics] combinatorial identities (recursive combinatorial identities | sum of variable terms | simple combinatorial identities and | sum of variable terms | staggered sums of combinatorial ide
[transform] [NLP] first proposed transformer. The 2017 paper "attention is all you need" by Google brain team
Atlas atlas torque gun USB communication tutorial based on mtcom