Skip to content

feat(payment): 支持订单级 notify/return 地址并回退应用默认配置#193

Merged
yyg-max merged 9 commits intolinux-do:masterfrom
zhx47:feat-order-level-callback-urls
Mar 10, 2026
Merged

feat(payment): 支持订单级 notify/return 地址并回退应用默认配置#193
yyg-max merged 9 commits intolinux-do:masterfrom
zhx47:feat-order-level-callback-urls

Conversation

@zhx47
Copy link
Contributor

@zhx47 zhx47 commented Mar 6, 2026

例行检查

  • 我已阅读并理解 贡献者公约
  • 我已阅读并同意 贡献者许可协议 (CLA),确认我的贡献将根据项目的 Apache2.0 许可证进行许可
  • 我知晓如果此 PR 并不做出实质性更改,或可被认为是为了PR被合并而提交PR的,则可能不会被合并

关联信息

QuantumNous/new-api#2906
https://linux.do/t/topic/1696314

变更内容

允许记录创建订单时候指定的回调信息

变更原因

允许记录创建订单时候指定的回调信息

newapi充值余额和支付订阅是两个不同的接口

@zhx47
Copy link
Contributor Author

zhx47 commented Mar 6, 2026

@chenyme 老板,是否可以进行检查一下

@yyg-max
Copy link
Collaborator

yyg-max commented Mar 7, 2026

啊,怎么支付回调还有多个,按道理不应该只存在一个支付回调吗

@zhx47
Copy link
Contributor Author

zhx47 commented Mar 7, 2026

啊,怎么支付回调还有多个,按道理不应该只存在一个支付回调吗

很明显不是,微信支付也可以针对不同类型的订单进行指定回调路径

@yyg-max
Copy link
Collaborator

yyg-max commented Mar 7, 2026

很明显不是,微信支付也可以针对不同类型的订单进行指定回调路径

好的感谢PR,等前个PR合并了再看这个

@yyg-max yyg-max requested a review from chenyme March 7, 2026 09:05
@yyg-max
Copy link
Collaborator

yyg-max commented Mar 9, 2026

冲突解决一下~

# Conflicts:
#	internal/apps/payment/middlewares.go
@zhx47
Copy link
Contributor Author

zhx47 commented Mar 9, 2026

冲突解决一下~

我来看下

- 补齐 LDCPayRequest 的 notify_url 和 return_url 字段解析
- 将订单级回调地址纳入 MD5/Ed25519 签名校验并透传到通用下单请求
- 更新 API 文档,说明订单级通知与回跳地址的参数和优先级
@zhx47
Copy link
Contributor Author

zhx47 commented Mar 9, 2026

冲突解决一下~

已处理

Remark string `json:"remark" gorm:"size:255"`
PaymentType string `json:"payment_type" gorm:"size:20"`
NotifyURL *string `json:"-" gorm:"size:512"`
ReturnURL *string `json:"-" gorm:"size:512"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RedirectURI string json:"redirect_uri" gorm:"size:512"
NotifyURL string json:"notify_url" gorm:"size:512"

Remark string `json:"remark" binding:"max=100"`
PaymentType string `json:"payment_type"`
NotifyURL *string `json:"notify_url,omitempty"`
ReturnURL *string `json:"return_url,omitempty"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NotifyURL string form:"notify_url" binding:"omitempty,max=512,url"
ReturnURL string form:"return_url" binding:"omitempty,max=512,url"

