Java接入微信支付保姆式教程(一):支付流程、商户号与环境准备

Java 接入微信支付保姆式教程(一):支付流程、商户号与环境准备

前言

微信支付几乎是国内 Java 开发人员绕不开的一项能力。

不管做的是:

text 复制代码
商城
外卖
预约系统
SaaS
会员系统
医院系统
门店系统
小程序
公众号

只要系统存在在线收款,就很有可能需要接入微信支付。

但是对于第一次接微信支付的开发者来说,真正让人头疼的往往不是 Java 代码。

而是一上来就会看到一大堆名词:

text 复制代码
AppID
mchid
商户号
微信商户平台
微信公众平台
微信开放平台
APIv3
APIv3 密钥
商户 API 证书
商户私钥
证书序列号
微信支付公钥
微信支付公钥 ID
openid
prepay_id

第一次看到这些东西的时候,很容易产生一个感觉:

我只是想让用户付个钱,为什么要准备这么多东西?

实际上,只要把微信支付整个体系拆开来看,它并没有想象中那么复杂。

整个微信支付接入,本质上可以理解成三件事情:

text 复制代码
第一步
证明"我是哪个商户"

第二步
证明"用户正在我的哪个微信应用中支付"

第三步
由我的服务器调用微信支付 API 创建支付订单

其中:

text 复制代码
商户号 mchid

解决的是:

谁在收钱?

而:

text 复制代码
AppID

解决的是:

用户在哪个微信应用里完成支付?

最后:

text 复制代码
商户 API 私钥
+
微信支付公钥
+
APIv3 密钥

解决的则是:

微信支付服务器和我们的服务器之间,如何安全地通信?

所以本系列不会一上来就复制一堆微信支付 SDK 代码。

第一篇我们先把整个微信支付体系真正搞清楚。

本文主要依据当前微信支付官方 API v3 商户文档整理,包括:

  • 微信支付小程序支付产品文档;
  • JSAPI 支付产品文档;
  • 微信支付开发接入准备文档;
  • API v3 开发必要参数说明;
  • 商户号与 AppID 绑定说明;
  • APIv3 密钥说明;
  • 商户 API 证书说明;
  • 微信支付公钥相关说明。

本文以:

text 复制代码
普通商户
+
微信小程序
+
Spring Boot
+
微信支付 API v3

作为主要教程场景。

服务商模式、特约商户模式暂时不在本系列第一阶段讨论范围内。


一、我们最终到底要实现什么?

在正式了解微信支付之前,先把最终目标搞清楚。

假设我们现在有一个微信小程序。

用户在小程序中购买一个商品:

text 复制代码
商品:测试商品
金额:0.01 元

点击:

text 复制代码
立即支付

然后弹出微信支付收银台。

用户确认金额以后:

text 复制代码
验证指纹 / 密码
        ↓
支付成功
        ↓
返回我们的小程序

最终服务器中的订单状态从:

text 复制代码
待支付

变成:

text 复制代码
已支付

看起来非常简单。

但从技术角度来看,这个过程实际上至少涉及三个系统:

text 复制代码
微信小程序
Java 后端
微信支付服务器

它们之间的大概关系是:

text 复制代码
┌──────────────────────────┐
│        微信小程序          │
│                          │
│ 用户点击"立即支付"         │
└────────────┬─────────────┘
             │
             │ ① 创建支付请求
             ▼
┌──────────────────────────┐
│       Java 后端服务        │
│                          │
│ 创建业务订单               │
│ 调用微信支付 API v3        │
└────────────┬─────────────┘
             │
             │ ② JSAPI/小程序下单
             ▼
┌──────────────────────────┐
│       微信支付服务器        │
│                          │
│ 创建预支付交易              │
└────────────┬─────────────┘
             │
             │ ③ 返回 prepay_id
             ▼
┌──────────────────────────┐
│       Java 后端服务        │
│                          │
│ 生成小程序调起支付参数       │
└────────────┬─────────────┘
             │
             │ ④ 返回支付参数
             ▼
┌──────────────────────────┐
│        微信小程序          │
│                          │
│ wx.requestPayment()      │
└────────────┬─────────────┘
             │
             │ ⑤ 拉起微信收银台
             ▼
┌──────────────────────────┐
│       微信支付收银台        │
│                          │
│ 用户确认并完成付款          │
└────────────┬─────────────┘
             │
             │ ⑥ 支付成功
             ▼
┌──────────────────────────┐
│       微信支付服务器        │
└────────────┬─────────────┘
             │
             │ ⑦ 支付结果通知
             ▼
┌──────────────────────────┐
│       Java 后端服务        │
│                          │
│ 验签 / 解密 / 校验          │
│ 更新业务订单状态            │
└──────────────────────────┘

这就是我们整个系列最终需要打通的链路。

微信支付官方当前的小程序支付开发指引也是这个思路:

商户先调用 JSAPI/小程序下单接口获得:

text 复制代码
prepay_id

然后小程序通过:

javascript 复制代码
wx.requestPayment()

拉起微信支付收银台。

