Repository navigation
feat(alipay): 支付宝当面付直连插件(对标 #12.2 支付宝侧) - #5
Merged
Merged
Conversation
审计指出支付只有第三方聚合(易支付)一条路,缺「直连官方渠道」。这是支付宝半边: 当面付(`alipay.trade.precreate`)扫码下单 + 异步通知验签 + 关单,商户自有密钥, 不经中间商。 ## 能被验证的部分(在没有商户号的情况下) 密码学与协议全部跑真实实现,没有一处 mock 掉签名: - RSA2(SHA256withRSA)签名/验签、裸 base64 私钥自动补 PEM 头(控制台复制出来就是裸的) - 待签名串按 **ASCII 字节序**排序并排除空值 —— 用 `localeCompare` 会在大小写混排时 与支付宝不一致;保留空值则所有请求都验签失败 - 响应验签取**节点原文**(不是 `JSON.stringify(parsed)`):支付宝签的是响应体里那段 文本,重新序列化会在字段顺序/空格/转义上不一致,症状是「明明签名对却验不过」 - 回调:签名 → app_id 必须匹配 → 只有 `TRADE_SUCCESS`/`TRADE_FINISHED` 才结算 - 金额:分 ↔ 元字符串,回调用整数换算(浮点加法会把 0.1+0.2 变成 0.30000000000000004) - 时间戳必须是北京时间 `YYYY-MM-DD HH:mm:ss`,ISO 8601 会被直接拒 ## 设计取舍 - **未付款/已关闭的通知也回 `success`**:回 4xx 会让支付宝一直重推,而这些状态本来 就不该结算,重推多少次结果一样。 - **业务错误(code != 10000)标记为 definitive**:参数/商户配置问题重试一百次也一样。 - **网关地址只允许 https 域名**:允许自定义是为了沙箱,但「可配置的出站地址」天然是 SSRF 入口,所以拒 IP 字面量、localhost、.local/.internal。 - **私钥不回显**:后台只显示「已配置」,不把密钥材料吐回浏览器。 - **关单失败不假装成功**:返回 false,让内核保留记录等过期扫描。 ## 配套 后台配置页(`frontend/`):AppID / 网关 / 应用私钥 / 支付宝公钥,四语言目录。 装了插件才有支付方式 —— 没配密钥时 `getMethods()` 返回空,不制造「能点但必失败」的支付按钮。 ## 验证 `pnpm test` **33 例**:协议 23 例(签名往返、篡改、错密钥、裸私钥、金额换算、响应原文 验签、业务错误、嵌套节点提取、回调四类拒绝、网关 URL 校验)+ 插件接线 10 例 (未配置不给支付方式、CNY 之外不出网、precreate 请求含签名、回调结算与不结算、未签名通知 在结算前被拒、配置持久化与坏密钥拒绝保存)。 `pnpm typecheck` / `pnpm build` 通过;`install-into-kernel.mjs` 成功装入内核 data/plugins。 ## 未完成(写清楚,别当成已经能用) - **未用真实商户号跑过真单**:需要 AppID + 应用私钥 + 支付宝公钥 + 可公网回调的 https 域名。 - **微信支付 v3 未做**(需要 APIv3 密钥 + 平台证书,且回调要 AES-GCM 解密,单独一件)。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
对标 #12.2 的支付宝半边。审计指出支付只有第三方聚合(
epay)一条路,缺官方直连。做了什么
新插件
packages/plugins/alipay:alipay.trade.precreate扫码下单 + 异步通知验签 + 关单,商户自有密钥,不经中间商;配套后台配置页(AppID / 网关 / 应用私钥 / 支付宝公钥,四语言)。
没有商户号,怎么验
密码学与协议不需要商户凭据也能验透:自签一对 RSA 密钥分别扮演「商户」和「支付宝」,
签名/验签/回调/金额换算全部跑真实 crypto —— 没有一处 mock 掉签名。
三个必须按支付宝原文来、否则必然出错的点:
localeCompareJSON.stringify(parsed)设计取舍
success(如TRADE_CLOSED):回 4xx 会让支付宝无限重推,而这些状态本来就不该结算,重推多少次结果一样。
code != 10000)标 definitive:参数/商户配置问题重试无意义。getMethods()返回空:不制造「能点但必失败」的支付按钮。所以拒 IP 字面量、localhost、
.local/.internal。验证
pnpm test33 例:协议 23(签名往返、篡改、错密钥、裸 base64 私钥补 PEM、分↔元、响应原文验签、嵌套节点提取、业务错误、回调四类拒绝、网关 URL 校验)+ 插件接线 10
(未配置不给支付方式、CNY 之外不出网、precreate 请求含签名、回调结算/不结算、
未签名通知在结算前被拒、配置持久化、坏密钥拒绝保存)
pnpm typecheck/pnpm build通过;install-into-kernel.mjs成功装入内核data/plugins未完成
因此按 TRACK §四 的约定,本 PR 只能声称「驱动已实现,未联调」,不能写「已支持支付宝」。