|
|
|
@@ -13,18 +13,27 @@ import ( |
|
|
|
) |
|
|
|
|
|
|
|
type TopUp struct { |
|
|
|
Id int `json:"id"` |
|
|
|
UserId int `json:"user_id" gorm:"index"` |
|
|
|
Amount int64 `json:"amount"` |
|
|
|
Money float64 `json:"money"` |
|
|
|
TradeNo string `json:"trade_no" gorm:"unique;type:varchar(255);index"` |
|
|
|
PaymentMethod string `json:"payment_method" gorm:"type:varchar(50)"` |
|
|
|
CreateTime int64 `json:"create_time"` |
|
|
|
CompleteTime int64 `json:"complete_time"` |
|
|
|
Status string `json:"status"` |
|
|
|
UserEmail string `json:"user_email" gorm:"-"` // Join 查询时填充,非数据库字段 |
|
|
|
Id int `json:"id"` |
|
|
|
UserId int `json:"user_id" gorm:"index"` |
|
|
|
Amount int64 `json:"amount"` |
|
|
|
Money float64 `json:"money"` |
|
|
|
TradeNo string `json:"trade_no" gorm:"unique;type:varchar(255);index"` |
|
|
|
PaymentMethod string `json:"payment_method" gorm:"type:varchar(50)"` |
|
|
|
PaymentProvider string `json:"payment_provider" gorm:"type:varchar(50);default:''"` |
|
|
|
CreateTime int64 `json:"create_time"` |
|
|
|
CompleteTime int64 `json:"complete_time"` |
|
|
|
Status string `json:"status"` |
|
|
|
UserEmail string `json:"user_email" gorm:"-"` // Join 查询时填充,非数据库字段 |
|
|
|
} |
|
|
|
|
|
|
|
const ( |
|
|
|
PaymentProviderEpay = "epay" |
|
|
|
PaymentProviderStripe = "stripe" |
|
|
|
PaymentProviderCreem = "creem" |
|
|
|
PaymentProviderWechat = "wechat_pay" |
|
|
|
PaymentProviderAlipay = "alipay" |
|
|
|
) |
|
|
|
|
|
|
|
// fillTopUpEmails 批量填充 topup 记录的用户邮箱 |
|
|
|
func fillTopUpEmails(topups []*TopUp) { |
|
|
|
if len(topups) == 0 { |
|
|
|
@@ -113,7 +122,10 @@ func Recharge(referenceId string, customerId string) (err error) { |
|
|
|
} |
|
|
|
|
|
|
|
quota = topUp.Money * common.QuotaPerUnit |
|
|
|
err = tx.Model(&User{}).Where("id = ?", topUp.UserId).Updates(map[string]interface{}{"stripe_customer": customerId, "quota": gorm.Expr("quota + ?", quota)}).Error |
|
|
|
if topUp.PaymentProvider != "" && topUp.PaymentProvider != PaymentProviderStripe { |
|
|
|
return fmt.Errorf("支付网关不匹配: 订单由 %s 创建, 但 Stripe webhook 尝试完成", topUp.PaymentProvider) |
|
|
|
} |
|
|
|
err = tx.Model(&User{}).Where("id = ?", topUp.UserId).Updates(map[string]interface{}{"stripe_customer": customerId, "quota": gorm.Expr("quota + ?", quota)}).Error |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
@@ -360,6 +372,11 @@ func RechargeCreem(referenceId string, customerEmail string, customerName string |
|
|
|
return errors.New("充值订单状态错误") |
|
|
|
} |
|
|
|
|
|
|
|
// 防止跨网关回调攻击 |
|
|
|
if topUp.PaymentProvider != "" && topUp.PaymentProvider != PaymentProviderCreem { |
|
|
|
return fmt.Errorf("支付网关不匹配: 订单由 %s 创建, 但 Creem webhook 尝试完成", topUp.PaymentProvider) |
|
|
|
} |
|
|
|
|
|
|
|
topUp.CompleteTime = common.GetTimestamp() |
|
|
|
topUp.Status = common.TopUpStatusSuccess |
|
|
|
err = tx.Save(topUp).Error |
|
|
|
|