fix platform authorization and workflow integrity
This commit is contained in:
@@ -25,25 +25,46 @@ var walletOwnerModels = map[string]any{
|
||||
"gas": &models.GasBasic{},
|
||||
}
|
||||
|
||||
func ListWalletBasic(ctx *gin.Context) { listWalletPage[models.WalletBasic](ctx) }
|
||||
func ListWalletBasic(ctx *gin.Context) {
|
||||
ownerType := strings.TrimSpace(ctx.Query("owner_type"))
|
||||
if ownerType != "" && ownerType != "user" && ownerType != "staff" && ownerType != "delivery" && ownerType != "gas" && ownerType != "platform" {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
ownerIdentities := strings.Split(strings.TrimSpace(ctx.Query("owner_identities")), ",")
|
||||
if len(ownerIdentities) == 1 && ownerIdentities[0] == "" {
|
||||
ownerIdentities = nil
|
||||
}
|
||||
if len(ownerIdentities) > 100 {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
listWalletPage[models.WalletBasic](ctx, ownerType, ownerIdentities)
|
||||
}
|
||||
func GetWalletBasic(ctx *gin.Context) { getWalletByIdentity[models.WalletBasic](ctx) }
|
||||
func ListWalletBank(ctx *gin.Context) { listWalletPage[models.WalletBank](ctx) }
|
||||
func ListWalletBank(ctx *gin.Context) { listWalletPage[models.WalletBank](ctx, "", nil) }
|
||||
func GetWalletBank(ctx *gin.Context) { getWalletByIdentity[models.WalletBank](ctx) }
|
||||
func ListWalletPayment(ctx *gin.Context) { listWalletPage[models.WalletPayment](ctx) }
|
||||
func ListWalletPayment(ctx *gin.Context) { listWalletPage[models.WalletPayment](ctx, "", nil) }
|
||||
func GetWalletPayment(ctx *gin.Context) { getWalletByIdentity[models.WalletPayment](ctx) }
|
||||
func ListWalletRecord(ctx *gin.Context) { listWalletPage[models.WalletRecord](ctx) }
|
||||
func ListWalletRecord(ctx *gin.Context) { listWalletPage[models.WalletRecord](ctx, "", nil) }
|
||||
func GetWalletRecord(ctx *gin.Context) { getWalletByIdentity[models.WalletRecord](ctx) }
|
||||
func ListWalletRefund(ctx *gin.Context) { listWalletPage[models.WalletRefund](ctx) }
|
||||
func ListWalletRefund(ctx *gin.Context) { listWalletPage[models.WalletRefund](ctx, "", nil) }
|
||||
func GetWalletRefund(ctx *gin.Context) { getWalletByIdentity[models.WalletRefund](ctx) }
|
||||
func ListWalletApplyCash(ctx *gin.Context) { listWalletPage[models.WalletApplyCash](ctx) }
|
||||
func ListWalletApplyCash(ctx *gin.Context) { listWalletPage[models.WalletApplyCash](ctx, "", nil) }
|
||||
func GetWalletApplyCash(ctx *gin.Context) { getWalletByIdentity[models.WalletApplyCash](ctx) }
|
||||
|
||||
func listWalletPage[T any](ctx *gin.Context) {
|
||||
func listWalletPage[T any](ctx *gin.Context, ownerType string, ownerIdentities []string) {
|
||||
page, size := common.PageSize(ctx)
|
||||
var list []T
|
||||
var total int64
|
||||
model := new(T)
|
||||
query := common.ApplyKeywordFilter(ctx, common.ActiveRecords(impl.DBService.Model(model)), model)
|
||||
if ownerType != "" {
|
||||
query = query.Where("owner_type = ?", ownerType)
|
||||
}
|
||||
if len(ownerIdentities) > 0 {
|
||||
query = query.Where("owner_identity IN ?", ownerIdentities)
|
||||
}
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
@@ -63,7 +84,7 @@ func listWalletPage[T any](ctx *gin.Context) {
|
||||
|
||||
func getWalletByIdentity[T any](ctx *gin.Context) {
|
||||
var data T
|
||||
if err := impl.DBService.Where("identity = ?", ctx.Param("identity")).First(&data).Error; err != nil {
|
||||
if err := common.ActiveRecords(impl.DBService).Where("identity = ?", ctx.Param("identity")).First(&data).Error; err != nil {
|
||||
common.RespondRecordError(ctx, err)
|
||||
return
|
||||
}
|
||||
@@ -268,9 +289,6 @@ func RejectWalletApplyCash(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
func reviewWalletApplyCash(ctx *gin.Context, targetStatus int) {
|
||||
if !common.RequirePlatformRoot(ctx) {
|
||||
return
|
||||
}
|
||||
var request struct {
|
||||
Reason string `json:"reason" binding:"required,max=2000"`
|
||||
}
|
||||
@@ -282,7 +300,7 @@ func reviewWalletApplyCash(ctx *gin.Context, targetStatus int) {
|
||||
err := impl.DBService.Transaction(func(tx *gorm.DB) error {
|
||||
var application models.WalletApplyCash
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("identity = ?", ctx.Param("identity")).First(&application).Error; err != nil {
|
||||
Where("identity = ? AND status = ?", ctx.Param("identity"), common.StatusEnable).First(&application).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if application.ApplyStatus == targetStatus {
|
||||
@@ -315,6 +333,45 @@ func reviewWalletApplyCash(ctx *gin.Context, targetStatus int) {
|
||||
infra.Response.Success(ctx, gin.H{"updated": true, "apply_status": targetStatus})
|
||||
}
|
||||
|
||||
// CompleteWalletApplyCash records the external payout result after approval.
|
||||
func CompleteWalletApplyCash(ctx *gin.Context) {
|
||||
var request struct {
|
||||
TradeNo string `json:"trade_no" binding:"required,max=128"`
|
||||
CallbackMsg string `json:"callback_msg" binding:"max=4000"`
|
||||
}
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil || strings.TrimSpace(request.TradeNo) == "" {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
err := impl.DBService.Transaction(func(tx *gorm.DB) error {
|
||||
var application models.WalletApplyCash
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("identity = ? AND status = ?", ctx.Param("identity"), common.StatusEnable).
|
||||
First(&application).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if application.ApplyStatus == common.StatusCompleted {
|
||||
if application.TradeNo == request.TradeNo {
|
||||
return nil
|
||||
}
|
||||
return errors.New("cash application already completed")
|
||||
}
|
||||
if application.ApplyStatus != common.StatusApproved {
|
||||
return errors.New("cash application is not approved")
|
||||
}
|
||||
now := time.Now()
|
||||
return tx.Model(&application).Updates(map[string]any{
|
||||
"apply_status": common.StatusCompleted, "trade_no": strings.TrimSpace(request.TradeNo),
|
||||
"callback_msg": request.CallbackMsg, "completed_at": &now,
|
||||
}).Error
|
||||
})
|
||||
if err != nil {
|
||||
common.RespondRecordError(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, gin.H{"updated": true, "apply_status": common.StatusCompleted})
|
||||
}
|
||||
|
||||
func dateNumber(value time.Time, layout string) int32 {
|
||||
number, _ := strconv.ParseInt(value.Format(layout), 10, 32)
|
||||
return int32(number)
|
||||
|
||||
Reference in New Issue
Block a user