fix(alipay): 加固授权回调 state 解析 + 异步通知补业务字段交叉校验 - #106
Merged
Conversation
jeequan
force-pushed
the
fix/alipay-callback-bizcheck
branch
from
May 27, 2026 07:51
06618c8 to
cdb9421
Compare
修复 #81(感谢 @xiaowuDev 提交的 PR 描述定位到这两处问题)。 1) 授权回调 state 参数解析鲁棒性 - 原 AlipayBizController.redirectAppToAppAuth / appToAppAuthCallback 直接 split("_")[0]/[1],没做长度、空值、空串校验,异常或被构造的 state 会触发 ArrayIndexOutOfBoundsException / 空指针,回调链路出现 500。 - 抽出 AlipayKit.parseIsvAndMchAppIdState(String) 工具方法:用 indexOf 而非 split(避免 mchAppId 内部含 "_" 时被切碎),任一段为空都返回 null。 - 两个回调入口改用工具方法 + null 校验 + mchAppService.getById 结果空校验, 抛出 BizException 由现有异常处理统一展示给用户。 - 顺手清理 redirectAppToAppAuth 里两行无效代码(getSandbox() 返回值未使用、 isvNo 局部变量从未读取)。 2) 异步通知业务字段交叉校验 - 原 AlipayChannelNoticeService.doNotice 验签通过后直接信任 jsonParams, 仅取了 trade_no / buyer_id / trade_status 来设置 ChannelRetMsg。 验签通过仅证明请求来自支付宝并由本商户密钥签名,不保证回调内容就是 这笔本地订单。多商户配置切换 / 跨订单签名穿越 / 沙箱与生产串扰 等场景下,仍可能出现 out_trade_no / 金额 / app_id 与本地订单上下文 不一致的回调,按现有逻辑会把这笔"看似合法"的回调直接当成功来回写订单。 - 在验签通过后、设置 ChannelRetMsg 前补一道校验: out_trade_no 必须等于 payOrder.payOrderId、 app_id 必须等于商户配置里的 appId、 total_amount(元)必须等于本地金额(分→元,用 BigDecimal compareTo 比对避免 scale 差异)。 - 任一字段不一致:记 ERROR 日志(带具体不匹配的字段与双方值,便于排查)+ 返回 SUCCESS 给支付宝阻断重试 8 次浪费资源 + 不更新订单状态。 - ChannelState 用 UNKNOWN 而非 CONFIRM_FAIL,避免被下游误判为"已确认失败" 从而触发退款补偿逻辑。
jeequan
force-pushed
the
fix/alipay-callback-bizcheck
branch
from
May 27, 2026 07:53
cdb9421 to
b20b680
Compare
Merged
pull Bot
pushed a commit
to w346489584/jeepay
that referenced
this pull request
May 27, 2026
按 upgrade.md 风格惯例(参考 V3.2.7 / V3.2.8 段),把 V3.2.9 段从展开版 (带 ">" 引言段 + 每条 3-5 行类名 / 机制 / 详细技术解释)改成每条 1-2 行 的简短风格。 upgrade.md 是面向用户的版本说明,关心"哪些场景受影响 / 是否需要升级", 详细机制保留在 PR jeequan#102 / jeequan#106 描述里。
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.
背景
修复 #81(感谢 @xiaowuDev 提交的 PR 描述定位到这两处问题,原 PR 关闭后由本 PR 重新实现)。
修复 1:授权回调 state 参数解析鲁棒性
原问题:
AlipayBizController的redirectAppToAppAuth和appToAppAuthCallback都直接isvAndMchAppId.split("_")[0]/[1],未做长度 / 空值 / 空串校验。异常或被构造的 state(如 `/redirectAppToAppAuth/badid` 或 state 为空字符串)会触发ArrayIndexOutOfBoundsException或空指针,回调链路出现 500。修复:
AlipayKit.parseIsvAndMchAppIdState(String)工具方法:用indexOf而非split(避免 mchAppId 内部含_时被切碎),任一段为空返回 nullmchAppService.getById结果空校验,抛BizException由现有异常处理统一展示redirectAppToAppAuth里两行无效代码(getSandbox()返回值未使用、isvNo局部变量从未读取)修复 2:异步通知业务字段交叉校验
原问题:
AlipayChannelNoticeService.doNotice验签通过后直接信任jsonParams,仅取了trade_no/buyer_id/trade_status来设置ChannelRetMsg。验签通过仅证明请求来自支付宝并由本商户密钥签名,不保证回调内容就是这笔本地订单。多商户配置切换、跨订单签名穿越、沙箱与生产串扰等场景下,仍可能出现out_trade_no/ 金额 /app_id与本地订单上下文不一致的回调,按现有逻辑会把这笔"看似合法"的回调直接当成功回写订单,造成错单和账务异常。修复:在验签通过后、设置
ChannelRetMsg前补一道校验:out_trade_no必须等于payOrder.payOrderIdapp_id必须等于商户配置里的appId(ISV/普通商户分别取对应配置)total_amount(元)必须等于本地金额(分→元,用BigDecimal.compareTo比对,避免 scale 差异)任一字段不一致:
SUCCESS给支付宝,阻断 8 次重试浪费资源ChannelState设为UNKNOWN(而非CONFIRM_FAIL,避免被下游误判为"确认失败"触发退款补偿逻辑)不做的事
seller_id:AlipayNormalMchParams当前没存 PID 字段,强行做要么改 schema 要么改 channelExtra,破坏面太大,留到未来需要时再补。app_id校验已能拦截 PR 优化支付宝回调参数解析,增加参数格式校验 #81 描述的主要场景。jeepay-payment/src/test是空目录占位状态;校验逻辑组织成纯静态方法 / 局部变量,便于未来引入测试基础设施时补。验证
mvn -pl jeepay-payment -am compile通过out_trade_no与本地订单不一致 /total_amount不一致 /app_id不一致 时返回 SUCCESS 但订单状态不变,日志能看到 ERROR 行发布节奏
下个补丁版(V3.2.9)一起发出。本 PR 不改 version.md,由 V3.2.9 发版本 PR 集中撞版本号。