用户完成或取消支付后返回小程序;对于最终订单状态,商户还需要结合查询订单接口及微信支付发送的支付成功通知进行处理。citeturn165650search13turn165650search0

所以从一开始就要建立一个非常重要的认知:

微信支付不是"小程序调用一个支付 API 就结束了"。

真正的支付系统是:

text 复制代码
前端
+
自己的后端
+
微信支付服务器

三方共同完成。


二、JSAPI 支付和小程序支付到底是什么?

这个地方是很多新手第一次看微信支付文档时最容易混淆的地方。

因为官方文档中经常会出现:

text 复制代码
JSAPI支付

以及:

text 复制代码
小程序支付

而它们下单时又都会看到:

text 复制代码
/v3/pay/transactions/jsapi

所以很容易产生疑问:

小程序支付是不是就是 JSAPI 支付?

严格来说:

不是同一个支付场景,但当前普通商户的小程序支付和 JSAPI 支付共享支付权限以及 JSAPI/小程序下单接口。


2.1 什么是 JSAPI 支付?

根据微信支付官方目前的定义:

JSAPI 支付主要用于用户在微信客户端内部浏览器网页中完成微信支付。

最典型的场景就是:

text 复制代码
微信公众号
        ↓
点击菜单
        ↓
打开 H5 网页
        ↓
选择商品
        ↓
微信内网页发起支付

例如:

text 复制代码
微信
 │
 ▼
公众号文章 / 菜单 / 分享链接
 │
 ▼
微信内置浏览器
 │
 ▼
商户 H5 页面
 │
 ▼
JSAPI 支付

所以传统意义上的:

text 复制代码
公众号支付

基本就是大家经常说的:

text 复制代码
JSAPI 支付

微信支付官方当前对 JSAPI 支付的产品定义也是:为商户提供在微信客户端内部浏览器网页中使用微信支付收款的能力。citeturn165650search1


2.2 什么是小程序支付?

小程序支付就更加直观了。

官方定义是:

商户在自己的微信小程序中,通过微信支付完成收款。

例如:

text 复制代码
微信
 │
 ▼
XX商城小程序
 │
 ▼
商品详情
 │
 ▼
提交订单
 │
 ▼
立即支付
 │
 ▼
微信支付收银台

小程序支付最典型的前端 API 就是:

javascript 复制代码
wx.requestPayment({
    // 支付参数
})

微信支付官方当前明确说明:

text 复制代码
小程序支付
=
在商户自身微信小程序中使用微信支付收款

并且当前准入条件中要求相应的小程序满足支付产品要求。citeturn165650search0


2.3 为什么小程序下单接口里面还有 jsapi?

因为微信支付目前的普通商户 API v3 中:

text 复制代码
JSAPI 支付

和:

text 复制代码
小程序支付

共享一个下单接口:

http 复制代码
POST /v3/pay/transactions/jsapi

这个接口的官方名称就是:

text 复制代码
JSAPI/小程序下单

它负责创建:

text 复制代码
预支付交易

并返回:

text 复制代码
prepay_id

官方文档目前明确写明,该接口适用于:

text 复制代码
JSAPI 支付场景
或
小程序支付场景

并且请求中的 appid 必须与当前使用的 mchid 建立绑定关系。citeturn912615search6

所以:

text 复制代码
JSAPI 支付
         \
          \
           → /v3/pay/transactions/jsapi
          /
         /
小程序支付

后端下单接口可以相同。

但是:

前端调起支付的方法不同。


2.4 两者最大的区别在哪里?

可以简单整理成:

项目 JSAPI 支付 小程序支付
使用环境 微信客户端内部网页 微信小程序
常见场景 公众号/H5 微信小程序
API v3 下单 /v3/pay/transactions/jsapi /v3/pay/transactions/jsapi
下单结果 prepay_id prepay_id
前端调起方式 WeixinJSBridge 等 wx.requestPayment()
AppID 公众号 AppID 小程序 AppID
JSAPI 支付授权目录 需要 小程序场景不需要

微信支付当前"小程序支付开发接入准备"文档特别说明:

JSAPI 支付与小程序支付共享同一个权限以及下单接口,但调起方式不同;JSAPI 需要校验授权目录,小程序场景不需要配置 JSAPI 支付授权目录。citeturn165650search16

这个区别一定要搞清楚。

因为很多旧教程会把:

text 复制代码
JSAPI支付

直接等于:

text 复制代码
小程序支付

实际上并不准确。


三、第一次接微信支付,一共有几个"平台"?

接下来到了微信支付新手最容易混乱的地方。

你很快会遇到:

text 复制代码
微信公众平台
微信开放平台
微信支付商户平台

三个名字看起来非常像的平台。

第一次接微信支付的人很容易产生疑问:

我到底应该登录哪一个?

其实它们负责的是完全不同的东西。

可以先记住一句话:

text 复制代码
公众平台
管理公众号 / 小程序

开放平台
主要管理移动应用等开放能力

商户平台
管理"钱"和微信支付

四、微信公众平台是干什么的?

如果我们开发:

text 复制代码
微信公众号

或者:

text 复制代码
微信小程序

