当前位置:网站首页>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
边栏推荐
- What is label encoding? How to distinguish and use one hot encoding and label encoding?
- Halcon and WinForm study section 2
- Halcon and WinForm study section 1
- Halcon与Winform学习第二节
- Didi off the shelf! Data security is national security
- [cloud native training camp] module VIII kubernetes life cycle management and service discovery
- 求字符串函数和长度不受限制的字符串函数的详解
- What are the composite types of Blackhorse Clickhouse, an OLAP database recognized in the industry
- [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 赋值后状态不变化
猜你喜欢
The state does not change after the assignment of El switch
What are the composite types of Blackhorse Clickhouse, an OLAP database recognized in the industry
Jvm-02-class loading subsystem
Halcon与Winform学习第一节
What is embedding (encoding an object into a low dimensional dense vector), NN in pytorch Principle and application of embedding
Visual upper system design and development (Halcon WinForm) -3 Image control
el-switch 赋值后状态不变化
找映射关系
Mysql报错:[ERROR] mysqld: File ‘./mysql-bin.010228‘ not found (Errcode: 2 “No such file or directory“)
Matplotlib drawing label cannot display Chinese problems
随机推荐
Halcon与Winform学习第一节
Win10 enterprise 2016 long term service activation tutorial
Jvm-03-runtime data area PC, stack, local method stack
通过进程PID获取可执行文件路径(QueryFullProcessImageName)
视觉上位系统设计开发(halcon-winform)
Custom annotation
[combinatorics] combinatorial identities (recursive combinatorial identities | sum of variable terms | simple combinatorial identities and | sum of variable terms | staggered sums of combinatorial ide
Creation and destruction of function stack frames
The method of parameter estimation of user-defined function in MATLAB
redis单线程问题强制梳理门外汉扫盲
Didi off the shelf! Data security is national security
互斥对象与临界区的区别
Visual upper system design and development (Halcon WinForm) -2 Global variable design
使用JMeter对WebService进行压力测试
视觉上位系统设计开发(halcon-winform)-3.图像控件
[transform] [practice] use pytoch's torch nn. Multiheadattention to realize self attention
Introduction to redis master-slave, sentinel and cluster mode
秒杀系统3-商品列表和商品详情
【云原生训练营】模块七 Kubernetes 控制平面组件:调度器与控制器
leetcode_ Power of Four