Integrating WeChat Native Pay into a Java Backend for Membership Upgrade
This guide details how to integrate WeChat native payment into a Java backend, covering merchant setup, Spring configuration, QR‑code generation with the official SDK, handling HTTPS callbacks, and implementing front‑end polling using Redis and Bloom filters for reliable membership upgrades.
Introduction
Recently we needed to add a payment function to a website so that users can become members after paying, providing additional features and generating revenue.
WeChat Pay Integration Overview
Clarify Payment Flow
A typical native WeChat Pay membership upgrade includes: user obtains payment info, selects a type and generates a QR code, user scans and pays, WeChat notifies the server, and the server upgrades the user to a member.
Step 1: Prepare Merchant Information
Obtain merchant number (mch-id), AppID, merchant API certificate serial number (mch-serial-no), API v3 key, and merchant private key.
Merchant platform: https://pay.weixin.qq.com/index.php/core/home
Step 2: Write Configuration and Inject Config Class
Place configuration in application.yml:
wechat:
pay-config:
# Authentication type
auth-type: WECHATPAY2-SHA256-RSA2048
# Merchant ID
mch-id: 1···7
# AppID
appid: wx·····a2
# Merchant API certificate serial number
mch-serial-no: 5··················6
# API v3 key
api-v3-key: J··············123
# Notify URL
notify-url: https://······/notify // can ignore for now
# Merchant private key
private-key: MIME····Configuration class:
@Data
@Configuration
@ConfigurationProperties(prefix = "wechat.pay-config")
public class WeChatPayConfig {
private String authType;
private String mchId;
private String mchSerialNo;
private String privateKey;
private String apiV3Key;
private String appId;
private String notifyUrl;
}RSA auto‑certificate bean:
@Configuration
public class BeanConfig {
@Autowired
private WeChatPayConfig weChatPayConfig;
/** Create a singleton RSAAutoCertificateConfig for WeChat API */
@Bean
public RSAAutoCertificateConfig rsaAutoCertificateConfig() {
return new RSAAutoCertificateConfig.Builder()
.merchantId(weChatPayConfig.getMchId())
.privateKey(weChatPayConfig.getPrivateKey())
.merchantSerialNumber(weChatPayConfig.getMchSerialNo())
.apiV3Key(weChatPayConfig.getApiV3Key())
.build();
}
}Inject the config where needed:
@Autowired
private WeChatPayConfig weChatPayConfig;Step 3: Generate QR Code for Native Pay
Official API docs: https://pay.weixin.qq.com/docs/merchant/sdk-tools/sdk-tool.html
Java SDK repository: https://github.com/wechatpay-apiv3/wechatpay-java
Sample code to create a pre‑pay order and obtain the QR code URL:
package com.wechat.pay.java.service;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
/** Native payment example */
public class QuickStart {
@Autowired
private WeChatPayConfig weChatPayConfig;
@Autowired
private RSAAutoCertificateConfig certificateConfig;
public static void main(String[] args) {
// Build service
NativePayService service = new NativePayService.Builder().config(certificateConfig).build();
// Set request parameters
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(100);
request.setAmount(amount);
request.setAppid("wxa9d9651ae******");
request.setMchid("190000****");
request.setDescription("测试商品标题");
request.setNotifyUrl("https://notify_url");
request.setOutTradeNo("out_trade_no_001");
// Call API
PrepayResponse response = service.prepay(request);
// Print QR code URL
System.out.println(response.getCodeUrl());
}
}Step 4: Handle Payment Notification
WeChat posts the payment result to the notify‑url you configured. Example controller:
@PostMapping("/notify")
public Map
getNativeNotify(HttpServletRequest request) {
String resultCode = payService.solveNotify(request);
Map
resultMap = new HashMap<>();
resultMap.put("code", resultCode);
// Respond to WeChat to stop further callbacks
return resultMap;
}The callback URL must be HTTPS and publicly reachable.
Step 5: Front‑end Polling for Result
Two approaches exist: polling or server push (WebSocket/SSE). We choose polling with Redis cache and a Bloom filter to avoid cache penetration.
Sample polling endpoint:
@GetMapping("/{tradeNo}/result")
public R
getPayResult(@PathVariable String tradeNo) {
// Bloom filter check omitted for brevity
if ("1".equals(redisService.getValue(RedisConstants.ORDER_IS_DEAL + tradeNo))) {
Order order = orderDao.getOrderByTradeNo(tradeNo);
String vipExpiration = redisService.getValue(RedisConstants.USER_VIP + order.getUid());
redisService.deleteValue(RedisConstants.ORDER_IS_DEAL + tradeNo);
return R.success(vipExpiration, "支付已成功, 本用户vip截至");
}
return R.error(ResultCode.FAILED, "订单未完成或不存在");
}During local development, expose the server with a tool like ngrok so that WeChat can reach the HTTPS callback endpoint.
Conclusion
The article walks through the complete backend implementation of WeChat native payment, from merchant configuration, SDK usage, QR code generation, notification handling, to front‑end result polling, and mentions practical tips such as using ngrok for local testing.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.