1.官网文档地址
https://pay.weixin.qq.com/doc/v3/merchant/4012791856
2.支付产品
JSAPI支付:提供商户在微信客户端内部浏览器网页中使用和小程序使用
APP支付:提供商户在自己的APP中使用
H5支付:提供商户在手机浏览器网页(非微信客户端内部浏览器)中使用
Native支付:提供商户在PC端网页浏览器中使用
小程序支付:后端调用接口和JSAPI共用,前端使用方式不同
付款码支付:超市收银出示付款码场景
合单支付:提供将多个商户的订单合并为一个订单进行支付的能力
刷脸支付
医保支付
3.时序图
例:预支付到支付成功回调 全过程。
例:退款申请 回调全流程
例:提现转账 全流程
4.具体使用
依赖:
<dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>${wechatpay-java.version}</version> </dependency>wx-pay: #回调使用 - 异步回调地址 notifyURI: https://yyjkb-*****xue.net/mrjkapi/ #商户密钥文件 keyPath: /wx/ap****nt_key.pem #微信应用ID #小程序/公众号 在微信公众平台获取 #App在:微信开发平台获取 openAppId: wxb32****71c5d #商户号 mchId: wxb3*****c5d #商户Api公钥证书序列号 SerialNo: 2B0DA37*******************2025C #回调使用 - 对称密钥 用来解密回调通知里的敏感数据 apiV3Key: oX2sS5E************D6dPpackage net.quankeyixue.config; import com.wechat.pay.java.core.RSAAutoCertificateConfig; import com.wechat.pay.java.service.payments.app.AppService; import com.wechat.pay.java.service.payments.app.AppServiceExtension; import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension; public class WeChatConstants { //回调域名 public static final String NOTIFY_DOMAIN; //开放appid public static final String OPEN_APP_ID; //商户号 public static final String MCH_ID; public static final String WX_PAY_NOTIFY; public static final String WECHAT_PAY_KEY_PATH; public static final String SERIAL_NO; public static final String API_V3_KEY; public static final String WX_REFUND_NOTIFY; public static final RSAAutoCertificateConfig rsaConfig; public static final JsapiServiceExtension jsapiService; public static final AppServiceExtension appServiceExtension; public static final AppService appService; public static final String TRANSFER_NOTIFY_URL; static { OPEN_APP_ID = YamlConfigurerUtil.getStrYmlVal("wx-pay.openAppId"); MCH_ID = YamlConfigurerUtil.getStrYmlVal("wx-pay.mchId"); NOTIFY_DOMAIN = YamlConfigurerUtil.getStrYmlVal("wx-pay.notifyURI"); WECHAT_PAY_KEY_PATH = YamlConfigurerUtil.getStrYmlVal("wx-pay.keyPath"); SERIAL_NO = YamlConfigurerUtil.getStrYmlVal("wx-pay.serialNo"); API_V3_KEY = YamlConfigurerUtil.getStrYmlVal("wx-pay.apiV3Key"); WX_PAY_NOTIFY = NOTIFY_DOMAIN + "/api/v2/wxPay/notify"; WX_REFUND_NOTIFY = NOTIFY_DOMAIN + "/api/v2/wxRefund/notify"; TRANSFER_NOTIFY_URL = NOTIFY_DOMAIN + "/api/wxTransfer/notify"; rsaConfig = new RSAAutoCertificateConfig.Builder() .merchantId(MCH_ID) .privateKeyFromPath(WECHAT_PAY_KEY_PATH) .merchantSerialNumber(SERIAL_NO) .apiV3Key(API_V3_KEY) .build(); jsapiService = new JsapiServiceExtension.Builder().config(rsaConfig).build(); appServiceExtension = new AppServiceExtension.Builder().config(rsaConfig).build(); appService = new AppService.Builder().config(WeChatConstants.rsaConfig).build(); } }例:以JSAPI 预支付 和 微信JSAPI 回调为例
package net.quankeyixue.controller; import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse; import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import net.quankeyixue.domain.response.BillResponse; import net.quankeyixue.domain.response.CallbackResponse; import net.quankeyixue.domain.response.CloseOrderResponse; import net.quankeyixue.domain.response.OrderQueryResponse; import net.quankeyixue.domain.response.PayResponse; import net.quankeyixue.domain.response.RefundQueryResponse; import net.quankeyixue.domain.response.RefundResponse; import net.quankeyixue.service.WechatPayService; import org.springframework.web.bind.annotation.*; /** * 微信支付控制器 * @author qinyu * @since 2026/4/28 10:55 */ @RestController @RequestMapping("/wechat_pay") public class WechatPayController { private final WechatPayService wechatPayService; public WechatPayController(WechatPayService wechatPayService) { this.wechatPayService = wechatPayService; } /** * JSAPI支付下单 */ @PostMapping("/jsapi_pay") public com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse jsapiPay() { return wechatPayService.jsapiPay(); } @PostMapping("/jsapi/callback") public void jsapiPayCallback(HttpServletRequest request, HttpServletResponse response) { wechatPayService.JsapiPayCallback(request,response); } }package net.quankeyixue.service; import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import net.quankeyixue.domain.response.BillResponse; import net.quankeyixue.domain.response.CallbackResponse; import net.quankeyixue.domain.response.CloseOrderResponse; import net.quankeyixue.domain.response.OrderQueryResponse; import net.quankeyixue.domain.response.PayResponse; import net.quankeyixue.domain.response.RefundQueryResponse; import net.quankeyixue.domain.response.RefundResponse; /** * 微信支付服务接口 * @author qinyu * @since 2026/4/28 10:56 */ public interface WechatPayService { /** * JSAPI支付下单 */ com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse jsapiPay(); void JsapiPayCallback(HttpServletRequest request, HttpServletResponse response); }package net.quankeyixue.service.impl; import com.alibaba.fastjson.JSON; import com.wechat.pay.java.core.http.Constant; import com.wechat.pay.java.core.notification.NotificationParser; import com.wechat.pay.java.core.notification.RequestParam; import com.wechat.pay.java.service.partnerpayments.app.model.Transaction; import com.wechat.pay.java.service.payments.app.AppService; import com.wechat.pay.java.service.payments.app.AppServiceExtension; import com.wechat.pay.java.service.payments.h5.H5Service; import com.wechat.pay.java.service.payments.h5.model.H5Info; import com.wechat.pay.java.service.payments.h5.model.SceneInfo; import com.wechat.pay.java.service.payments.h5.model.StoreInfo; import com.wechat.pay.java.service.payments.jsapi.JsapiService; import com.wechat.pay.java.service.payments.jsapi.model.CloseOrderRequest; import com.wechat.pay.java.service.payments.jsapi.model.Payer; import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse; 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.NativePayService; import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import net.quankeyixue.config.WeChatConstants; import net.quankeyixue.domain.response.*; import net.quankeyixue.service.WechatPayService; import org.springframework.stereotype.Service; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.UUID; /** * 微信支付服务实现类 * @author qinyu * @since 2026/4/28 10:56 */ @Service @Slf4j public class WechatPayServiceImpl implements WechatPayService { @Override public com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse jsapiPay() { String spuName = "大容量水杯"; String orderNo = "dasdv236724"+"prepayLog本地表ID"; JsapiService build = new JsapiService.Builder().config(WeChatConstants.rsaConfig).build(); com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest(); prepayRequest.setAppid(WeChatConstants.OPEN_APP_ID); prepayRequest.setMchid(WeChatConstants.MCH_ID); prepayRequest.setDescription("描述"); prepayRequest.setOutTradeNo(orderNo); prepayRequest.setTimeExpire("2026-06-08T10:34:56+08:00"); prepayRequest.setNotifyUrl("/wechat_pay/jsapi/callback"); com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount(); amount.setTotal(100); amount.setCurrency("CNY"); prepayRequest.setAmount(amount); Payer payer = new Payer(); //每个端 内的唯一微信标识 payer.setOpenid("oKEA36xoFqOo89KlHHBkMPbF5t_4"); prepayRequest.setPayer(payer); com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse prepay = build.prepay(prepayRequest); PayResponse payResponse = new PayResponse(); payResponse.setAppId(WeChatConstants.OPEN_APP_ID); //当前时间 秒级时间 String timeStamp = String.valueOf(System.currentTimeMillis() / 1000); payResponse.setTimeStamp(timeStamp); String nonceStr = UUID.randomUUID().toString().replace("-", ""); payResponse.setNonceStr(nonceStr); String packageStr = "prepay_id=wx21201855730335ac86f8c43d1889123400"; payResponse.setPackageStr(packageStr); //签名算法 payResponse.setSignType("RSA"); //防篡改核心签名 PrepayWithRequestPaymentResponse prepayWithRequestPaymentResponse = WeChatConstants.jsapiService.prepayWithRequestPayment(prepayRequest); return prepayWithRequestPaymentResponse; } @Override public void JsapiPayCallback(HttpServletRequest request, HttpServletResponse response) { BufferedReader bufferedReader = null; // 先声明 try { // 1. 读取请求体 StringBuilder stringBuffer = new StringBuilder(); bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream())); String s; while ((s = bufferedReader.readLine()) != null) { stringBuffer.append(s); } // 2. 验签 + 解密 NotificationParser parser = new NotificationParser(WeChatConstants.rsaConfig); RequestParam requestParam = new RequestParam.Builder() .serialNumber(request.getHeader(Constant.WECHAT_PAY_SERIAL)) .nonce(request.getHeader(Constant.WECHAT_PAY_NONCE)) .signature(request.getHeader(Constant.WECHAT_PAY_SIGNATURE)) .timestamp(request.getHeader(Constant.WECHAT_PAY_TIMESTAMP)) .signType(request.getHeader("Wechatpay-Signature-Type")) .body(stringBuffer.toString()) .build(); Transaction parse = parser.parse(requestParam, Transaction.class); // ============== 微信规则:5秒内必须先返回! ============== response.setStatus(200); // 返回200 // ======================================================= // 3. 不是成功直接结束 if (!parse.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) { log.error("微信支付回调失败:{}", JSON.toJSONString(parse)); return; } // 4. 解析参数 AttachDTO attachDTO = JSON.parseObject(parse.getAttach(), AttachDTO.class); String[] orderNoArr = parse.getOutTradeNo().split("_"); //交易号 String outTradeNo = parse.getOutTradeNo(); //交易状态 Transaction.TradeStateEnum tradeState = parse.getTradeState(); //使用解析出来的数据进行 // 1.订单状态变更 // 2.修改预支付记录表 // 3.对商品进行扣减库存,增加销量等 } catch (Exception e) { log.error("微信回调处理失败", e); // 异常返回失败 response.setStatus(500); } finally { // ===================== 关闭流 ===================== try { if (bufferedReader != null) { bufferedReader.close(); } } catch (Exception e) { log.error("关闭流失败", e); } // ================================================= } } }5.可参考的表结构
表格
| 序号 | 表名 | 操作 | 业务时机 |
|---|---|---|---|
| 1 | yy_order | INSERT / UPDATE | 创建订单、支付成功、订单取消 |
| 2 | yy_order_item | INSERT / UPDATE | 创建订单、虚拟商品发货 |
| 3 | yy_sub_order | INSERT | 下单创建 |
| 4 | yy_sku | UPDATE | 扣库存 (下单)、回滚 (取消)、加销量 (支付) |
| 5 | yy_prepay_log | INSERT / UPDATE | 发起预支付、支付完成 |
| 6 | yy_member_points_detail | UPDATE | 冻结、解冻、积分抵扣确认 |
| 7 | yy_order_fee | INSERT | 支付成功生成分佣 |
| 8 | yy_activity_member | INSERT | 活动商品下单报名 |
| 9 | yy_order_status_records | INSERT | 所有订单状态变更留痕 |
| 10 | yy_member_order_stats | UPDATE | 用户订单数据统计 |
历史项目:核心接口清单
表格
| 接口地址 | 请求入参 | 响应出参 |
|---|---|---|
/jsapi/prepay | PayRequestParam | PrePayVO |
/jsapi/rePrepay/{orderNo} | orderNo (路径参数) | PrePayVO |
/notify | 微信原生回调 XML 报文 | 固定返回200 |
历史项目:关键对应关系(你提供的接口 → 流程图步骤)
表格
| 你的接口方法 | 对应流程图步骤 | 业务说明 |
|---|---|---|
jsapiService.prepayWithRequestPayment() | 步骤③、⑲ | 首次 / 重新支付:调用微信统一下单 |
appService.prepay() | 补充步骤 | APP 支付统一下单(同 JSAPI 官方地址) |
jsapiService.closeOrder() | 步骤⑭、⑯ | 主动 / 超时取消:调用微信关闭订单 |
POST /api/v2/wxPay/notify | 步骤⑪ | 微信支付结果异步回调 |