MerchantOrderNo *string `form:"out_trade_no" binding:"required,min=1,max=64"`
Amount decimal.Decimal `form:"money" binding:"required"`
NotifyURL string `form:"notify_url"`
ReturnURL string `form:"return_url"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NotifyURL string form:"notify_url" binding:"omitempty,max=512,url"
ReturnURL string form:"return_url" binding:"omitempty,max=512,url"

return
}

redirectURI := ResolveOrderReturnURL(&order, &merchant)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以通过 cmp.or

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里就不需要改了,通过 cmp.or 应该可以完美解决

- 为 notify_url 和 return_url 增加 URL 与长度校验,阻止无效地址进入支付流程
- 提取 util.NilIfEmptyString 复用空值处理,删除 payment 模块重复的 URL 归一化函数
- 订单模型对外暴露 notify_url 和 return_url,并在回调与支付页直接回退到商户默认地址
NotifyURL *string `json:"-" gorm:"size:512"`
ReturnURL *string `json:"-" gorm:"size:512"`
NotifyURL *string `json:"notify_url" gorm:"size:512"`
ReturnURL *string `json:"return_url" gorm:"size:512"`
Copy link
Collaborator

@yyg-max yyg-max Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉直接 string 就行?然后不需要 NilIfEmptyString 进行判断了

Copy link
Contributor Author

@zhx47 zhx47 Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉直接 string 就行?然后不需要 NilIfEmptyString 进行判断了

可以的,是直接记录空串,还是记录应用配置的默认的,不过记录应用配置的,task是不是依旧需要进行判断,防止上线中途的空数据

Copy link
Collaborator

@yyg-max yyg-max Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果orders里的notify_url是空串通过 mcp.or 就能直接判断 cmp.or(order.notify_url,api_key.notify_url) 这样即可,就不用再判断了。
*string 也可以,string和api_key表里面 统一更好点?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我这个本来是打算数据库不记录空串的,没传递的时候记录null,要是允许数据库存入空串我就改一下

Copy link
Collaborator

@yyg-max yyg-max Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

允许的,传递也会传递空

- 将订单 notify_url 和 return_url 从 *string 改为 string
- 移除 NilIfEmptyString 与相关解引用逻辑,直接使用空字符串兜底
- 简化支付回调与跳转地址读取,减少空指针分支
Remark string `json:"remark" gorm:"size:255"`
PaymentType string `json:"payment_type" gorm:"size:20"`
NotifyURL string `json:"notify_url" gorm:"size:512"`
ReturnURL string `json:"return_url" gorm:"size:512"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我复制错了,应该是
NotifyURL string json:"notify_url" gorm:"size:512"
RedirectURI string `json:"redirect_uri" gorm:"size:512"
和后端的api_key表统一一下

NotifyURL string `json:"notify_url" gorm:"size:512"`
ReturnURL string `json:"return_url" gorm:"size:512"`
RedirectURI string `json:"redirect_uri" gorm:"size:100"`
NotifyURL string `json:"notify_url" gorm:"size:100"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

长度为啥变成100了,会拼接参数长度可能不够

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

跟随merchant_api_keys的,没搞明白,为啥merchant_api_keys 100够啊

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

订单级别的redirect_uri和notify_url实际上和merchant_api_keys的含义是一样的,应该共用一个数据字典才对,如果之前merchant_api_keys长度100跑着没问题,我认为这里还是100吧,之前500是没注意merchant_api_keys的信息,你提示我需要对齐我才想起来去看下

Copy link
Collaborator

@yyg-max yyg-max Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

想留个长一点的兼容可以让用户在url做一些验证等,问题也不大就这样吧,那把 gin的验证最大长度改成100吧。
我刚review时看到 frontend/lib/services/merchant/types.ts(GetMerchantOrderResponse.order.return_url)后端应该返回的是 redirect_uri ,你可以顺便运行测一下,有问题的话麻烦把前端接收参数改为redirect_uri ❤️

Copy link
Contributor Author

@zhx47 zhx47 Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

看了下,这个应该没有影响,因为前端没有相关的展示。
支付成功跳转用的是

const redirectUri = orderInfo?.merchant?.redirect_uri
if (redirectUri && redirectUri.trim()) {
  window.location.href = redirectUri
  return
}

不是用的orderInfo.order下面的东西

现在前端的return_url应该是之前根据epay的进行占位的,实际上没有效果

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的,把参数校验改为 max=100 即可

@yyg-max yyg-max merged commit 1642efc into linux-do:master Mar 10, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants