章
目
录
基于Spring Boot开发的项目如何接入微信支付功能?下面详细介绍如何在Spring Boot项目里完成微信支付的对接。
一、前期准备工作
(一)注册微信支付商户账号
首先,要前往微信支付商户平台进行注册,注册完成后需完成实名认证。这一步完成后,会获取到几个关键信息:
appid
:这是公众号或小程序的唯一标识AppID,在后续的支付流程中用于识别应用身份。mch_id
:即微信支付商户号,用于标识商户身份,是与微信支付交互的重要身份凭证。api_key
:这是在商户平台自行设置的API密钥,主要用于对支付请求进行签名,保障数据的安全性和完整性。notify_url
:支付结果回调地址,微信支付会将支付结果发送到这个地址,务必保证该地址能在公网上被访问到。
(二)配置开发环境
项目开发环境也有一定要求。一方面,要确保项目使用的是Java 8及以上版本,并且基于Spring Boot 2.x进行开发。另一方面,由于微信支付规定回调地址必须使用HTTPS,所以还需要配置好域名并开启HTTPS服务。
二、添加项目依赖
在Spring Boot项目的pom.xml
文件中,添加一些必要的依赖,这些依赖会在后续的开发过程中发挥重要作用:
<!-- HTTP客户端,用于发起HTTP请求与微信支付服务器交互 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- XML处理,因为微信支付的请求和响应数据大多是XML格式,这个依赖用于处理XML数据 -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- 其他Spring Boot基础依赖,用于构建Web应用,提供基础的Web功能支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
三、配置微信支付参数
(一)在配置文件中设置参数
在application.yml
文件里配置微信支付相关参数:
wxpay:
appid: your_appid
mch-id: your_mch_id
api-key: your_api_key
notify-url: https://your-domain.com/pay/notify
这里需要把your_appid
、your_mch_id
、your_api_key
和https://your-domain.com/pay/notify
替换成实际获取到的AppID、商户号、API密钥以及支付结果回调地址。
(二)读取配置参数
通过@ConfigurationProperties
注解读取配置文件中的参数:
@Configuration
@ConfigurationProperties(prefix = "wxpay")
@Data
public class WxPayConfig {
private String appid;
private String mchId;
private String apiKey;
private String notifyUrl;
}
这段代码定义了一个配置类WxPayConfig
,它会读取application.yml
中wxpay
前缀下的参数,并将其注入到对应的属性中。
四、实现工具类
(一)签名工具类
签名在支付过程中用于验证数据的完整性和真实性,下面是签名工具类的实现:
public class WxPayUtil {
public static String generateSign(Map<String, String> data, String apiKey) {
// 按参数名ASCII字典序排序
List<String> keyList = new ArrayList<>(data.keySet());
Collections.sort(keyList);
StringBuilder sb = new StringBuilder();
for (String key : keyList) {
if (!key.equals("sign") && data.get(key) != null &&!data.get(key).isEmpty()) {
sb.append(key).append("=").append(data.get(key)).append("&");
}
}
sb.append("key=").append(apiKey);
// MD5签名(或使用HMAC-SHA256)
return DigestUtils.md5Hex(sb.toString()).toUpperCase();
}
}
在这个工具类中,generateSign
方法首先对传入的参数进行排序,然后拼接成特定格式的字符串,最后使用MD5算法进行签名(也可以选择HMAC – SHA256算法)。
(二)HTTP请求工具类
为了方便与微信支付服务器进行通信,还需要一个HTTP请求工具类:
public class WxPayHttpClient {
public static String post(String url, String xmlData) throws IOException {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.setEntity(new StringEntity(xmlData, "UTF-8"));
post.setHeader("Content-Type", "application/xml");
CloseableHttpResponse response = client.execute(post);
return EntityUtils.toString(response.getEntity(), "UTF-8");
}
}
这个类的post
方法使用HttpClients
创建一个默认的HTTP客户端,然后构建一个POST请求,将XML格式的数据发送到指定的URL,并返回服务器的响应数据。
五、实现统一下单接口
在Controller中创建统一下单的接口:
@RestController
@RequestMapping("/pay")
public class WxPayController {
@Autowired
private WxPayConfig wxPayConfig;
@PostMapping("/create")
public String createOrder(@RequestBody OrderRequest orderRequest) throws Exception {
Map<String, String> data = new HashMap<>();
// 设置支付请求参数
data.put("appid", wxPayConfig.getAppid());
data.put("mch_id", wxPayConfig.getMchId());
data.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));
data.put("body", orderRequest.getBody());
data.put("out_trade_no", orderRequest.getOrderNo());
data.put("total_fee", String.valueOf(orderRequest.getTotalFee())); // 单位:分
data.put("spbill_create_ip", "123.12.12.123");
data.put("notify_url", wxPayConfig.getNotifyUrl());
data.put("trade_type", "NATIVE"); // 也可以是JSAPI、APP等
// 生成签名
String sign = WxPayUtil.generateSign(data, wxPayConfig.getApiKey());
data.put("sign", sign);
// 将参数转换为XML格式
String xmlData = mapToXml(data);
// 调用微信统一下单接口
String response = WxPayHttpClient.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xmlData);
// 解析返回的XML,获取code_url或prepay_id
Map<String, String> respData = parseXml(response);
return respData.get("code_url");
}
}
在这个接口中,首先构建支付请求参数,然后生成签名并添加到参数中,接着将参数转换为XML格式,调用微信统一下单接口,最后解析返回的XML数据,获取支付二维码链接(code_url
)或预支付交易会话标识(prepay_id
)。
六、处理支付回调
支付完成后,微信会向回调地址发送支付结果通知,下面是回调接口的实现:
@PostMapping("/notify")
public String payNotify(HttpServletRequest request) throws Exception {
// 读取回调数据
String xmlData = IOUtils.toString(request.getInputStream(), "UTF-8");
Map<String, String> notifyData = parseXml(xmlData);
// 验证签名
String sign = notifyData.get("sign");
String localSign = WxPayUtil.generateSign(notifyData, wxPayConfig.getApiKey());
if (!sign.equals(localSign)) {
return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
}
// 处理业务逻辑(如更新订单状态)
String orderNo = notifyData.get("out_trade_no");
orderService.updateOrderPaid(orderNo);
// 返回成功响应
return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
}
在这个回调接口中,首先读取微信发送的回调数据,然后验证签名的正确性。如果签名验证通过,就可以根据业务需求处理订单状态更新等逻辑,最后返回成功响应给微信。
七、其他支付相关功能
(一)订单查询
要查询订单状态,可以调用https://api.mch.weixin.qq.com/pay/orderquery
接口,在请求时传递订单号等必要参数,就能获取订单的当前状态信息。
(二)退款操作
退款功能需要调用https://api.mch.weixin.qq.com/secapi/pay/refund
接口,并且在调用时需要使用商户证书(.p12
文件),以确保退款操作的安全性。
八、对接过程中的注意事项
(一)金额单位
微信支付的金额单位是分,在设置订单金额时,要注意将以元为单位的金额转换为分。例如,1元在微信支付中应表示为100分。
(二)超时处理
在与微信支付服务器交互过程中,可能会遇到网络问题导致请求超时。因此,需要设置合理的超时时间,并建立重试机制,以确保支付流程的稳定性。
(三)幂等性处理
支付回调可能会因为网络等原因出现重复通知的情况,在处理回调时要确保业务操作的幂等性,避免重复处理导致数据不一致等问题。
(四)日志记录
在整个支付对接过程中,记录关键步骤的日志非常重要。这些日志可以帮助快速定位和排查问题,提高开发和调试效率。
(五)沙箱测试
在正式上线前,一定要使用微信支付沙箱环境进行测试。通过沙箱测试,可以在模拟的真实环境中验证支付功能是否正常,减少上线后的风险。
通过以上步骤,就可以在Spring Boot项目中完成微信支付的对接。不过,具体实现过程中可能需要根据微信支付官方文档,对参数和接口调用方式进行适当调整。