You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

81 lines
2.0 KiB

  1. package model
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/QuantumNous/new-api/common"
  6. "github.com/QuantumNous/new-api/logger"
  7. "github.com/shopspring/decimal"
  8. "gorm.io/gorm"
  9. )
  10. // RechargeAlipay 支付宝支付充值完成(由回调触发)
  11. // 与 RechargeWechat 类似,使用事务+行锁保证幂等
  12. func RechargeAlipay(tradeNo string) error {
  13. if tradeNo == "" {
  14. return errors.New("未提供支付单号")
  15. }
  16. var quotaToAdd int64
  17. var payMoney float64
  18. var userId int
  19. refCol := "`trade_no`"
  20. if common.UsingPostgreSQL {
  21. refCol = `"trade_no"`
  22. }
  23. err := DB.Transaction(func(tx *gorm.DB) error {
  24. topUp := &TopUp{}
  25. if err := tx.Set("gorm:query_option", "FOR UPDATE").Where(refCol+" = ?", tradeNo).First(topUp).Error; err != nil {
  26. return errors.New("充值订单不存在")
  27. }
  28. if topUp.Status == common.TopUpStatusSuccess {
  29. // 已处理,幂等返回
  30. return nil
  31. }
  32. if topUp.Status != common.TopUpStatusPending {
  33. return errors.New("充值订单状态错误")
  34. }
  35. topUp.CompleteTime = common.GetTimestamp()
  36. topUp.Status = common.TopUpStatusSuccess
  37. if err := tx.Save(topUp).Error; err != nil {
  38. return err
  39. }
  40. // 支付宝充值额度计算:
  41. // topUp.Money = req.Amount * topUpGroupRatio * unitPrice * discount(经分组倍率和折扣调整后的实际支付金额)
  42. // 充值额度 = topUp.Money * QuotaPerUnit
  43. dMoney := decimal.NewFromFloat(topUp.Money)
  44. dQuotaPerUnit := decimal.NewFromFloat(common.QuotaPerUnit)
  45. quotaToAdd = dMoney.Mul(dQuotaPerUnit).IntPart()
  46. if quotaToAdd <= 0 {
  47. return errors.New("无效的充值额度")
  48. }
  49. if err := tx.Model(&User{}).Where("id = ?", topUp.UserId).Update("quota", gorm.Expr("quota + ?", quotaToAdd)).Error; err != nil {
  50. return err
  51. }
  52. userId = topUp.UserId
  53. payMoney = topUp.Money
  54. return nil
  55. })
  56. if err != nil {
  57. return err
  58. }
  59. if quotaToAdd > 0 {
  60. RecordLog(userId, LogTypeTopup, fmt.Sprintf("使用支付宝充值成功,充值金额: %v,支付金额:%.2f", logger.FormatQuota(int(quotaToAdd)), payMoney))
  61. }
  62. return nil
  63. }