最常接触的就是微信公众平台。

例如小程序的:

text 复制代码
AppID
AppSecret
服务器域名
开发设置
版本管理
微信支付商户号绑定

都和这个应用账号有关。

对于本文的小程序支付场景:

text 复制代码
小程序 AppID

就可以在对应公众平台的小程序开发设置中查看。

微信支付当前官方的 AppID 绑定说明中也明确区分:

  • 服务号/公众号 AppID 可在公众平台查看;
  • 小程序 AppID 可在公众平台开发设置中查看;
  • 移动应用 AppID 则在微信开放平台查看。citeturn165650search2

所以:

text 复制代码
微信公众平台
       │
       ├── 公众号
       │      └── AppID
       │
       └── 小程序
              └── AppID

对于我们这个系列:

text 复制代码
Spring Boot
+
微信小程序支付

重点就是:

text 复制代码
小程序 AppID

五、微信开放平台又是干什么的?

这个名字和:

text 复制代码
微信公众平台

特别容易弄混。

微信开放平台更多会出现在:

text 复制代码
移动应用
网站应用
微信登录
开放能力
账号体系

等场景。

例如你自己开发了一个:

text 复制代码
Android App

或者:

text 复制代码
iOS App

想接微信支付,那么对应的移动应用 AppID 就属于微信开放平台体系。

可以简单理解:

text 复制代码
小程序
公众号
    ↓
微信公众平台


Android / iOS App
    ↓
微信开放平台

注意:

这里说的是便于新手理解的主要使用场景,并不是在定义两个平台的全部能力。

对本系列来说,我们做的是:

text 复制代码
微信小程序支付

因此主要操作:

text 复制代码
微信公众平台
+
微信支付商户平台

微信开放平台不是我们当前最核心的后台。


六、微信支付商户平台是干什么的?

如果说:

text 复制代码
微信公众平台

管理的是:

我的微信应用是谁?

那么:

text 复制代码
微信支付商户平台

管理的就是:

谁在收钱?

这里最重要的身份就是:

text 复制代码
商户号

也就是:

text 复制代码
mchid

后面很多配置都在商户平台完成,例如:

text 复制代码
查看商户号
开通支付产品
绑定 AppID
配置 APIv3 密钥
申请商户 API 证书
管理微信支付公钥
查看交易
查看账单
退款
资金管理

因此可以把三个体系画成:

text 复制代码
                 微信生态
                    │
       ┌────────────┼────────────┐
       │            │            │
       ▼            ▼            ▼

   微信公众平台    微信开放平台    微信支付商户平台
       │            │            │
       │            │            │
   公众号/小程序    移动应用等       微信支付
       │            │            │
      AppID        AppID         mchid
       │            │            │
       └────────────┼────────────┘
                    │
                    ▼
                支付业务

七、AppID 到底是什么?

终于到了第一个最关键的参数:

text 复制代码
AppID

AppID 可以理解成:

一个微信应用的唯一身份标识。

例如我有一个商城小程序。

它可能拥有:

text 复制代码
AppID = wx1234567890abcdef

这代表:

text 复制代码
这是哪个微信小程序

如果我还有一个公众号:

text 复制代码
AppID = wxabcdef1234567890

这是另外一个独立的微信应用。

所以:

text 复制代码
小程序 AppID
≠
公众号 AppID
≠
移动应用 AppID

它们不能因为都属于同一家企业,就认为是同一个 AppID。

微信支付官方"开发必要参数说明"目前将 appid 定义为商户在微信开放平台或公众平台上的账号开发识别码,并且强调:

text 复制代码
appid 必须与 mchid 建立绑定关系

之后才能用于对应支付场景。citeturn165650search11


八、商户号 mchid 又是什么?

第二个核心参数:

text 复制代码
mchid

英文通常理解成:

text 复制代码
Merchant ID

也就是:

text 复制代码
商户号

它是微信支付为商户分配的唯一身份标识。

假设:

text 复制代码
某某科技有限公司

注册并开通微信支付以后,微信支付会给这个支付商户分配:

text 复制代码
mchid = 190000xxxx

以后 Java 后端调用微信支付 API 时,微信支付就是通过这个商户号识别:

到底是哪一个商户在调用支付接口?

微信支付当前开发必要参数说明明确指出:

text 复制代码
mchid

是商户在微信支付系统中的唯一身份标识,调用接口时需要通过它确认商户身份。citeturn165650search11


8.1 AppID 和 mchid 有什么区别?

这是整篇文章最应该搞明白的问题之一。

一句话:

text 复制代码
AppID
=
哪个微信应用


mchid
=
哪个支付商户

比如:

text 复制代码
小程序:
钧逸商城

AppID:
wx123456

这个小程序背后的收款公司:

text 复制代码
某某科技有限公司

微信支付商户号:

text 复制代码
mchid:
190000001

那么关系就是:

text 复制代码
┌────────────────────────┐
│       微信小程序         │
│                       │
│ AppID = wx123456      │
└───────────┬────────────┘
            │
            │ 授权绑定
            │
            ▼
