Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ otel:
# Payment (LDC Credit EasyPay-compatible)
payment:
enabled: false
api_url: "https://credit.linux.do/epay" # 易支付网关地址
notify_base_url: "https://your-domain.com" # 本项目公网基址,用于拼接回调 URL
config_encryption_key: "<32-char-secret-key!!>" # AES-256 密钥,恰好 32 字节,首次部署后不可更改
order_expire_minutes: 10 # 订单未付款超时时间(分钟)
api_url: "https://credit.linux.do/epay" # 易支付网关地址
notify_base_url: "http://cdk.cdk.svc.cluster.local" # CDK 的内网或公网地址,供支付网关回调使用
redirect_base_url: "https://cdk.linux.do" # 支付完成后跳转的 URL 基址
config_encryption_key: "<32-char-secret-key!!>" # AES-256 密钥,恰好 32 字节,首次部署后不可更改
order_expire_minutes: 10 # 订单未付款超时时间(分钟)
8 changes: 6 additions & 2 deletions internal/apps/payment/epay.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ func callbackNotifyURL() string {
}

// callbackReturnURL 返回同步回跳地址。
func callbackReturnURL() string {
return strings.TrimRight(config.Config.Payment.NotifyBaseURL, "/") + "/received"
func callbackReturnURL(projectID string) string {
baseURL := strings.TrimRight(config.Config.Payment.RedirectBaseURL, "/")
if projectID == "" {
return baseURL + "/received"
}
return baseURL + "/receive/" + projectID
}

// refundResponse 易支付退款接口响应
Expand Down
16 changes: 12 additions & 4 deletions internal/apps/payment/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,17 @@ func InitiatePayment(ctx context.Context, p *project.Project, payer *oauth.User,
name := truncateRuneLen("CDK-"+p.Name, 60)
init = PaymentInitiation{
OutTradeNo: outTradeNo,
PayURL: submitURL(cfg.ClientID, secret, name, moneyString(p.Price), outTradeNo, callbackNotifyURL(), callbackReturnURL()),
Amount: moneyString(p.Price),
ExpireAt: expireAt,
PayURL: submitURL(
cfg.ClientID,
secret,
name,
moneyString(p.Price),
outTradeNo,
callbackNotifyURL(),
callbackReturnURL(p.ID),
),
Amount: moneyString(p.Price),
ExpireAt: expireAt,
}
return nil
})
Expand Down Expand Up @@ -385,7 +393,7 @@ func fulfillPaidOrder(ctx context.Context, order *PaymentOrder) error {

// CallbackURLs 返回当前平台配置的回调地址,用于前端展示给用户。
func CallbackURLs() (notifyURL, returnURL string) {
return callbackNotifyURL(), callbackReturnURL()
return callbackNotifyURL(), callbackReturnURL("")
}

// ErrOrderNotFoundSentinel 外部判断
Expand Down
3 changes: 3 additions & 0 deletions internal/config/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ type PaymentConfig struct {
// NotifyBaseURL 本项目对外可访问的基址(不含路径),例如 https://cdk.linux.do
// 用于拼接 notify_url / return_url 并提示用户在 LDC 商户后台填写
NotifyBaseURL string `mapstructure:"notify_base_url"`
// RedirectBaseURL 本项目对外可访问的基址(不含路径),例如 https://cdk.linux.do
// 用于拼接 redirect_url 并提示用户在 LDC 商户后台填写
RedirectBaseURL string `mapstructure:"redirect_base_url"`
// ConfigEncryptionKey 用于加密用户 clientSecret 的密钥,必须是 32 字节长度
// 建议直接填 32 字符 ASCII 字符串或 base64 解码得 32 字节
ConfigEncryptionKey string `mapstructure:"config_encryption_key"`
Expand Down
Loading