package shanghu import ( orm "duoduo/database" "errors" "fmt" "github.com/shopspring/decimal" "time" ) type ClientPayTrans struct { ID int64 `gorm:"column:id;type:bigint(20);primary_key" json:"id"` // 主键 RequestID string `gorm:"column:request_id;type:varchar(255)" json:"request_id"` // 请求id,幂等性 OutTradeNo string `gorm:"column:out_trade_no;type:varchar(255)" json:"out_trade_no"` // 交易id MerchantCardID int64 `gorm:"column:merchant_card_id;type:bigint(20)" json:"merchant_card_id"` // 商户卡id ClientOpenID string `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"` // 客户端openid Status int `gorm:"column:status;type:int(11)" json:"status"` // 1-未支付 2-支付成功 3-取消支付 4-退款 Amount decimal.Decimal `gorm:"column:amount;type:decimal(10,2)" json:"amount"` // 交易金额 ThirdTradeNo string `gorm:"column:third_trade_no;type:varchar(255)" json:"third_trade_no"` // 微信交易id PayTime time.Time `gorm:"column:pay_time;type:datetime(3);default:null" json:"pay_time"` // 支付时间 InvitationCode string `gorm:"column:invitation_code;type:varchar(25)" json:"invitation_code"` // 邀请码 AccountStatus int `gorm:"column:account_status;type:int(11)" json:"account_status"` // 分账状态 99-分账成功 2-分账失败 1-未分账 AccountErrLog string `gorm:"column:account_err_log;type:varchar(255)" json:"account_err_log"` // 分账err日志 CreateBy int64 `gorm:"column:create_by;type:bigint(20)" json:"create_by"` // 创建者 UpdateBy int64 `gorm:"column:update_by;type:bigint(20)" json:"update_by"` // 更新者 CreatedAt time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"` // 创建时间 UpdatedAt time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"` // 最后更新时间 DeletedAt time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间 } func (m *ClientPayTrans) TableName() string { return "client_pay_trans" } func (m *ClientPayTrans) GetRequestNum() int { var count int tableCount := orm.ShMysql.Table(m.TableName()).Where("request_id = ? ", m.RequestID) tableCount.Count(&count) return count } func (m *ClientPayTrans) GetNumByCardID() int { var count int tableCount := orm.ShMysql.Table(m.TableName()).Where("merchant_card_id = ? and status =2 ", m.MerchantCardID) tableCount.Count(&count) return count } func (m *ClientPayTrans) GetPayTransByOpenid() (ClientPayTrans, error) { var doc ClientPayTrans table := orm.ShMysql.Table(m.TableName()) table = table.Where("merchant_card_id = ? and client_open_id = ? and status = 2 ", m.MerchantCardID, m.ClientOpenID) if err := table.Select("*").First(&doc).Error; err != nil { return doc, err } return doc, nil } func (m *ClientPayTrans) GetPayTransById() (ClientPayTrans, error) { var doc ClientPayTrans table := orm.ShMysql.Table(m.TableName()) table = table.Where("id = ? ", m.ID) if err := table.Select("*").First(&doc).Error; err != nil { return doc, err } return doc, nil } func (m *ClientPayTrans) GetPayTransByTradeNo() (ClientPayTrans, error) { var doc ClientPayTrans table := orm.ShMysql.Table(m.TableName()) table = table.Where("out_trade_no = ? ", m.OutTradeNo) if err := table.Select("*").First(&doc).Error; err != nil { return doc, err } return doc, nil } func (u *ClientPayTrans) Create() (ClientPayTrans, error) { var doc ClientPayTrans var err error doc = *u err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error if err != nil { return doc, err } return doc, nil } func (m *ClientPayTrans) UpdatePayTransByTradeNo() error { if err := orm.ShMysql.Table(m.TableName()).Model(&m).Where("out_trade_no = ? ", m.OutTradeNo).Updates( map[string]interface{}{ "third_trade_no": m.ThirdTradeNo, "pay_time": m.PayTime, "status": m.Status, "account_status": m.AccountStatus, "updated_at": time.Now()}).Error; err != nil { return err } return nil } func (m *ClientPayTrans) GetTransByAccount() (ClientPayTrans, error) { var doc ClientPayTrans table := orm.ShMysql.Table(m.TableName()) table = table.Where("account_status = ? ", m.AccountStatus) if err := table.Select("*").First(&doc).Error; err != nil { return doc, err } return doc, nil } func (m *ClientPayTrans) GetPayTransByStatus() (ClientPayTrans, error) { var doc ClientPayTrans table := orm.ShMysql.Table(m.TableName()) table = table.Where("status = ? and account_status = ?", m.Status, m.AccountStatus) if err := table.Select("*").First(&doc).Error; err != nil { return doc, err } return doc, nil } func (m *ClientPayTrans) UpdateById(data map[string]interface{}) error { err := orm.ShMysql.Table(m.TableName()).Where("id = ?", m.ID).Updates(data).Error if err != nil { return err } return nil } func (m *ClientPayTrans) GetPayTransSuccessByOpenID(pageSize int, pageIndex int) ([]ClientPayTrans, int, error) { var doc []ClientPayTrans table := orm.ShMysql.Table(m.TableName()) //if m.ActivityStartTime != 0 table = table.Where("client_open_id = ? and status = 2", m.ClientOpenID) var count int if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil { return nil, 0, err } table.Count(&count) return doc, count, nil } func (m *ClientPayTrans) GetPayTransSuccessByMerchantID(pageSize int, pageIndex int, merchantId []int64) ([]ClientPayTrans, int, error) { var doc []ClientPayTrans table := orm.ShMysql.Table(m.TableName()) table = table.Where("merchant_card_id in (?) and status = 2", merchantId) var count int if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil { return nil, 0, err } table.Count(&count) return doc, count, nil } func (m *ClientPayTrans) SettleAdd(merchantAmount, clientAmount decimal.Decimal, merchantOpenId, clientOpenId string, payTransId int64) error { // 使用事务 添加 var err error var clientAccount MerchantClientAccount var merchantAccount MerchantAccount var amountPreMerchant decimal.Decimal var amountPreClient decimal.Decimal tx := orm.ShMysql.Begin() defer func() { if err != nil { tx.Rollback() } else { tx.Commit() } }() //查看是否有账号,没有创建 err = tx.Table("merchant_account").Select("*").Where("merchant_open_id = ?", merchantOpenId).Find(&merchantAccount).Error if err != nil && err.Error() != "record not found" { return err } if merchantAccount.ID == 0 { merchantAccount.MerchantOpenID = merchantOpenId merchantAccount.Version = 1 merchantAccount.UpdatedAt = time.Now() merchantAccount.CreatedAt = time.Now() err = tx.Table("merchant_account").Create(&merchantAccount).Error if err != nil { return err } } amountPreMerchant = merchantAccount.Amount if clientOpenId != "" { //原始码不抽佣金 err = tx.Table("merchant_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error if err != nil && err.Error() != "record not found" { return err } if clientAccount.ID == 0 { clientAccount.ClientOpenID = clientOpenId clientAccount.Version = 1 clientAccount.UpdatedAt = time.Now() clientAccount.CreatedAt = time.Now() err = tx.Table("merchant_client_account").Create(&clientAccount).Error if err != nil { return err } } amountPreClient = clientAccount.Amount clientAmountAdd := clientAccount.Amount.Add(clientAmount) result := tx.Table("merchant_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates( map[string]interface{}{ "amount": clientAmountAdd, "version": clientAccount.Version + 1, "updated_at": time.Now()}) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { err = errors.New("rows is zero") return err } var clientAccountLog MerchantClientAccountLog clientAccountLog.ClientOpenID = clientOpenId clientAccountLog.UpdatedAt = time.Now() clientAccountLog.AmountPre = amountPreClient clientAccountLog.AmountAfter = clientAmountAdd clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount clientAccountLog.Amount = clientAmount clientAccountLog.PayTransId = payTransId err = tx.Table("merchant_client_account_log").Create(&clientAccountLog).Error if err != nil { return err } } //做金额加减操作并且入日志库 merchantAmountAdd := merchantAccount.Amount.Add(merchantAmount) result := tx.Table("merchant_account").Model(&merchantAccount).Where("merchant_open_id = ? and version = ?", merchantOpenId, merchantAccount.Version).Updates( map[string]interface{}{ "amount": merchantAmountAdd, "version": merchantAccount.Version + 1, "updated_at": time.Now()}) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { err = errors.New("rows is zero") return err } var merchantAccountLog MerchantAccountLog fmt.Println("amountPreMerchant = ", amountPreMerchant) fmt.Println("merchantAccount.Amount = ", merchantAccount.Amount) merchantAccountLog.MerchantOpenID = merchantOpenId merchantAccountLog.UpdatedAt = time.Now() merchantAccountLog.AmountPre = amountPreMerchant merchantAccountLog.AmountAfter = merchantAmountAdd merchantAccountLog.ReviewAmountAfter = merchantAccount.ReviewAmount merchantAccountLog.ReviewAmountPre = merchantAccount.ReviewAmount merchantAccountLog.Amount = merchantAmount merchantAccountLog.PayTransId = payTransId err = tx.Table("merchant_account_log").Create(&merchantAccountLog).Error if err != nil { return err } return nil } func (m *ClientPayTrans) SettleAddCashOutFee(amount decimal.Decimal, clientOpenId string, cashOutId int64) error { // 使用事务 添加 var err error var clientAccount MerchantClientAccount var amountPreClient decimal.Decimal tx := orm.ShMysql.Begin() defer func() { if err != nil { tx.Rollback() } else { tx.Commit() } }() err = tx.Table("merchant_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error if err != nil && err.Error() != "record not found" { return err } if clientAccount.ID == 0 { clientAccount.ClientOpenID = clientOpenId clientAccount.Version = 1 clientAccount.UpdatedAt = time.Now() clientAccount.CreatedAt = time.Now() err = tx.Table("merchant_client_account").Create(&clientAccount).Error if err != nil { return err } } amountPreClient = clientAccount.Amount clientAmountAdd := clientAccount.Amount.Add(amount) result := tx.Table("merchant_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates( map[string]interface{}{ "amount": clientAmountAdd, "version": clientAccount.Version + 1, "updated_at": time.Now()}) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { err = errors.New("rows is zero") return err } var clientAccountLog MerchantClientAccountLog clientAccountLog.ClientOpenID = clientOpenId clientAccountLog.UpdatedAt = time.Now() clientAccountLog.AmountPre = amountPreClient clientAccountLog.AmountAfter = clientAmountAdd clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount clientAccountLog.Amount = amount clientAccountLog.PayTransId = cashOutId clientAccountLog.TransType = 3 //服务费 err = tx.Table("merchant_client_account_log").Create(&clientAccountLog).Error if err != nil { return err } return nil } func (m *ClientPayTrans) SettleSubClient(clientAmount decimal.Decimal, clientOpenId string, cashOutId int64) error { // 使用事务 添加 var err error var clientAccount MerchantClientAccount var cashOut CashOut var amountPreClient decimal.Decimal tx := orm.ShMysql.Begin() defer func() { if err != nil { tx.Rollback() } else { tx.Commit() } }() err = tx.Table("merchant_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error if err != nil { return err } amountPreClient = clientAccount.Amount if clientAccount.Amount.Cmp(clientAmount) < 0 { err = errors.New("账户金额不够") return err } clientAmountSub := clientAccount.Amount.Sub(clientAmount) result := tx.Table("merchant_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates( map[string]interface{}{ "amount": clientAmountSub, "version": clientAccount.Version + 1, "updated_at": time.Now()}) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { err = errors.New("rows is zero") return err } var clientAccountLog MerchantClientAccountLog clientAccountLog.ClientOpenID = clientOpenId clientAccountLog.UpdatedAt = time.Now() clientAccountLog.AmountPre = amountPreClient clientAccountLog.AmountAfter = clientAmountSub clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount clientAccountLog.Amount = clientAmount clientAccountLog.PayTransId = cashOutId clientAccountLog.TransType = 2 err = tx.Table("merchant_client_account_log").Create(&clientAccountLog).Error if err != nil { return err } result = tx.Table("cash_out").Model(&cashOut).Where("id = ? ", cashOutId).Updates( map[string]interface{}{ "status": 99, //体现成功 "account_status": 99, //分账成功 "updated_at": time.Now()}) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { err = errors.New("rows is zero") return err } return nil } func (m *ClientPayTrans) SettleSubMerchant(merchantAmount decimal.Decimal, merchantOpenId string, cashOutId int64) error { // 使用事务 添加 var err error var merchantAccount MerchantAccount var cashOut CashOut var amountPreMerchant decimal.Decimal tx := orm.ShMysql.Begin() defer func() { if err != nil { tx.Rollback() } else { tx.Commit() } }() err = tx.Table("merchant_account").Select("*").Where("merchant_open_id = ?", merchantOpenId).Find(&merchantAccount).Error if err != nil { return err } amountPreMerchant = merchantAccount.Amount if merchantAccount.Amount.Cmp(merchantAmount) < 0 { err = errors.New("账户金额不够") return err } merchantAmountSub := merchantAccount.Amount.Sub(merchantAmount) result := tx.Table("merchant_account").Model(&merchantAccount).Where("merchant_open_id = ? and version = ?", merchantOpenId, merchantAccount.Version).Updates( map[string]interface{}{ "amount": merchantAmountSub, "version": merchantAccount.Version + 1, "updated_at": time.Now()}) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { err = errors.New("rows is zero") return err } var merchantAccountLog MerchantAccountLog merchantAccountLog.MerchantOpenID = merchantOpenId merchantAccountLog.UpdatedAt = time.Now() merchantAccountLog.AmountPre = amountPreMerchant merchantAccountLog.AmountAfter = merchantAmountSub merchantAccountLog.ReviewAmountAfter = merchantAccount.ReviewAmount merchantAccountLog.ReviewAmountPre = merchantAccount.ReviewAmount merchantAccountLog.Amount = merchantAmount merchantAccountLog.PayTransId = cashOutId merchantAccountLog.TransType = 2 err = tx.Table("merchant_account_log").Create(&merchantAccountLog).Error if err != nil { return err } result = tx.Table("cash_out").Model(&cashOut).Where("id = ? ", cashOutId).Updates( map[string]interface{}{ "status": 99, //体现成功 "account_status": 99, //分账成功 "updated_at": time.Now()}) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { err = errors.New("rows is zero") return err } return nil }