┌────────────────────────┐
│      微信支付商户         │
│                       │
│ mchid = 190000001     │
└────────────────────────┘

九、为什么 AppID 和商户号必须绑定?

假设:

text 复制代码
AppID = wxAAA

属于:

text 复制代码
小程序 A

而:

text 复制代码
mchid = 100001

属于:

text 复制代码
商户 A

微信支付不能允许任何一个人随便写:

json 复制代码
{
    "appid": "wxAAA",
    "mchid": "100001"
}

就让它们一起收款。

否则我完全可以:

text 复制代码
拿别人的小程序 AppID
+
绑定我自己的商户号

那整个支付体系就乱了。

所以微信支付要求:

AppID 与 mchid 之间必须建立授权绑定关系。

当前官方的普通商户 AppID 管理文档中,商户需要先从微信支付商户平台发起 AppID 关联申请,然后到相应的平台确认授权。

对于小程序,就是:

text 复制代码
微信支付商户平台
        │
        │ 发起关联
        ▼
小程序 AppID
        │
        ▼
微信公众平台
        │
        │ 确认授权
        ▼
绑定完成

而且官方当前说明,一个普通商户号可以关联多个受支持的 AppID 账号,实际绑定仍需满足对应账号类型、认证状态、主体及风险规则等要求。citeturn165650search2


十、一个商户号是不是只能绑定一个小程序?

不是。

实际企业很可能拥有:

text 复制代码
商城小程序
会员小程序
门店小程序
预约小程序

但收款主体可能都是:

text 复制代码
同一家公司

因此可以出现:

text 复制代码
                mchid
             190000001
                 │
       ┌─────────┼─────────┐
       │         │         │
       ▼         ▼         ▼
     AppID A   AppID B   AppID C
       │         │         │
       ▼         ▼         ▼
    商城小程序   会员小程序   门店小程序

每个应用和商户号之间都需要按照微信支付要求建立对应关系。


十一、openid 又是什么?为什么支付还需要它?

小程序支付过程中还有一个非常重要的参数:

text 复制代码
openid

很多新手容易把:

text 复制代码
AppID

和:

text 复制代码
openid

混起来。

它们完全不是一个东西。

AppID 表示:

text 复制代码
哪个应用

openid 表示:

text 复制代码
当前这个用户
在这个 AppID 下是谁

例如:

text 复制代码
小程序 AppID
wx123456

用户张三在这个小程序中的:

text 复制代码
openid
=
oABCxxxxxxxx

所以关系是:

text 复制代码
                    微信用户
                       │
                       ▼
                某个小程序 AppID
                       │
                       ▼
                     OpenID

微信支付官方的开发必要参数说明也指出:

text 复制代码
openid

是用户在对应公众账号/小程序体系下的身份标识,不同应用下的 OpenID 可能不同。citeturn912615search7

所以调用小程序支付下单接口时,我们后面会看到类似参数:

json 复制代码
{
    "payer": {
        "openid": "oABCxxxxxxxx"
    }
}

也就是说微信支付需要知道:

这笔订单最终是哪个微信用户准备支付。


十二、API v3 是什么?为什么教程都在说 API v3?

如果你搜索比较老的微信支付教程,会看到很多:

text 复制代码
XML
MD5
APIv2

例如:

xml 复制代码
<xml>
    <appid>xxx</appid>
    <mch_id>xxx</mch_id>
</xml>

但是现在新项目接微信支付,应该优先按照:

text 复制代码
微信支付 API v3

进行开发。

API v3 使用:

text 复制代码
HTTP REST
+
JSON
+
非对称签名
+
HTTPS

这样的现代 API 设计。

例如我们后面小程序下单会调用:

http 复制代码
POST /v3/pay/transactions/jsapi

请求:

json 复制代码
{
    "appid": "wx123456",
    "mchid": "190000001",
    "description": "测试商品",
    "out_trade_no": "PAY202609140001",
    "notify_url": "https://example.com/pay/wechat/notify",
    "amount": {
        "total": 1,
        "currency": "CNY"
    },
    "payer": {
        "openid": "oABCxxxx"
    }
}

注意:

text 复制代码
total = 1

不是:

text 复制代码
1 元

而是:

text 复制代码
1 分

这个我们到实际下单篇再详细讲。

微信支付 API v3 官方说明中,当前 API v3 主要使用 REST 风格、JSON 数据交互以及基于非对称密钥的 SHA256-RSA 签名机制,并使用 AES-256-GCM 对需要保护的回调数据进行加密。官方同时推荐开发者使用其提供的 Java/Go 工具库降低签名、验签等接入复杂度。citeturn912615search9


十三、接微信支付到底要准备哪些参数?

到了这里,我们终于可以整理微信支付 Java 开发真正需要的核心东西。

目前普通商户 API v3 场景下,主要需要理解:

