SpringBoot實(shí)現(xiàn)微信支付接口調(diào)用及回調(diào)函數(shù)(商戶參數(shù)獲取)
一、具體業(yè)務(wù)流程
1. 用戶下單
- 前端操作:
- 用戶在應(yīng)用中選擇商品、填寫訂單信息(如地址、聯(lián)系方式等),并點(diǎn)擊“下單”按鈕。
- 前端將訂單信息(商品ID、數(shù)量、價(jià)格等)發(fā)送到后端。
- 后端處理:
- 接收到訂單請(qǐng)求后,生成唯一的訂單號(hào)(`out_trade_no`)。
- 將訂單信息存儲(chǔ)到數(shù)據(jù)庫(kù)中,設(shè)置訂單狀態(tài)為“待支付”。
2. 后端創(chuàng)建訂單
- 構(gòu)建請(qǐng)求參數(shù):
- 使用商戶號(hào)、應(yīng)用ID、隨機(jī)字符串、訂單描述、商戶訂單號(hào)、金額(單位:分)、IP 地址等構(gòu)建 XML 格式的請(qǐng)求數(shù)據(jù)。
- 發(fā)送請(qǐng)求:
- 使用 HTTP POST 方法將請(qǐng)求數(shù)據(jù)發(fā)送到微信的統(tǒng)一下單 API(`https://api.mch.weixin.qq.com/pay/unifiedorder`)。
- 處理響應(yīng):
- 接收微信返回的響應(yīng)數(shù)據(jù)(XML 格式),解析響應(yīng)內(nèi)容。
- 檢查返回的 `return_code` 和 `result_code`,確保請(qǐng)求成功。
- 獲取 `prepay_id`,并根據(jù)它生成支付簽名等信息。
3. 返回支付信息
- 返回給前端:
- 將 `prepay_id` 和其他必要參數(shù)(如時(shí)間戳、隨機(jī)字符串、簽名等)封裝成 JSON 響應(yīng)返回給前端。
- 前端支付:
- 前端使用微信支付 SDK,調(diào)用支付接口啟動(dòng)支付流程。
- 用戶確認(rèn)支付后,微信客戶端處理支付。
4. 用戶確認(rèn)支付
- 用戶行為:
- 用戶在微信中查看支付信息,確認(rèn)后進(jìn)行支付。
- 支付結(jié)果:
- 微信處理支付請(qǐng)求,完成后將結(jié)果異步通知你的服務(wù)器。
5. 微信支付回調(diào)
- 回調(diào) URL 配置:
- 在微信商戶平臺(tái)配置你的回調(diào) URL(如 `https://yourdomain.com/wechat/notify`)。
- 處理回調(diào)請(qǐng)求:
- 接收到來(lái)自微信的 POST 請(qǐng)求,讀取請(qǐng)求體中的 XML 數(shù)據(jù)。
- 驗(yàn)證簽名:
- 提取回調(diào)數(shù)據(jù)中的簽名字段,使用相同的參數(shù)生成新的簽名,與返回的簽名進(jìn)行比較,確保數(shù)據(jù)的完整性和有效性。
- 更新訂單狀態(tài):
- 根據(jù)回調(diào)數(shù)據(jù)中的 `result_code` 更新數(shù)據(jù)庫(kù)中的訂單狀態(tài)。如果支付成功,修改訂單狀態(tài)為“已支付”,并進(jìn)行相應(yīng)的業(yè)務(wù)處理(如發(fā)貨)。
- 返回處理結(jié)果:
- 向微信返回處理結(jié)果,通常是 `<xml><return_code>SUCCESS</return_code></xml>`。
6. 返回處理結(jié)果
- 響應(yīng)微信:
- 確保響應(yīng)格式正確,避免微信因無(wú)法解析而重發(fā)通知。
7. 訂單狀態(tài)查詢(可選)
- 查詢訂單狀態(tài):
- 在用戶支付后的一段時(shí)間內(nèi),可以調(diào)用微信的訂單查詢 API(`https://api.mch.weixin.qq.com/pay/orderquery`)來(lái)確認(rèn)訂單的狀態(tài)。
- 處理結(jié)果:
- 根據(jù)查詢結(jié)果更新本地訂單狀態(tài),確保數(shù)據(jù)一致性。
8. 訂單完成
- 后續(xù)處理:
- 一旦訂單支付成功并發(fā)貨,可以根據(jù)業(yè)務(wù)需求進(jìn)行后續(xù)操作,例如發(fā)送確認(rèn)郵件、更新庫(kù)存等。
二、代碼具體實(shí)現(xiàn)
1. 商戶參數(shù)配置
在 application.properties 中配置微信支付的相關(guān)參數(shù):
# 微信支付配置 wechat.pay.appId=your_app_id wechat.pay.mchId=your_mch_id wechat.pay.apiKey=your_api_key wechat.pay.notifyUrl=https://yourdomain.com/wechat/notify
2. 創(chuàng)建 Spring Boot 項(xiàng)目
確保你的項(xiàng)目引入了必要的依賴。在 pom.xml 中添加以下內(nèi)容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.18</version>
</dependency>3. 創(chuàng)建微信支付服務(wù)類
創(chuàng)建一個(gè)服務(wù)類 WeChatPayService,用于處理訂單的創(chuàng)建和簽名等操作。
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class WeChatPayService {
@Value("${wechat.pay.appId}")
private String appId;
@Value("${wechat.pay.mchId}")
private String mchId;
@Value("${wechat.pay.apiKey}")
private String apiKey;
@Value("${wechat.pay.notifyUrl}")
private String notifyUrl;
private static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
public String createOrder(String orderNo, double amount) throws Exception {
String nonceStr = String.valueOf(System.currentTimeMillis());
String xmlData = "<xml>"
+ "<appid>" + appId + "</appid>"
+ "<mch_id>" + mchId + "</mch_id>"
+ "<nonce_str>" + nonceStr + "</nonce_str>"
+ "<body>Product Description</body>"
+ "<out_trade_no>" + orderNo + "</out_trade_no>"
+ "<total_fee>" + (int) (amount * 100) + "</total_fee>"
+ "<spbill_create_ip>127.0.0.1</spbill_create_ip>"
+ "<notify_url>" + notifyUrl + "</notify_url>"
+ "<trade_type>APP</trade_type>"
+ "</xml>";
// 生成簽名并添加到請(qǐng)求數(shù)據(jù)
String sign = WeChatPayUtil.generateSign(xmlData, apiKey);
xmlData = xmlData.replace("</xml>", "<sign>" + sign + "</sign></xml>");
try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpPost post = new HttpPost(UNIFIED_ORDER_URL);
post.setEntity(new StringEntity(xmlData, "UTF-8"));
post.setHeader("Content-Type", "text/xml");
String response = EntityUtils.toString(client.execute(post).getEntity(), "UTF-8");
return response; // 解析并返回需要的信息
}
}
}4. 創(chuàng)建微信支付控制器
創(chuàng)建一個(gè)控制器 WeChatPayController,處理用戶的下單請(qǐng)求(@PostMapping("/createOrder"))和回調(diào)@PostMapping("/notify")。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/wechat")
public class WeChatPayController {
@Autowired
private WeChatPayService weChatPayService;
@PostMapping("/createOrder")
public String createOrder(@RequestParam String orderNo, @RequestParam double amount) {
try {
return weChatPayService.createOrder(orderNo, amount);
} catch (Exception e) {
e.printStackTrace();
return "Error creating order";
}
}
@PostMapping("/notify")
public String handleCallback(HttpServletRequest request) {
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
String xmlData = sb.toString();
Map<String, String> data = WeChatPayUtil.parseXml(xmlData); // 解析 XML 數(shù)據(jù)
// 驗(yàn)證簽名
String sign = data.get("sign");
if (WeChatPayUtil.generateSign(xmlData, apiKey).equals(sign)) {
// 處理業(yè)務(wù)邏輯,例如更新訂單狀態(tài)
String resultCode = data.get("result_code");
if ("SUCCESS".equals(resultCode)) {
String orderNo = data.get("out_trade_no");
// 更新訂單狀態(tài)為已支付
// updateOrderStatus(orderNo, "PAID");
}
return "<xml><return_code>SUCCESS</return_code></xml>";
} else {
return "<xml><return_code>FAIL</return_code></xml>";
}
}
}5. 簽名和 XML 處理工具類
創(chuàng)建一個(gè)工具類 WeChatPayUtil,負(fù)責(zé)簽名和 XML 解析。
import com.thoughtworks.xstream.XStream;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class WeChatPayUtil {
public static String generateSign(String xmlData, String apiKey) {
// 將 XML 轉(zhuǎn)換為 Map
Map<String, String> data = parseXml(xmlData);
TreeMap<String, String> sortedMap = new TreeMap<>(data);
StringBuilder stringBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
if (!entry.getKey().equals("sign") && entry.getValue() != null) {
stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
}
stringBuilder.append("key=").append(apiKey);
return md5(stringBuilder.toString()).toUpperCase();
}
public static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : digest) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Map<String, String> parseXml(String xml) {
// 使用 XStream 解析 XML
XStream xStream = new XStream();
xStream.alias("xml", HashMap.class);
return (Map<String, String>) xStream.fromXML(xml);
}
}三、參數(shù)配置及獲取
一、回調(diào)函數(shù)的配置步驟
在微信商戶平臺(tái)配置回調(diào)地址:
- 登錄微信商戶平臺(tái)。
- 找到“賬戶設(shè)置”或“API安全”選項(xiàng)。
- 在“支付結(jié)果通知 URL”中填寫你的回調(diào)地址(如
https://yourdomain.com/wechat/notify)。
二、商戶參數(shù)獲取
商戶參數(shù)主要包括微信支付的相關(guān)信息,這些信息可以在微信商戶平臺(tái)上獲取。
商戶參數(shù)
- appId: 公眾賬號(hào)ID,由微信開(kāi)放平臺(tái)或微信支付商戶平臺(tái)提供。
- mchId: 商戶號(hào),由微信支付商戶平臺(tái)提供。
- apiKey: API 密鑰,在微信支付商戶平臺(tái)設(shè)置,用于簽名請(qǐng)求。
- notifyUrl: 支付結(jié)果通知地址,即微信支付成功后,微信服務(wù)器將異步通知該地址。
到此這篇關(guān)于SpringBoot實(shí)現(xiàn)微信支付接口調(diào)用及回調(diào)函數(shù)(商戶參數(shù)獲取)的文章就介紹到這了,更多相關(guān)SpringBoot微信支付接口調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java?Springboot對(duì)接開(kāi)發(fā)微信支付詳細(xì)流程
- SpringBoot對(duì)接小程序微信支付的實(shí)現(xiàn)
- Springboot整合微信支付(訂單過(guò)期取消及商戶主動(dòng)查單)
- UniApp?+?SpringBoot?實(shí)現(xiàn)微信支付和退款功能
- SpringBoot實(shí)現(xiàn)整合微信支付方法詳解
- springboot對(duì)接微信支付的完整流程(附前后端代碼)
- 一篇文章帶你入門Springboot整合微信登錄與微信支付(附源碼)
- springboot整合微信支付sdk過(guò)程解析
- SpringBoot+MyBatis集成微信支付實(shí)現(xiàn)示例
相關(guān)文章
java如何用遞歸生成樹(shù)形結(jié)構(gòu)
作者分享了自己在使用腳本之家資源進(jìn)行編程時(shí)的經(jīng)驗(yàn),包括準(zhǔn)備實(shí)體對(duì)象、測(cè)試數(shù)據(jù)、構(gòu)造樹(shù)形結(jié)構(gòu)遞歸函數(shù)、測(cè)試以及輸出結(jié)果等步驟,作者希望這些經(jīng)驗(yàn)?zāi)軐?duì)大家有所幫助,并鼓勵(lì)大家支持腳本之家2025-03-03
java中g(shù)radle項(xiàng)目報(bào)錯(cuò)org.gradle?.api.plugins.MavenPlugin解決辦法
在使用Gradle時(shí)開(kāi)發(fā)者可能會(huì)遇到org.gradle?.api.plugins.MavenPlugin報(bào)錯(cuò)提醒,這篇文章主要給大家介紹了關(guān)于java中g(shù)radle項(xiàng)目報(bào)錯(cuò)org.gradle?.api.plugins.MavenPlugin的解決辦法,需要的朋友可以參考下2023-12-12
springboot?vue測(cè)試列表遞歸查詢子節(jié)點(diǎn)下的接口功能實(shí)現(xiàn)
這篇文章主要為大家介紹了springboot?vue測(cè)試列表遞歸查詢子節(jié)點(diǎn)下的接口功能實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
MyBatis_Generator插件的安裝以及簡(jiǎn)單使用方法(圖解)
下面小編就為大家?guī)?lái)一篇MyBatis_Generator插件的安裝以及簡(jiǎn)單使用方法(圖解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
SpringBoot下使用定時(shí)任務(wù)的方式全揭秘(6種)
這篇文章主要介紹了SpringBoot下使用定時(shí)任務(wù)的方式全揭秘(6種),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
kettle指定jdk8的路徑啟動(dòng)的實(shí)現(xiàn)
本文主要介紹了指定jdk8的路徑啟動(dòng)的實(shí)現(xiàn),通過(guò)修改kettle的配置文件來(lái)指定使用jdk8版本啟動(dòng),具有一定的參考價(jià)值,感興趣的可以了解一下2025-03-03
SpringBoot 改造成https訪問(wèn)的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot 改造成https訪問(wèn)的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
Java實(shí)現(xiàn)NIO聊天室的示例代碼(群聊+私聊)
這篇文章主要介紹了Java實(shí)現(xiàn)NIO聊天室的示例代碼(群聊+私聊),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05
Spring?依賴注入和循環(huán)依賴的實(shí)例解析
依賴注入的主要目的是降低類之間的耦合度,使得代碼更加靈活、可維護(hù)和可測(cè)試,這篇文章主要介紹了Spring?依賴注入和循環(huán)依賴的相關(guān)知識(shí),需要的朋友可以參考下2023-09-09

