Files
platforms/backend/api/internal/logic/common/recharge_query.go
czl231 3ef33b531d 已完成用户APP首期功能开发
交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
2026-09-13 00:57:32 +08:00

101 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 功能描述本人充值结果查询、记录分页与请求冲突错误版本1.0.0。
package common
import (
"strconv"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/infra"
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
var ErrRechargeRequestConflict = errcode.NewError(2411, "充值请求已存在,请保持原金额和支付方式")
// rechargePublic 只投影本人查看所需字段,不暴露钱包主键、渠道密钥和原始支付参数。
func rechargePublic(order models.WalletRechargeOrder) gin.H {
return gin.H{"identity": order.Identity, "recharge_no": order.RechargeNo,
"recharge_status": order.RechargeStatus, "amount": order.Amount, "channel": order.Channel,
"created_at": order.CreatedAt, "completed_at": order.CompletedAt}
}
// GetRecharge 以本地已验签回调的入账事实确认结果;支付渠道已付与钱包已入账分别返回。
func GetRecharge(client string) gin.HandlerFunc {
return func(ctx *gin.Context) {
owner, ok := currentOwner(ctx, client)
if !ok {
return
}
var order models.WalletRechargeOrder
query := impl.DBService.Where("owner_type = ? AND owner_identity = ?", owner.Type, owner.Identity)
if request := ctx.Param("request"); request != "" {
query = query.Where("request_no = ?", request)
} else {
query = query.Where("identity = ?", ctx.Param("identity"))
}
if err := query.First(&order).Error; err != nil {
if err == gorm.ErrRecordNotFound {
ctx.Status(404)
infra.Response.Error(ctx, errcode.ErrRecordNotFound)
} else {
infra.Response.Error(ctx, err)
}
return
}
response := rechargePublic(order)
var paymentOrder models.PaymentOrder
err := impl.DBService.Where("business_type = ? AND business_identity = ? AND user_identity = ?", "recharge", order.Identity, owner.Identity).
Order("id desc").First(&paymentOrder).Error
if err != nil && err != gorm.ErrRecordNotFound {
infra.Response.Error(ctx, err)
return
}
// 缺少支付单不推断为支付成功或失败,前端应保留待确认状态。
if err == nil {
response["payment_status"] = paymentOrder.PaymentStatus
response["expires_at"] = paymentOrder.ExpiresAt
}
infra.Response.Success(ctx, response)
}
}
// ListRecharges 每次至多50条主体类型和标识双重过滤游标只影响本人范围。
func ListRecharges(client string) gin.HandlerFunc {
return func(ctx *gin.Context) {
var before uint64
if raw := ctx.Query("cursor"); raw != "" {
var err error
before, err = strconv.ParseUint(raw, 10, 64)
if err != nil || before == 0 {
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
return
}
}
owner, ok := currentOwner(ctx, client)
if !ok {
return
}
query := impl.DBService.Where("owner_type = ? AND owner_identity = ?", owner.Type, owner.Identity)
if before != 0 {
query = query.Where("id < ?", before)
}
var orders []models.WalletRechargeOrder
if err := query.Order("id desc").Limit(51).Find(&orders).Error; err != nil {
infra.Response.Error(ctx, err)
return
}
next := ""
if len(orders) > 50 {
orders = orders[:50]
next = strconv.FormatUint(orders[49].ID, 10)
}
items := make([]gin.H, 0, len(orders))
for _, order := range orders {
items = append(items, rechargePublic(order))
}
infra.Response.Success(ctx, gin.H{"items": items, "next_cursor": next})
}
}