参数 含义 主要作用
mchid 微信支付商户号 标识收款商户
appid 小程序/公众号等 AppID 标识支付应用
openid 用户身份 标识当前付款用户
商户 API 私钥 商户自己的私钥 对 API 请求进行签名
商户 API 证书序列号 商户证书编号 标识签名所用证书
APIv3 密钥 商户自己设置的 32 位密钥 解密支付通知等密文
微信支付公钥 微信支付提供 验证微信支付响应/通知签名
微信支付公钥 ID 对应微信支付公钥 确定使用哪把微信支付公钥
notify_url 支付通知地址 微信支付通知自己的服务器

最终 Java 配置可能会变成:

yaml 复制代码
wechat:
  pay:
    app-id: wx1234567890abcdef
    mch-id: 1900000001
    merchant-serial-number: xxxxxxxxx
    private-key-path: classpath:cert/apiclient_key.pem
    api-v3-key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    wechat-pay-public-key-id: PUB_KEY_ID_xxx
    wechat-pay-public-key-path: classpath:cert/wechatpay_public_key.pem
    notify-url: https://api.example.com/pay/wechat/notify

当然,这只是为了让大家提前知道这些参数以后会放在哪里。

第一篇暂时不写具体 Spring Boot 配置。


十四、APIv3 密钥到底是什么?

这个是第一次接微信支付时特别容易理解错的东西。

APIv3 密钥:

text 复制代码
不是 AppSecret
不是商户私钥
不是证书密码
也不是微信支付公钥

它是一串由商户自己设置并保存的:

text 复制代码
32 个字符

的密钥。

根据微信支付当前官方说明,APIv3 密钥主要用于:

text 复制代码
微信支付回调密文解密

以及与平台证书模式相关的解密场景。

官方同时明确提醒:

APIv3 密钥属于敏感信息,设置后应由技术人员安全保存,泄露后需要重新设置。citeturn912615search2

举个例子。

微信支付通知我们的服务器:

http 复制代码
POST /pay/wechat/notify

回调中的核心交易数据并不是直接:

json 复制代码
{
    "trade_state": "SUCCESS"
}

裸着传过来的。

而会涉及加密后的资源数据。

这时候我们就需要:

text 复制代码
APIv3 Key

完成相应解密。

因此可以先记:

text 复制代码
APIv3 Key

主要解决:
微信支付发给我的加密数据
我要怎么解开

十五、商户 API 证书和商户私钥又是什么?

接下来又出现:

text 复制代码
商户 API 证书

以及:

text 复制代码
商户 API 私钥

这也是很多人最容易懵的地方。

你可以暂时理解成一对:

text 复制代码
商户身份凭证

在 API v3 中,我们的 Java 服务器向微信支付发送请求时,需要证明:

这个请求真的是这个商户发出来的,不是别人伪造的。

所以我们的服务器需要使用:

text 复制代码
商户私钥

对请求进行数字签名。

大概是:

text 复制代码
Java 后端
    │
    │ 商户私钥签名
    ▼
支付请求
    │
    ▼
微信支付
    │
    │ 校验签名
    ▼
确认:
确实是该商户发送

商户私钥一定要:

text 复制代码
严格保管

不要:

text 复制代码
上传 GitHub
提交到公开 Git 仓库
放到前端代码
写进小程序
发到群里

因为它属于服务器端的核心安全凭据。

微信支付官方目前说明,API v3 请求需要通过商户侧私钥完成请求签名;商户 API 证书中包含商户号、公司名称、公钥等身份信息。citeturn912615search3turn165650search11


十六、商户 API 证书序列号又是什么?

后面代码里我们还会看到:

text 复制代码
merchantSerialNumber

也就是:

text 复制代码
商户 API 证书序列号

很多新手第一次看到会想:

有私钥还不够吗?怎么又来一个序列号?

因为一个商户可能存在证书更新等情况。

所以微信支付还需要知道:

text 复制代码
你这次签名
到底用的是哪一张商户 API 证书对应的私钥?

于是请求中需要带:

text 复制代码
serial_no

帮助标识对应的商户 API 证书。

可以理解成:

text 复制代码
商户 API 私钥
=
真正负责签名


证书序列号
=
告诉微信:
我用的是哪一套商户证书身份

官方当前的开发必要参数说明也明确将:

text 复制代码
商户 API 证书序列号

列为 API v3 请求签名认证的重要参数。citeturn912615search7


十七、微信支付公钥和平台证书到底是什么?

这里需要特别说明。

因为网上大量旧教程都会告诉你:

text 复制代码
必须下载微信支付平台证书

但是按照当前微信支付官方 API v3 文档,已经不能只这么讲了。

目前验签主要可以理解成两种模式:

text 复制代码
微信支付公钥模式

或者

微信支付平台证书模式

而当前官方文档明确把:

text 复制代码
微信支付公钥

标记为推荐使用的方式。

微信支付官方当前的"开发必要参数说明"指出:

text 复制代码
微信支付公钥

可用于:

  1. 验证 API v3 返回内容签名;
  2. 验证相关微信支付消息来源;
  3. 在涉及敏感参数时用于加密。

同时还有一个:

text 复制代码
微信支付公钥 ID

用于标识具体使用的微信支付公钥。

对于平台证书,当前官方文档则建议新接入场景优先考虑微信支付公钥模式,因为管理更简单。citeturn912615search7turn912615search9

