当前位置:网站首页>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
边栏推荐
- Kubernetes 进阶训练营 Pod基础
- Kubernetes vous emmène du début à la fin
- Matplotlib drawing label cannot display Chinese problems
- 视觉上位系统设计开发(halcon-winform)-2.全局变量设计
- 通过进程PID获取可执行文件路径(QueryFullProcessImageName)
- Digital image processing -- popular Canny edge detection
- [attention mechanism] [first vit] Detr, end to end object detection with transformers the main components of the network are CNN and transformer
- [cloud native training camp] module VIII kubernetes life cycle management and service discovery
- Visual upper system design and development (Halcon WinForm) -3 Image control
- 秒殺系統3-商品列錶和商品詳情
猜你喜欢
北京共有产权房出租新规实施的租赁案例
Didi off the shelf! Data security is national security
Finally, someone explained the financial risk management clearly
视觉上位系统设计开发(halcon-winform)-4.通信管理
Seckill system 2 redis solves the problem of distributed session
GCC cannot find the library file after specifying the link library path
Halcon and WinForm study section 2
Kubernetes 进阶训练营 Pod基础
WinDbg分析dump文件
Functional modules and application scenarios covered by the productization of user portraits
随机推荐
Visual upper system design and development (Halcon WinForm) -3 Image control
Can‘t connect to MySQL server on ‘localhost‘
视觉上位系统设计开发(halcon-winform)-4.通信管理
Leasing cases of the implementation of the new regulations on the rental of jointly owned houses in Beijing
win32创建窗口及按钮(轻量级)
需要知道的字符串函数
Matlab r2011b neural network toolbox precautions
What is embedding (encoding an object into a low dimensional dense vector), NN in pytorch Principle and application of embedding
Apache ant extension tutorial
基于SVN分支开发模式流程浅析
leetcode_ Power of Four
Kubernetes advanced training camp pod Foundation
redis单线程问题强制梳理门外汉扫盲
[transform] [practice] use pytoch's torch nn. Multiheadattention to realize self attention
do{}while()的妙用
WinDbg分析dump文件
高并发下之redis锁优化实战
Popular understanding of gradient descent
Jvm-04-runtime data area heap, method area
Tensorflow realizes verification code recognition (II)