Files
junhong_cmp_fiber/internal/application/packagesilence/online_jsapi.go
邹进 b2fc74c021
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
feat: H5 沉默期延期微信支付改为微信内直接拉起(JSAPI)
- H5 下单带 app_type 且选微信、商户为微信直连时,复用套餐购买的 JSAPI 预下单,返回 pay_config
- 调起参数保存在支付单,延期订单详情可继续支付;查单、回调、超时关单、作废沿用原流程
- 后台生成二维码、支付宝、富友商户保持原方式
2026-11-07 21:57:22 +09:00

65 lines
3.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package packagesilence
import (
"context"
"encoding/json"
"strings"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
)
// jsapiContentPrefix 标记支付单 qr_content 里保存的是微信 JSAPI 调起参数(JSON),而不是二维码 / 支付链接。
const jsapiContentPrefix = "jsapi:"
// JSAPIPayer 为 C 端客户按已冻结商户创建微信 JSAPI 预下单(复用套餐购买的公众号 / 小程序支付)。
type JSAPIPayer interface {
CreateJSAPIPayConfig(ctx context.Context, customerID uint, appType string, config *model.WechatConfig,
paymentNo, description string, amount int64) (*dto.ClientPayConfig, error)
}
// SetJSAPIPayer 注入微信 JSAPI 预下单能力;未注入时 H5 微信延期仍走 H5 支付链接。
func (s *ExtensionService) SetJSAPIPayer(payer JSAPIPayer) { s.jsapi = payer }
// useJSAPI 判断本次下单是否走微信内直接支付:H5 客户、微信支付、带应用类型、商户为微信直连(v3 / v2)。
// 富友商户仍走扫码,避免查单与下单协议不一致。
func (s *ExtensionService) useJSAPI(source string, req dto.SilenceOnlineOrderRequest, config *model.WechatConfig) bool {
return s.jsapi != nil && source == constants.SilenceOrderSourceClient && req.PaymentMethod == model.PaymentByWechat &&
strings.TrimSpace(req.AppType) != "" && config != nil &&
(config.ProviderType == model.ProviderTypeWechat || config.ProviderType == model.ProviderTypeWechatV2)
}
// createJSAPIContent 预下单并把调起参数编码成支付单内容,便于"继续支付"复用(预支付有效期 2 小时,长于支付截止)。
func (s *ExtensionService) createJSAPIContent(ctx context.Context, customerID uint, appType string, config *model.WechatConfig, payment *model.Payment) (string, error) {
payConfig, err := s.jsapi.CreateJSAPIPayConfig(ctx, customerID, appType, config, payment.PaymentNo, "沉默期延期", payment.Amount)
if err != nil {
return "", err
}
if payConfig == nil || strings.TrimSpace(payConfig.PackageVal) == "" {
return "", errors.New(errors.CodeWechatPayFailed, "微信支付未返回调起参数")
}
raw, err := json.Marshal(payConfig)
if err != nil {
return "", errors.Wrap(errors.CodeInternalError, err, "编码微信支付参数失败")
}
return jsapiContentPrefix + string(raw), nil
}
// ApplyPaymentContent 把支付单内容写到响应:JSAPI 参数放 pay_config,其余(二维码 / 支付链接)放 qr_content。
func ApplyPaymentContent(resp *dto.SilenceExtensionOrderResponse, content string) {
if resp == nil || content == "" {
return
}
if strings.HasPrefix(content, jsapiContentPrefix) {
var payConfig dto.ClientPayConfig
if err := json.Unmarshal([]byte(strings.TrimPrefix(content, jsapiContentPrefix)), &payConfig); err == nil {
resp.PayConfig = &payConfig
resp.QRContent = ""
}
return
}
resp.QRContent = content
}