因此本教程后续如果没有特殊需求,会优先按照:

text 复制代码
微信支付公钥模式

来讲。


十八、这些密钥和证书到底是什么关系?

现在把刚刚这些东西放到一张图里。

这是整篇文章最重要的一张关系图。

text 复制代码
                    我们的 Java 后端
                          │
                          │
                 商户 API 私钥
                          │
                       请求签名
                          │
                          ▼
                    微信支付 API
                          │
                          │
                 微信支付响应/通知
                          │
                          ▼
                    我们的 Java 后端
                     │            │
                     │            │
              微信支付公钥      APIv3 Key
                     │            │
                   验签         解密密文
                     │            │
                     └─────┬──────┘
                           ▼
                       得到可信数据

简单记忆:

text 复制代码
商户私钥
=
我证明我是我


微信支付公钥
=
我验证微信确实是微信


APIv3 Key
=
我解开微信支付发来的加密内容

这一句话建议新手直接记住。


十九、AppSecret 和 APIv3 Key 是一个东西吗?

不是。

这两个东西特别容易被新手搞混。

AppSecret

属于:

text 复制代码
微信小程序 / 公众号

主要用于应用身份相关接口。

例如:

text 复制代码
登录
获取 access_token
服务端调用微信开放接口

APIv3 Key

属于:

text 复制代码
微信支付商户

主要用于:

text 复制代码
微信支付 API v3

中的加密数据解密等支付安全场景。

所以:

text 复制代码
AppSecret
        ↓
微信应用体系


APIv3 Key
        ↓
微信支付体系

完全是两套东西。

千万不要混淆。


二十、正式开发前,我们到底需要准备什么?

如果你要跟着本系列完成:

text 复制代码
Spring Boot
+
微信小程序
+
微信支付 API v3

那么开始写代码之前,至少应该准备好以下内容。

项目 是否必须 说明
微信小程序 是 支付载体
小程序 AppID 是 标识小程序
微信支付商户号 是 收款商户
小程序与商户号绑定 是 建立支付授权关系
对应支付产品权限 是 小程序支付需要相应权限
商户 API 私钥 是 API v3 请求签名
商户 API 证书序列号 是 标识商户证书
APIv3 密钥 是 回调等密文解密
微信支付公钥 推荐方案需要 API v3 验签
微信支付公钥 ID 推荐方案需要 标识公钥
Java 后端 是 调用支付 API
HTTPS 公网接口 回调阶段需要 接收微信支付通知

二十一、小程序支付权限怎么准备?

当前官方的小程序支付接入流程,大致可以整理为:

text 复制代码
注册微信小程序
       ↓
完成所需认证
       ↓
申请 / 准备微信支付商户号
       ↓
开通对应支付权限
       ↓
商户号发起 AppID 绑定
       ↓
小程序侧确认绑定
       ↓
准备支付开发参数
       ↓
开始 API v3 开发

微信支付当前的小程序支付接入准备文档明确说明:

  • 需要准备对应的公众平台小程序账号;
  • 按产品要求完成账号认证;
  • 已有商户号时,可从商户侧申请对应支付权限并发起 AppID 授权绑定;
  • 小程序支付与 JSAPI 支付共享权限和下单接口,但小程序支付不需要配置 JSAPI 支付授权目录。citeturn165650search16

二十二、如果还没有商户号怎么办?

那么首先需要申请微信支付商户号。

这里建议新手不要急着进入代码。

因为:

text 复制代码
没有 mchid

后面绝大多数支付 API 根本没法正常开发。

商户号本质上代表:

text 复制代码
真正接受微信支付结算的经营主体

所以申请过程中通常涉及:

text 复制代码
主体信息
经营信息
联系人
结算账户
相关资质

等内容。

具体支持的主体类型和产品权限会随微信支付规则调整,所以申请时应直接以微信支付商户平台最新页面和官方文档为准。


二十三、正式开发前建议建立一个配置清单

我个人比较推荐,在第一次接微信支付的时候自己整理一张表。

例如:

text 复制代码
================================
微信支付开发参数
================================

小程序 AppID:
wx________________

商户号 mchid:
__________________

APIv3 Key:
********************************

商户 API 证书序列号:
__________________

商户私钥:
apiclient_key.pem

微信支付公钥 ID:
__________________

微信支付公钥:
wechatpay_public_key.pem

支付回调地址:
https://api.example.com/pay/wechat/notify

================================

当然:

text 复制代码
私钥
APIv3 Key
AppSecret

这种敏感信息不能真正放进博客、GitHub 或公开文档。

这里只是告诉大家:

在开始写 Java 代码前,先确认这些参数到底有没有准备完整。

否则写代码的时候会不断遇到:

text 复制代码
这个参数是什么?
去哪里找?
为什么为空?
为什么签名失败?

最后你甚至不知道到底是:

text 复制代码
代码有问题

还是:

text 复制代码
商户平台配置根本没完成

二十四、第一篇最重要的:把整个账号关系真正记住

到这里,我们把前面的东西整合成一张完整关系图。

