add count easypay
This commit is contained in:
@@ -19,17 +19,126 @@ import (
|
||||
|
||||
// EasyPayService 易支付服务
|
||||
type EasyPayService struct {
|
||||
config config.EasyPayConfig
|
||||
client *http.Client
|
||||
config config.EasyPayConfig
|
||||
client *http.Client
|
||||
orderModel model.OrderModel // 订单模型,用于次数轮询模式查询用户订单数量
|
||||
}
|
||||
|
||||
// getSelectedCID 获取当前应该使用的渠道ID
|
||||
// ctx: 上下文,用于次数轮询模式时访问Redis
|
||||
// userID: 用户ID,用于次数轮询模式时记录用户使用的渠道
|
||||
func (e *EasyPayService) getSelectedCID(ctx context.Context, userID string) string {
|
||||
// 如果没有配置 CID,返回空字符串
|
||||
if len(e.config.CIDs) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 如果只有一个渠道,直接返回
|
||||
if len(e.config.CIDs) == 1 {
|
||||
return e.config.CIDs[0]
|
||||
}
|
||||
|
||||
// 根据轮询模式选择策略
|
||||
rotateMode := e.config.RotateMode
|
||||
if rotateMode == "" {
|
||||
rotateMode = "day" // 默认天数轮询
|
||||
}
|
||||
|
||||
switch rotateMode {
|
||||
case "count":
|
||||
// 次数轮询模式:按用户订单次数轮询
|
||||
return e.selectCIDByCount(ctx, userID)
|
||||
case "day":
|
||||
// 天数轮询模式:按时间轮询
|
||||
return e.selectCIDByRotation()
|
||||
default:
|
||||
// 默认使用天数轮询
|
||||
logx.Infof("未知的轮询模式: %s,使用默认天数轮询", rotateMode)
|
||||
return e.selectCIDByRotation()
|
||||
}
|
||||
}
|
||||
|
||||
// selectCIDByRotation 按时间轮询策略选择CID
|
||||
func (e *EasyPayService) selectCIDByRotation() string {
|
||||
if len(e.config.CIDs) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 如果只有一个,直接返回
|
||||
if len(e.config.CIDs) == 1 {
|
||||
return e.config.CIDs[0]
|
||||
}
|
||||
|
||||
// 获取轮询天数,默认3天
|
||||
rotateDays := e.config.RotateDays
|
||||
if rotateDays <= 0 {
|
||||
rotateDays = 3
|
||||
}
|
||||
|
||||
// 计算从某个基准日期(比如2020-01-01)开始的天数
|
||||
baseDate := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
now := time.Now()
|
||||
daysSinceBase := int(now.Sub(baseDate).Hours() / 24)
|
||||
|
||||
// 按轮询天数计算当前应该使用的索引
|
||||
rotationIndex := (daysSinceBase / rotateDays) % len(e.config.CIDs)
|
||||
|
||||
selectedCID := e.config.CIDs[rotationIndex]
|
||||
logx.Infof("易支付渠道天数轮询选择: 总渠道数=%d, 轮询天数=%d, 当前索引=%d, 选择渠道=%s",
|
||||
len(e.config.CIDs), rotateDays, rotationIndex, selectedCID)
|
||||
|
||||
return selectedCID
|
||||
}
|
||||
|
||||
// selectCIDByCount 按次数轮询策略选择CID(针对用户)
|
||||
func (e *EasyPayService) selectCIDByCount(ctx context.Context, userID string) string {
|
||||
if len(e.config.CIDs) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 如果只有一个,直接返回
|
||||
if len(e.config.CIDs) == 1 {
|
||||
return e.config.CIDs[0]
|
||||
}
|
||||
|
||||
// 如果没有用户ID,回退到天数轮询
|
||||
if userID == "" {
|
||||
logx.Infof("次数轮询模式但用户ID为空,回退到天数轮询")
|
||||
return e.selectCIDByRotation()
|
||||
}
|
||||
|
||||
// 查询该用户的易支付订单数量
|
||||
orderCount := int64(0)
|
||||
if e.orderModel != nil {
|
||||
builder := e.orderModel.SelectBuilder().
|
||||
Where("user_id = ?", userID).
|
||||
Where("payment_platform = ?", "easypay_alipay")
|
||||
count, err := e.orderModel.FindCount(ctx, builder, "id")
|
||||
if err != nil {
|
||||
logx.Errorf("查询用户易支付订单数量失败: %v,使用索引0", err)
|
||||
} else {
|
||||
orderCount = count
|
||||
}
|
||||
}
|
||||
|
||||
// 根据订单数量计算应该使用的渠道索引(订单数量从0开始,所以第0个订单用索引0,第1个订单用索引1,以此类推)
|
||||
channelIndex := int(orderCount) % len(e.config.CIDs)
|
||||
selectedCID := e.config.CIDs[channelIndex]
|
||||
|
||||
logx.Infof("易支付渠道次数轮询选择: 用户ID=%s, 总渠道数=%d, 用户订单数=%d, 选择索引=%d, 选择渠道=%s",
|
||||
userID, len(e.config.CIDs), orderCount, channelIndex, selectedCID)
|
||||
|
||||
return selectedCID
|
||||
}
|
||||
|
||||
// NewEasyPayService 创建易支付服务实例
|
||||
func NewEasyPayService(c config.Config) *EasyPayService {
|
||||
func NewEasyPayService(c config.Config, orderModel model.OrderModel) *EasyPayService {
|
||||
return &EasyPayService{
|
||||
config: c.EasyPay,
|
||||
client: &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
},
|
||||
orderModel: orderModel,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +298,7 @@ func (e *EasyPayService) verifySign(params map[string]string, sign string) bool
|
||||
}
|
||||
|
||||
// CreateEasyPayH5Order 创建易支付H5订单(页面跳转方式)
|
||||
func (e *EasyPayService) CreateEasyPayH5Order(amount float64, subject string, outTradeNo string) (string, error) {
|
||||
func (e *EasyPayService) CreateEasyPayH5Order(ctx context.Context, amount float64, subject string, outTradeNo string, userID string) (string, error) {
|
||||
// 格式化金额,保留两位小数
|
||||
moneyStr := fmt.Sprintf("%.2f", amount)
|
||||
|
||||
@@ -203,9 +312,9 @@ func (e *EasyPayService) CreateEasyPayH5Order(amount float64, subject string, ou
|
||||
"return_url": e.config.ReturnUrl,
|
||||
"sign_type": "MD5",
|
||||
}
|
||||
// 如果配置了渠道ID,则添加
|
||||
if e.config.CID != "" {
|
||||
params["cid"] = e.config.CID
|
||||
// 获取并添加渠道ID
|
||||
if cid := e.getSelectedCID(ctx, userID); cid != "" {
|
||||
params["cid"] = cid
|
||||
}
|
||||
|
||||
// 生成签名
|
||||
@@ -226,7 +335,7 @@ func (e *EasyPayService) CreateEasyPayH5Order(amount float64, subject string, ou
|
||||
}
|
||||
|
||||
// CreateEasyPayAppOrder 创建易支付APP订单(API方式)
|
||||
func (e *EasyPayService) CreateEasyPayAppOrder(ctx context.Context, amount float64, subject string, outTradeNo string, clientIP string) (string, error) {
|
||||
func (e *EasyPayService) CreateEasyPayAppOrder(ctx context.Context, amount float64, subject string, outTradeNo string, clientIP string, userID string) (string, error) {
|
||||
// 格式化金额,保留两位小数
|
||||
moneyStr := fmt.Sprintf("%.2f", amount)
|
||||
|
||||
@@ -241,9 +350,9 @@ func (e *EasyPayService) CreateEasyPayAppOrder(ctx context.Context, amount float
|
||||
"device": "pc",
|
||||
"sign_type": "MD5",
|
||||
}
|
||||
// 如果配置了渠道ID,则添加
|
||||
if e.config.CID != "" {
|
||||
params["cid"] = e.config.CID
|
||||
// 获取并添加渠道ID
|
||||
if cid := e.getSelectedCID(ctx, userID); cid != "" {
|
||||
params["cid"] = cid
|
||||
}
|
||||
|
||||
// 生成签名
|
||||
@@ -302,14 +411,25 @@ func (e *EasyPayService) CreateEasyPayAppOrder(ctx context.Context, amount float
|
||||
return "", fmt.Errorf("未获取到支付链接")
|
||||
}
|
||||
|
||||
// CreateEasyPayOrderResult 易支付订单创建结果
|
||||
type CreateEasyPayOrderResult struct {
|
||||
PayURL string // 支付URL
|
||||
CID string // 使用的渠道ID
|
||||
}
|
||||
|
||||
// CreateEasyPayOrder 根据平台类型创建易支付订单
|
||||
func (e *EasyPayService) CreateEasyPayOrder(ctx context.Context, amount float64, subject string, outTradeNo string) (string, error) {
|
||||
func (e *EasyPayService) CreateEasyPayOrder(ctx context.Context, amount float64, subject string, outTradeNo string, userID string) (*CreateEasyPayOrderResult, error) {
|
||||
// 获取选中的渠道ID
|
||||
selectedCID := e.getSelectedCID(ctx, userID)
|
||||
|
||||
// 根据 ctx 中的 platform 判断平台
|
||||
platform, platformOk := ctx.Value("platform").(string)
|
||||
if !platformOk {
|
||||
return "", fmt.Errorf("无效的支付平台")
|
||||
return nil, fmt.Errorf("无效的支付平台")
|
||||
}
|
||||
|
||||
var payURL string
|
||||
var err error
|
||||
switch platform {
|
||||
case model.PlatformApp:
|
||||
// APP平台使用API方式
|
||||
@@ -317,13 +437,22 @@ func (e *EasyPayService) CreateEasyPayOrder(ctx context.Context, amount float64,
|
||||
if ip, ok := ctx.Value("client_ip").(string); ok {
|
||||
clientIP = ip
|
||||
}
|
||||
return e.CreateEasyPayAppOrder(ctx, amount, subject, outTradeNo, clientIP)
|
||||
payURL, err = e.CreateEasyPayAppOrder(ctx, amount, subject, outTradeNo, clientIP, userID)
|
||||
case model.PlatformH5:
|
||||
// H5平台使用页面跳转方式
|
||||
return e.CreateEasyPayH5Order(amount, subject, outTradeNo)
|
||||
payURL, err = e.CreateEasyPayH5Order(ctx, amount, subject, outTradeNo, userID)
|
||||
default:
|
||||
return "", fmt.Errorf("不支持的支付平台: %s", platform)
|
||||
return nil, fmt.Errorf("不支持的支付平台: %s", platform)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CreateEasyPayOrderResult{
|
||||
PayURL: payURL,
|
||||
CID: selectedCID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HandleEasyPayNotification 处理易支付回调通知
|
||||
|
||||
Reference in New Issue
Block a user