text 复制代码
                         微信生态
                            │
             ┌──────────────┴──────────────┐
             │                             │
             ▼                             ▼
         微信公众平台                  微信支付商户平台
             │                             │
             │                             │
         微信小程序                      微信商户
             │                             │
             ▼                             ▼
           AppID                         mchid
             │                             │
             └──────────授权绑定────────────┘
                           │
                           ▼
                     可以进行微信支付
                           │
                           ▼
                     Java 后端服务
                           │
           ┌───────────────┼───────────────┐
           │               │               │
           ▼               ▼               ▼
       商户私钥         APIv3 Key       微信支付公钥
           │               │               │
           ▼               ▼               ▼
         请求签名         数据解密          响应验签
           │               │               │
           └───────────────┼───────────────┘
                           │
                           ▼
                      微信支付 API v3
                           │
                           ▼
                /v3/pay/transactions/jsapi
                           │
                           ▼
                       prepay_id
                           │
                           ▼
                       微信小程序
                           │
                           ▼
                   wx.requestPayment()
                           │
                           ▼
                      微信支付收银台

如果这一张图能够完全看懂:

那么微信支付最容易让新手迷糊的基础概念,其实已经解决了一半。


二十五、再看一次完整支付流程

最后,在进入下一篇代码开发之前,再把整个支付流程完整过一遍。

假设用户在小程序购买:

text 复制代码
商品:测试商品
金额:0.01 元

第一步:用户提交订单

text 复制代码
小程序
   ↓
POST /api/pay/wechat/create

第二步:Java 创建自己的业务订单

数据库:

text 复制代码
order_no = PAY202609140001

amount = 0.01

status = WAIT_PAY

第三步:Java 调微信支付

Java 后端调用:

http 复制代码
POST /v3/pay/transactions/jsapi

携带:

text 复制代码
appid
mchid
description
out_trade_no
notify_url
amount
openid

第四步:微信支付返回 prepay_id

例如:

json 复制代码
{
    "prepay_id": "wx201410272009395522657a690389285100"
}

prepay_id 可以理解为:

微信支付为这次支付创建的预支付交易会话标识。


第五步:Java 生成小程序支付参数

后端根据:

text 复制代码
AppID
timeStamp
nonceStr
package

等信息完成调起支付所需要的签名。

然后返回给小程序。


第六步:小程序调用 wx.requestPayment()

javascript 复制代码
wx.requestPayment({
    timeStamp,
    nonceStr,
    package,
    signType,
    paySign
})

然后:

text 复制代码
微信支付收银台

出现。


第七步:用户完成支付

用户:

text 复制代码
确认订单
   ↓
验证密码 / 指纹
   ↓
支付成功

第八步:微信支付通知 Java 后端

微信支付服务器请求:

text 复制代码
notify_url

例如:

http 复制代码
POST https://api.example.com/pay/wechat/notify

Java 后端:

text 复制代码
验签
 ↓
解密
 ↓
校验商户号
 ↓
校验金额
 ↓
幂等判断
 ↓
更新订单

最终:

text 复制代码
WAIT_PAY
   ↓
SUCCESS

第九步:必要时主动查单

还有一个非常重要的原则:

不要单纯依赖小程序 wx.requestPayment() 的 success 回调判断服务器中的业务订单已经支付成功。

按照微信支付当前开发指引,用户返回商户页面后,商户应结合微信支付订单查询结果处理业务;支付成功时微信支付也会向商户服务器发送支付成功通知。citeturn165650search10turn165650search13

这部分我们会在后面的:

text 复制代码
支付回调
+
订单查询

中详细讲。


二十六、几个新手特别容易搞错的问题

最后把第一篇最容易混淆的内容集中总结一下。

1. AppID 是商户号吗?

不是。

text 复制代码
AppID
=
微信应用身份


mchid
=
微信支付商户身份

2. APIv3 Key 是 AppSecret 吗?

不是。

text 复制代码
AppSecret
=
微信应用开发凭据


APIv3 Key
=
微信支付 API v3 加密相关密钥

3. 商户私钥是 APIv3 Key 吗?

不是。

text 复制代码
商户私钥
=
数字签名


APIv3 Key
=
相关支付密文解密

4. 小程序支付等于 JSAPI 支付吗?

不能直接画等号。

当前:

text 复制代码
共享支付权限
共享 JSAPI/小程序下单接口

但是:

text 复制代码
使用场景
前端调起方式
部分接入配置

不同。


5. 小程序 AppID 能不能随便配一个商户号?

不能。

需要:

text 复制代码
AppID
↕
mchid

建立授权绑定关系。


6. Java 私钥可以放进小程序吗?

绝对不可以。

以下内容都应该只保存在安全的服务器环境:

text 复制代码
商户私钥
APIv3 Key
AppSecret

7. wx.requestPayment success 就代表订单可以直接改成已支付吗?

不要这么设计。

客户端回调用于:

text 复制代码
用户体验

最终可信业务状态应该结合:

text 复制代码
微信支付通知
+
微信支付订单查询

进行确认。


二十七、本文总结

这一篇我们还没有开始真正写 Java 微信支付代码。

但是已经把微信支付中最容易把新手绕晕的一整套关系梳理完成了。

现在应该能够明确:

text 复制代码
微信小程序
     ↓
   AppID

解决:

用户在哪个微信应用中支付?

而:

text 复制代码
微信支付商户
     ↓
    mchid

解决:

到底是谁在收款?

两者:

text 复制代码
AppID
  │
授权绑定
  │
mchid

建立支付关系。

然后 Java 服务器需要:

text 复制代码
商户私钥

完成:

text 复制代码
API 请求签名

使用:

text 复制代码
微信支付公钥

完成:

text 复制代码
微信支付响应/通知验签

使用:

text 复制代码
APIv3 Key

完成:

text 复制代码
相关加密数据解密

最后整个支付流程就是:

text 复制代码
用户
 ↓
微信小程序
 ↓
Java 后端
 ↓
创建业务订单
 ↓
微信支付 API v3
 ↓
prepay_id
 ↓
Java 生成支付参数
 ↓
wx.requestPayment()
 ↓
微信支付收银台
 ↓
用户支付
 ↓
微信支付通知 Java 后端
 ↓
验签 + 解密 + 幂等
 ↓
更新业务订单

如果把这一条链路真正理解清楚,那么接下来真正开始写代码时,就不会再看到:

text 复制代码
appid
mchid
serialNo
privateKey
apiV3Key
wechatPayPublicKey
openid
prepay_id

以后完全不知道它们分别是干什么的。


下一篇

下一篇正式进入 Java 项目实战:

《Java 接入微信支付保姆式教程(二):Spring Boot 接入微信支付并完成统一下单》

下一篇将基于一个已经存在的 Spring Boot 项目进行演示,不会浪费大量篇幅从零创建 Java 工程。

主要完成:

text 复制代码
引入微信支付 Java SDK
        ↓
配置 mchid / AppID
        ↓
加载商户私钥
        ↓
配置微信支付公钥
        ↓
初始化微信支付 Client
        ↓
设计支付订单
        ↓
创建微信支付业务订单
        ↓
调用 JSAPI/小程序下单
        ↓
获得 prepay_id

也就是从下一篇开始:

我们真正开始写代码,完成第一笔微信支付订单的后端下单。


参考资料

本文主要参考微信支付当前官方文档整理,建议开发过程中始终以微信支付最新官方文档为最终依据。

主要参考:

  1. 微信支付商户文档中心:《小程序支付 - 产品介绍》
  2. 微信支付商户文档中心:《小程序支付 - 开发接入准备》
  3. 微信支付商户文档中心:《小程序支付 - 开发指引》
  4. 微信支付商户文档中心:《JSAPI支付 - 产品介绍》
  5. 微信支付商户文档中心:《JSAPI支付 - 开发接入准备》
  6. 微信支付商户文档中心:《JSAPI/小程序下单》
  7. 微信支付商户文档中心:《开发必要参数说明》
  8. 微信支付商户文档中心:《管理商户号绑定的 APPID 账号》
  9. 微信支付商户文档中心:《配置 APIv3 密钥》
  10. 微信支付商户文档中心:《申请商户 API 证书》
  11. 微信支付官方:《APIv3 概述》

需要特别注意:

微信支付产品能力、平台菜单、证书方案和接入要求可能持续调整。本文依据 2026 年 9 月可查询到的微信支付官方 API v3 文档整理,实际开发时请再次核对官方最新要求。

相关推荐
Ai-_Man3 小时前
您您这可以把Grok的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。AI导出鸭
javascript·人工智能·ai·小程序·电脑
光影少年5 小时前
Taro 是如何解析入口配置 app.config.ts 和页面配置的?
微信小程序·小程序·typescript·reactjs·百度小程序·taro
DS小龙哥10 小时前
从呼吸心率到离床报警:60G雷达睡眠仪全栈开发实录(硬件+MQTT+小程序)DIY一台全功能睡眠监护仪
stm32·单片机·嵌入式硬件·物联网·小程序·智能家居
扶风ff13 小时前
练题簿在线免费刷题:刷题、背题、错题复习,一个小程序安排日常备考
学习·小程序
扶风ff13 小时前
练题簿在线免费刷题:共享题库、学习任务、在线考试,岗位培训更方便
学习·小程序
愚公搬代码14 小时前
【愚公系列】《微信小程序项目实战(AI编程+视频图解)》014-莫凡商城小程序项目视图容器组件的应用
微信小程序·小程序·ai编程
程xu袁1 天前
只有一段副歌,AI写歌选小程序、Suno还是海绵音乐?
小程序·suno·ai音乐·ai音乐工具·ai生成音乐·ai写歌工具
专业程序开发源2 天前
springboot生命故事书制作小程序65290-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·mysql·小程序·课程设计
QQ_21696290962 天前
基于微信小程序的智能膳食分析系统
java·大数据·spring boot·微信小程序·小程序·旅游
扶风ff2 天前
求职笔试资料太散?用练题簿在线刷题,按岗位整理练习清单
前端·学习·小程序