feat(jd-cookie): 引入用户订单号支持并重构订单创建逻辑

- 新增用户订单号字段以区分内部订单号
- 修改订单表结构添加 user_order_id 字段及索引
- 更新 CreateOrder 接口支持用户订单号参数-重构 CreateOrder 和 GetPaymentUrl 方法返回统一结果对象
- 新增模型定义用于封装订单创建与支付结果
- 调整相关逻辑方法签名与调用方式适配新结构- 优化订单创建流程增加内部订单号生成逻辑
- 完善订单查询逻辑确保正确关联用户订单号- 更新控制器层对接新版服务接口- 升级 Cookie 状态及订单状态管理枚举类型使用
This commit is contained in:
danial
2025-10-13 15:00:11 +08:00
parent 5b059bdb84
commit f358aa0745
13 changed files with 254 additions and 148 deletions

View File

@@ -28,16 +28,17 @@ type JdCookieOrderApi struct {
// CreateOrderReq Create Order Request
type CreateOrderReq struct {
g.Meta `path:"/jd-cookie/order/create" method:"post" summary:"Create Order" tags:"JD Order Management"`
OrderId string `json:"orderId" v:"required#订单号不能为空" dc:"订单号"`
Amount float64 `json:"amount" v:"required|min:0.01#订单金额不能为空|订单金额必须大于0" dc:"订单金额"`
Category consts.RedeemOrderCardCategory `json:"category" v:"required#商品品类不能为空" dc:"商品品类"`
g.Meta `path:"/jd-cookie/order/create" method:"post" summary:"Create Order" tags:"JD Order Management"`
UserOrderId string `json:"userOrderId" v:"required#用户订单号不能为空" dc:"用户订单号"`
Amount float64 `json:"amount" v:"required|min:0.01#订单金额不能为空|订单金额必须大于0" dc:"订单金额"`
Category consts.RedeemOrderCardCategory `json:"category" v:"required#商品品类不能为空" dc:"商品品类"`
}
type CreateOrderRes struct {
g.Meta `mime:"application/json"`
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
OrderId string `json:"orderId" dc:"内部订单号"`
}
// GetPaymentUrlReq Get Payment URL Request
@@ -47,8 +48,10 @@ type GetPaymentUrlReq struct {
}
type GetPaymentUrlRes struct {
g.Meta `mime:"application/json"`
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
g.Meta `mime:"application/json"`
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
OrderId string `json:"orderId" dc:"内部订单号"`
}
// GetOrderStatusReq Query Order Status Request
@@ -96,14 +99,24 @@ type OrderInfo struct {
}
type JdOrderInfo struct {
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
OrderId string `json:"orderId" dc:"关联的内部订单号"`
Amount float64 `json:"amount" dc:"订单金额"`
Category string `json:"category" dc:"商品品类"`
Status consts.JdOrderStatus `json:"status" dc:"状态1待支付 2已支付 3已过期 4已取消"`
PaidAt string `json:"paidAt" dc:"支付时间"`
CreatedAt string `json:"createdAt" dc:"创建时间"`
UpdatedAt string `json:"updatedAt" dc:"更新时间"`
Id int64 `json:"id" dc:"主键ID"`
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
PayId string `json:"payId" dc:"支付ID"`
Amount float64 `json:"amount" dc:"订单金额"`
Category string `json:"category" dc:"商品品类"`
CookieId string `json:"cookieId" dc:"使用的Cookie ID"`
Status consts.JdOrderStatus `json:"status" dc:"状态1待支付 2已支付 3已过期 4已取消"`
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
WxPayExpireAt *string `json:"wxPayExpireAt" dc:"微信支付链接过期时间"`
OrderExpireAt *string `json:"orderExpireAt" dc:"订单过期时间(默认24小时)"`
CurrentOrderId int64 `json:"currentOrderId" dc:"当前关联的订单ID"`
PaidAt *string `json:"paidAt" dc:"支付完成时间"`
CardNo string `json:"cardNo" dc:"卡号"`
CardPassword string `json:"cardPassword" dc:"卡密"`
CardExtractedAt *string `json:"cardExtractedAt" dc:"卡密提取时间"`
CreatedAt *string `json:"createdAt" dc:"创建时间"`
UpdatedAt *string `json:"updatedAt" dc:"更新时间"`
DeletedAt *string `json:"deletedAt" dc:"删除时间"`
}
// ListOrderReq Order List Query Request

View File

@@ -11,14 +11,15 @@ import (
// CreateOrder 创建订单
func (c *ControllerV1) CreateOrder(ctx context.Context, req *v1.CreateOrderReq) (res *v1.CreateOrderRes, err error) {
wxPayUrl, jdOrderId, err := service.JdCookie().CreateOrder(ctx, req.OrderId, req.Amount, req.Category)
result, err := service.JdCookie().CreateOrder(ctx, req.UserOrderId, req.Amount, req.Category)
if err != nil {
return nil, gerror.WrapCode(gcode.CodeInternalError, err, "创建订单失败")
}
res = &v1.CreateOrderRes{
WxPayUrl: wxPayUrl,
JdOrderId: jdOrderId,
WxPayUrl: result.WxPayUrl,
JdOrderId: result.JdOrderId,
OrderId: result.OrderId,
}
return
}

View File

@@ -18,13 +18,15 @@ func (c *ControllerV1) GetPaymentUrl(ctx context.Context, req *v1.GetPaymentUrlR
return
}
wxPayUrl, _, err := service.JdCookie().GetPaymentUrl(ctx, req.OrderId)
result, err := service.JdCookie().GetPaymentUrl(ctx, req.OrderId)
if err != nil {
return nil, gerror.WrapCode(gcode.CodeInternalError, err, "获取支付链接失败")
}
res = &v1.GetPaymentUrlRes{
WxPayUrl: wxPayUrl,
WxPayUrl: result.WxPayUrl,
JdOrderId: result.JdOrderId,
OrderId: result.OrderId,
}
return
}

View File

@@ -23,6 +23,7 @@ type V1JdCookieOrderDao struct {
type V1JdCookieOrderColumns struct {
Id string // 主键ID
OrderId string // 订单号
UserOrderId string // 用户订单号
Amount string // 订单金额
Category string // 商品品类
JdOrderId string // 关联的京东订单号
@@ -38,6 +39,7 @@ type V1JdCookieOrderColumns struct {
var v1JdCookieOrderColumns = V1JdCookieOrderColumns{
Id: "id",
OrderId: "order_id",
UserOrderId: "user_order_id",
Amount: "amount",
Category: "category",
JdOrderId: "jd_order_id",

View File

@@ -3,116 +3,142 @@ package jd_cookie
import (
"context"
"kami/internal/consts"
"kami/internal/model"
"kami/utility/utils"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime"
)
// CreateOrder 创建订单
func (s *sJdCookie) CreateOrder(ctx context.Context, orderId string, amount float64, category consts.RedeemOrderCardCategory) (wxPayUrl, jdOrderId string, err error) {
func (s *sJdCookie) CreateOrder(ctx context.Context, userOrderId string, amount float64, category consts.RedeemOrderCardCategory) (result *model.CreateOrderResult, err error) {
_ = s.ReleaseExpiredJdOrders(ctx)
if orderId == "" {
return "", "", gerror.New("订单号不能为空")
if userOrderId == "" {
return nil, gerror.New("用户订单号不能为空")
}
if amount <= 0 {
return "", "", gerror.New("订单金额必须大于0")
return nil, gerror.New("订单金额必须大于0")
}
// 检查订单是否已存在
existingOrder, err := s.getOrderByOrderId(ctx, orderId)
// 检查用户订单是否已存在
existingOrder, err := s.getOrderByUserOrderId(ctx, userOrderId)
if err != nil {
return "", "", gerror.Wrap(err, "检查订单是否存在失败")
return nil, gerror.Wrap(err, "检查用户订单是否存在失败")
}
//
if existingOrder != nil {
// 订单已存在,尝试获取支付链接
return s.GetPaymentUrl(ctx, orderId)
}
//
//// 优先尝试复用现有的京东订单
//reusableJdOrder, err := s.findReusableJdOrder(ctx, amount, category)
//if err != nil {
// glog.Warning(ctx, "查找可复用京东订单失败", err)
//}
//
var cookieId string
//var isReused bool = false
//
//if reusableJdOrder != nil {
// // 尝试使用可复用的京东订单
// jdOrderId = reusableJdOrder.JdOrderId
// cookieId = reusableJdOrder.CookieId
// wxPayUrl = reusableJdOrder.WxPayUrl
//
// // 检查支付链接是否过期
// if reusableJdOrder.WxPayExpireAt != nil && gtime.Now().After(reusableJdOrder.WxPayExpireAt) {
// // 支付链接已过期,尝试刷新
// newWxPayUrl, refreshErr := s.refreshPaymentUrl(ctx, jdOrderId, reusableJdOrder.PayId, cookieId, orderId)
// if refreshErr != nil {
// glog.Warning(ctx, "刷新支付链接失败,将创建新订单", g.Map{
// "jdOrderId": jdOrderId,
// "error": refreshErr,
// })
// // 刷新失败,标记为不可复用
// _ = s.UpdateJdOrderStatus(ctx, jdOrderId, int(consts.JdOrderStatusExpired), "刷新支付链接失败")
// _ = s.RecordJdOrderHistory(ctx, jdOrderId, string(consts.JdOrderChangeTypeInvalid), "", reusableJdOrder.WxPayUrl)
//
// // 记录Cookie刷新失败历史
// _ = s.RecordCookieHistory(ctx, cookieId, string(consts.CookieChangeTypeRefreshFail), 0, 0, orderId, 0)
//
// // 清空,准备创建新订单
// jdOrderId = ""
// cookieId = ""
// wxPayUrl = ""
// } else {
// wxPayUrl = newWxPayUrl
// // 更新京东订单的支付链接和过期时间
// _ = s.updateJdOrderPaymentUrl(ctx, jdOrderId, wxPayUrl)
// isReused = true
// }
// } else {
// isReused = true
// }
//
// if isReused {
// glog.Info(ctx, "复用现有京东订单", g.Map{
// "orderId": orderId,
// "jdOrderId": jdOrderId,
// "cookieId": cookieId,
// })
// }
//}
//
// 如果没有成功复用,创建新的京东订单
if jdOrderId == "" {
jdOrderId, cookieId, wxPayUrl, err = s.createNewJdOrderWithRetry(ctx, orderId, amount, category)
paymentResult, err := s.GetPaymentUrl(ctx, existingOrder.OrderId)
if err != nil {
return "", "", err
return nil, err
}
// 转换为CreateOrderResult
return &model.CreateOrderResult{
WxPayUrl: paymentResult.WxPayUrl,
JdOrderId: paymentResult.JdOrderId,
OrderId: paymentResult.OrderId,
}, nil
}
// 优先尝试复用现有的京东订单
reusableJdOrder, err := s.findReusableJdOrder(ctx, amount, category)
if err != nil {
glog.Warning(ctx, "查找可复用京东订单失败", err)
}
// 生成内部订单ID
internalOrderId := "JD_" + utils.GenerateRandomUUID()
var cookieId, jdOrderId, wxPayUrl string
var isReused = false
if reusableJdOrder != nil {
// 尝试使用可复用的京东订单
jdOrderId = reusableJdOrder.JdOrderId
cookieId = reusableJdOrder.CookieId
wxPayUrl = reusableJdOrder.WxPayUrl
// 检查支付链接是否过期
if reusableJdOrder.WxPayExpireAt != nil && gtime.Now().After(reusableJdOrder.WxPayExpireAt) {
// 支付链接已过期,尝试刷新
newWxPayUrl, refreshErr := s.refreshPaymentUrl(ctx, jdOrderId, reusableJdOrder.PayId, cookieId, internalOrderId)
if refreshErr != nil {
glog.Warning(ctx, "刷新支付链接失败,将创建新订单", g.Map{
"jdOrderId": jdOrderId,
"error": refreshErr,
})
// 刷新失败,标记为不可复用
_ = s.UpdateJdOrderStatus(ctx, jdOrderId, consts.JdOrderStatusExpired, "刷新支付链接失败")
_ = s.RecordJdOrderHistory(ctx, jdOrderId, consts.JdOrderChangeTypeInvalid, "", reusableJdOrder.WxPayUrl)
// 记录Cookie刷新失败历史
_ = s.RecordCookieHistory(ctx, cookieId, consts.CookieChangeTypeRefreshFail, 0, 0, internalOrderId, 0)
// 清空,准备创建新订单
jdOrderId = ""
cookieId = ""
wxPayUrl = ""
} else {
wxPayUrl = newWxPayUrl
// 更新京东订单的支付链接和过期时间
_ = s.updateJdOrderPaymentUrl(ctx, jdOrderId, wxPayUrl)
isReused = true
}
} else {
isReused = true
}
if isReused {
glog.Info(ctx, "复用现有京东订单", g.Map{
"orderId": internalOrderId,
"jdOrderId": jdOrderId,
"cookieId": cookieId,
})
}
}
// 如果没有成功复用,创建新的京东订单
if jdOrderId == "" {
retryRes, err := s.createNewJdOrderWithRetry(ctx, &model.CreateNewJdOrderWithRetryReq{
OrderId: internalOrderId,
Amount: amount,
Category: category,
})
if err != nil {
return nil, err
}
jdOrderId = retryRes.JdOrderId
cookieId = retryRes.CookieId
wxPayUrl = retryRes.WxPayUrl
}
// 创建订单记录
err = s.createOrderRecord(ctx, orderId, amount, category, jdOrderId, wxPayUrl)
err = s.createOrderRecord(ctx, internalOrderId, userOrderId, amount, category, jdOrderId, wxPayUrl)
if err != nil {
return "", "", gerror.Wrap(err, "创建订单记录失败")
return nil, gerror.Wrap(err, "创建订单记录失败")
}
// 更新京东订单的当前关联订单ID
_ = s.updateJdOrderCurrentOrderId(ctx, jdOrderId, orderId)
_ = s.updateJdOrderCurrentOrderId(ctx, jdOrderId, internalOrderId)
// 记录Cookie使用历史
_ = s.RecordCookieHistory(ctx, cookieId, consts.CookieChangeTypeUse, 0, 0, orderId, 0)
_ = s.RecordCookieHistory(ctx, cookieId, consts.CookieChangeTypeUse, 0, 0, internalOrderId, 0)
// 记录订单创建历史
_ = s.RecordOrderHistory(ctx, orderId, consts.OrderChangeTypeCreate, jdOrderId)
_ = s.RecordOrderHistory(ctx, internalOrderId, consts.OrderChangeTypeCreate, jdOrderId)
return wxPayUrl, jdOrderId, nil
return &model.CreateOrderResult{
WxPayUrl: wxPayUrl,
JdOrderId: jdOrderId,
OrderId: internalOrderId,
}, nil
}
// createNewJdOrderWithRetry 创建新的京东订单(带重试机制)
func (s *sJdCookie) createNewJdOrderWithRetry(ctx context.Context, orderId string, amount float64, category consts.RedeemOrderCardCategory) (jdOrderId, cookieId, wxPayUrl string, err error) {
func (s *sJdCookie) createNewJdOrderWithRetry(ctx context.Context, req *model.CreateNewJdOrderWithRetryReq) (res *model.CreateNewJdOrderWithRetryRes, err error) {
var lastErr error
var triedCookies []string // 记录已尝试的Cookie
@@ -122,7 +148,7 @@ func (s *sJdCookie) createNewJdOrderWithRetry(ctx context.Context, orderId strin
availableCookieId, cookieErr := s.GetAvailableCookie(ctx)
if cookieErr != nil {
glog.Warning(ctx, "获取可用Cookie失败", g.Map{
"orderId": orderId,
"orderId": req.OrderId,
"triedCookies": len(triedCookies),
"error": cookieErr,
})
@@ -143,44 +169,48 @@ func (s *sJdCookie) createNewJdOrderWithRetry(ctx context.Context, orderId strin
// 调用京东下单接口
var payId string
jdOrderId, payId, wxPayUrl, lastErr = s.callJdCreateOrder(ctx, availableCookieId, amount, category)
jdOrderId, payId, wxPayUrl, lastErr := s.callJdCreateOrder(ctx, availableCookieId, req.Amount, req.Category)
if lastErr != nil {
glog.Warning(ctx, "京东下单失败尝试切换Cookie重试", g.Map{
"orderId": orderId,
"orderId": req.OrderId,
"cookieId": availableCookieId,
"triedCookies": len(triedCookies),
"error": lastErr,
})
// Cookie失败更新状态
s.handleCookieFailure(ctx, availableCookieId, orderId)
s.handleCookieFailure(ctx, availableCookieId, req.OrderId)
// 继续下一次重试
continue
}
// 下单成功,创建京东订单记录
err = s.createJdOrderRecord(ctx, jdOrderId, payId, availableCookieId, category, amount, wxPayUrl)
err = s.createJdOrderRecord(ctx, jdOrderId, payId, availableCookieId, req.Category, req.Amount, wxPayUrl)
if err != nil {
glog.Error(ctx, "创建京东订单记录失败", g.Map{
"jdOrderId": jdOrderId,
"error": err,
})
return "", "", "", gerror.Wrap(err, "创建京东订单记录失败")
return nil, gerror.Wrap(err, "创建京东订单记录失败")
}
// 记录京东订单创建历史
_ = s.RecordJdOrderHistory(ctx, jdOrderId, consts.JdOrderChangeTypeCreate, orderId, wxPayUrl)
_ = s.RecordJdOrderHistory(ctx, jdOrderId, consts.JdOrderChangeTypeCreate, req.OrderId, wxPayUrl)
glog.Info(ctx, "创建京东订单成功", g.Map{
"orderId": orderId,
"orderId": req.OrderId,
"jdOrderId": jdOrderId,
"cookieId": availableCookieId,
"triedCookies": len(triedCookies),
})
// 返回成功结果
return jdOrderId, availableCookieId, wxPayUrl, nil
return &model.CreateNewJdOrderWithRetryRes{
JdOrderId: jdOrderId,
CookieId: availableCookieId,
WxPayUrl: wxPayUrl,
}, nil
}
// 所有重试都失败了
@@ -189,12 +219,12 @@ func (s *sJdCookie) createNewJdOrderWithRetry(ctx context.Context, orderId strin
}
glog.Error(ctx, "创建京东订单失败所有Cookie均不可用", g.Map{
"orderId": orderId,
"orderId": req.OrderId,
"triedCookies": triedCookies,
"error": lastErr,
})
return "", "", "", gerror.Wrapf(lastErr, "创建京东订单失败,已尝试%d个Cookie", len(triedCookies))
return nil, gerror.Wrapf(lastErr, "创建京东订单失败,已尝试%d个Cookie", len(triedCookies))
}
// hasCookieBeenTried 检查Cookie是否已经尝试过

View File

@@ -5,6 +5,7 @@ import (
v1 "kami/api/jd_cookie/v1"
"kami/internal/consts"
"kami/internal/dao"
"kami/internal/model"
"kami/internal/model/entity"
"kami/utility/config"
@@ -14,31 +15,31 @@ import (
)
// GetPaymentUrl 获取支付链接
func (s *sJdCookie) GetPaymentUrl(ctx context.Context, orderId string) (wxPayUrl, jdOrderId string, err error) {
func (s *sJdCookie) GetPaymentUrl(ctx context.Context, orderId string) (result *model.PaymentResult, err error) {
if orderId == "" {
return "", "", gerror.New("订单号不能为空")
return nil, gerror.New("订单号不能为空")
}
// 获取订单信息
order, err := s.getOrderByOrderId(ctx, orderId)
if err != nil {
return "", "", gerror.Wrap(err, "查询订单失败")
return nil, gerror.Wrap(err, "查询订单失败")
}
if order == nil {
return "", "", gerror.New(consts.ErrCodeOrderNotFound)
return nil, gerror.New(consts.ErrCodeOrderNotFound)
}
// 获取关联的京东订单
jdOrder, err := s.getJdOrderByJdOrderId(ctx, order.JdOrderId)
if err != nil {
return "", "", gerror.Wrap(err, "查询京东订单失败")
return nil, gerror.Wrap(err, "查询京东订单失败")
}
if jdOrder == nil {
return "", "", gerror.New(consts.ErrCodeJdOrderNotFound)
return nil, gerror.New(consts.ErrCodeJdOrderNotFound)
}
jdOrderId = jdOrder.JdOrderId
wxPayUrl = jdOrder.WxPayUrl
jdOrderId := jdOrder.JdOrderId
wxPayUrl := jdOrder.WxPayUrl
// 检查支付链接是否有效
if jdOrder.WxPayExpireAt != nil && gtime.Now().After(jdOrder.WxPayExpireAt) {
@@ -46,7 +47,7 @@ func (s *sJdCookie) GetPaymentUrl(ctx context.Context, orderId string) (wxPayUrl
newWxPayUrl, refreshErr := s.refreshPaymentUrl(ctx, jdOrder.JdOrderId, jdOrder.PayId, jdOrder.CookieId, orderId)
if refreshErr != nil {
// 刷新失败,标记旧订单为失效
_ = s.UpdateJdOrderStatus(ctx, jdOrder.JdOrderId, int(consts.JdOrderStatusExpired), "刷新支付链接失败")
_ = s.UpdateJdOrderStatus(ctx, jdOrder.JdOrderId, consts.JdOrderStatusExpired, "刷新支付链接失败")
_ = s.RecordJdOrderHistory(ctx, jdOrder.JdOrderId, consts.JdOrderChangeTypeInvalid, orderId, jdOrder.WxPayUrl)
_ = s.RecordCookieHistory(ctx, jdOrder.CookieId, consts.CookieChangeTypeRefreshFail, 0, 0, orderId, 0)
@@ -54,26 +55,30 @@ func (s *sJdCookie) GetPaymentUrl(ctx context.Context, orderId string) (wxPayUrl
_ = s.updateJdOrderCurrentOrderId(ctx, jdOrder.JdOrderId, "")
// 创建新的京东订单(带重试机制)
newJdOrderId, newCookieId, newWxPayUrl, createErr := s.createNewJdOrderWithRetry(ctx, orderId, gconv.Float64(order.Amount), consts.RedeemOrderCardCategory(order.Category))
retryRes, createErr := s.createNewJdOrderWithRetry(ctx, &model.CreateNewJdOrderWithRetryReq{
OrderId: orderId,
Amount: gconv.Float64(order.Amount),
Category: consts.RedeemOrderCardCategory(order.Category),
})
if createErr != nil {
return "", "", gerror.Wrap(createErr, "刷新失败且创建新订单失败")
return nil, gerror.Wrap(createErr, "刷新失败且创建新订单失败")
}
// 更新订单关联的京东订单ID
_ = s.updateOrderJdOrderId(ctx, orderId, newJdOrderId, newWxPayUrl)
_ = s.updateOrderJdOrderId(ctx, orderId, retryRes.JdOrderId, retryRes.WxPayUrl)
// 更新京东订单的当前关联订单ID
_ = s.updateJdOrderCurrentOrderId(ctx, newJdOrderId, orderId)
_ = s.updateJdOrderCurrentOrderId(ctx, retryRes.JdOrderId, orderId)
// 记录Cookie使用历史
_ = s.RecordCookieHistory(ctx, newCookieId, consts.CookieChangeTypeUse, 0, 0, orderId, 0)
_ = s.RecordCookieHistory(ctx, retryRes.CookieId, consts.CookieChangeTypeUse, 0, 0, orderId, 0)
// 记录订单重新绑定历史
_ = s.RecordOrderHistory(ctx, orderId, consts.OrderChangeTypeRebind, newJdOrderId)
_ = s.RecordOrderHistory(ctx, orderId, consts.OrderChangeTypeRebind, retryRes.JdOrderId)
// 返回新的支付信息
jdOrderId = newJdOrderId
wxPayUrl = newWxPayUrl
jdOrderId = retryRes.JdOrderId
wxPayUrl = retryRes.WxPayUrl
} else {
// 刷新成功,更新支付链接
wxPayUrl = newWxPayUrl
@@ -84,7 +89,11 @@ func (s *sJdCookie) GetPaymentUrl(ctx context.Context, orderId string) (wxPayUrl
// 更新订单最后请求时间
_ = s.updateOrderLastRequest(ctx, orderId)
return wxPayUrl, jdOrderId, nil
return &model.PaymentResult{
WxPayUrl: wxPayUrl,
JdOrderId: jdOrderId,
OrderId: order.OrderId,
}, nil
}
// GetOrder 获取单个订单

View File

@@ -29,6 +29,14 @@ func (s *sJdCookie) getOrderByOrderId(ctx context.Context, orderId string) (orde
return
}
// getOrderByUserOrderId 根据用户订单号查询订单
func (s *sJdCookie) getOrderByUserOrderId(ctx context.Context, userOrderId string) (order *entity.V1JdCookieOrder, err error) {
m := dao.V1JdCookieOrder.Ctx(ctx).DB(config.GetDatabaseV1())
err = m.Where(dao.V1JdCookieOrder.Columns().UserOrderId, userOrderId).Scan(&order)
err = utils.HandleNoRowsError(err)
return
}
// getJdOrderByJdOrderId 根据京东订单号查询京东订单
func (s *sJdCookie) getJdOrderByJdOrderId(ctx context.Context, jdOrderId string) (jdOrder *entity.V1JdCookieJdOrder, err error) {
m := dao.V1JdCookieJdOrder.Ctx(ctx).DB(config.GetDatabaseV1())
@@ -65,15 +73,16 @@ func (s *sJdCookie) createJdOrderRecord(ctx context.Context, jdOrderId, payId, c
}
// createOrderRecord 创建订单记录
func (s *sJdCookie) createOrderRecord(ctx context.Context, orderId string, amount float64, category consts.RedeemOrderCardCategory, jdOrderId, wxPayUrl string) error {
func (s *sJdCookie) createOrderRecord(ctx context.Context, internalOrderId, userOrderId string, amount float64, category consts.RedeemOrderCardCategory, jdOrderId, wxPayUrl string) error {
m := dao.V1JdCookieOrder.Ctx(ctx).DB(config.GetDatabaseV1())
_, err := m.Insert(&do.V1JdCookieOrder{
OrderId: orderId,
Amount: amount,
Category: category,
JdOrderId: jdOrderId,
Status: int(consts.OrderStatusPending),
WxPayUrl: wxPayUrl,
OrderId: internalOrderId,
UserOrderId: userOrderId,
Amount: amount,
Category: category,
JdOrderId: jdOrderId,
Status: int(consts.OrderStatusPending),
WxPayUrl: wxPayUrl,
})
return err
}

View File

@@ -101,7 +101,7 @@ func (s *sJdCookie) unlockExpiredCookies(ctx context.Context) {
// ====================================================================================
// UpdateCookieStatus 更新Cookie状态
func (s *sJdCookie) UpdateCookieStatus(ctx context.Context, cookieId string, status int, failureCount int) (err error) {
func (s *sJdCookie) UpdateCookieStatus(ctx context.Context, cookieId string, status consts.JdCookieStatus, failureCount int) (err error) {
if cookieId == "" {
return gerror.New("Cookie ID不能为空")
}
@@ -119,17 +119,17 @@ func (s *sJdCookie) UpdateCookieStatus(ctx context.Context, cookieId string, sta
}
updateData := &do.V1JdCookieAccount{
Status: status,
Status: int(status),
FailureCount: failureCount,
}
// 如果是暂停状态,设置暂停时间
if status == int(consts.JdCookieStatusSuspend) {
if status == consts.JdCookieStatusSuspend {
updateData.SuspendUntil = gtime.Now().Add(time.Minute * consts.JdCookieSuspendDuration)
}
// 如果是恢复正常状态,清除暂停时间
if status == int(consts.JdCookieStatusNormal) {
if status == consts.JdCookieStatusNormal {
updateData.SuspendUntil = nil
}
@@ -139,20 +139,20 @@ func (s *sJdCookie) UpdateCookieStatus(ctx context.Context, cookieId string, sta
}
// 记录状态变更历史
if oldCookie.Status != status || oldCookie.FailureCount != failureCount {
if oldCookie.Status != int(status) || oldCookie.FailureCount != failureCount {
var changeType consts.CookieChangeType
switch status {
case int(consts.JdCookieStatusNormal):
case consts.JdCookieStatusNormal:
changeType = consts.CookieChangeTypeResume
case int(consts.JdCookieStatusSuspend):
case consts.JdCookieStatusSuspend:
changeType = consts.CookieChangeTypeSuspend
case int(consts.JdCookieStatusExpired):
case consts.JdCookieStatusExpired:
changeType = consts.CookieChangeTypeFail
default:
changeType = consts.CookieChangeTypeUpdate
}
_ = s.RecordCookieHistory(ctx, cookieId, changeType, oldCookie.Status, status, "", failureCount)
_ = s.RecordCookieHistory(ctx, cookieId, changeType, oldCookie.Status, int(status), "", failureCount)
}
return
@@ -190,7 +190,7 @@ func (s *sJdCookie) CreateJdOrder(ctx context.Context, jdOrderId, payId, cookieI
}
// UpdateJdOrderStatus 更新京东订单状态
func (s *sJdCookie) UpdateJdOrderStatus(ctx context.Context, jdOrderId string, status int, wxPayUrl string) (err error) {
func (s *sJdCookie) UpdateJdOrderStatus(ctx context.Context, jdOrderId string, status consts.JdOrderStatus, wxPayUrl string) (err error) {
if jdOrderId == "" {
return gerror.New("京东订单号不能为空")
}
@@ -208,7 +208,7 @@ func (s *sJdCookie) UpdateJdOrderStatus(ctx context.Context, jdOrderId string, s
}
updateData := &do.V1JdCookieJdOrder{
Status: status,
Status: int(status),
}
if wxPayUrl != "" {
@@ -222,14 +222,14 @@ func (s *sJdCookie) UpdateJdOrderStatus(ctx context.Context, jdOrderId string, s
}
// 记录状态变更历史
if oldOrder.Status != status {
if oldOrder.Status != int(status) {
var changeType consts.JdOrderChangeType
switch status {
case int(consts.JdOrderStatusPaid):
case consts.JdOrderStatusPaid:
changeType = consts.JdOrderChangeTypePay
case int(consts.JdOrderStatusExpired):
case consts.JdOrderStatusExpired:
changeType = consts.JdOrderChangeTypeExpire
case int(consts.JdOrderStatusCanceled):
case consts.JdOrderStatusCanceled:
changeType = consts.JdOrderChangeTypeInvalid
default:
changeType = consts.JdOrderChangeTypeReplace

View File

@@ -14,6 +14,7 @@ type V1JdCookieOrder struct {
g.Meta `orm:"table:jd_cookie_order, do:true"`
Id any // 主键ID
OrderId any // 订单号
UserOrderId any // 用户订单号
Amount any // 订单金额
Category any // 商品品类
JdOrderId any // 关联的京东订单号

View File

@@ -13,6 +13,7 @@ import (
type V1JdCookieOrder struct {
Id int64 `json:"id" orm:"id" description:"主键ID"`
OrderId string `json:"orderId" orm:"order_id" description:"订单号"`
UserOrderId string `json:"userOrderId" orm:"user_order_id" description:"用户订单号"`
Amount decimal.Decimal `json:"amount" orm:"amount" description:"订单金额"`
Category string `json:"category" orm:"category" description:"商品品类"`
JdOrderId string `json:"jdOrderId" orm:"jd_order_id" description:"关联的京东订单号"`

View File

@@ -0,0 +1,35 @@
package model
import "kami/internal/consts"
// ====================================================================================
// JD Cookie 相关模型结构体
// ====================================================================================
// CreateOrderResult 创建订单返回结果
type CreateOrderResult struct {
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
OrderId string `json:"orderId" dc:"内部订单号"`
}
// PaymentResult 支付结果
type PaymentResult struct {
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
OrderId string `json:"orderId" dc:"内部订单号"`
}
// CreateNewJdOrderWithRetryReq 创建新的京东订单请求参数
type CreateNewJdOrderWithRetryReq struct {
OrderId string `json:"orderId" dc:"内部订单号"`
Amount float64 `json:"amount" dc:"订单金额"`
Category consts.RedeemOrderCardCategory `json:"category" dc:"卡券类别"`
}
// CreateNewJdOrderWithRetryRes 创建新的京东订单返回结果
type CreateNewJdOrderWithRetryRes struct {
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
CookieId string `json:"cookieId" dc:"Cookie ID"`
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
}

View File

@@ -9,6 +9,7 @@ import (
"context"
v1 "kami/api/jd_cookie/v1"
"kami/internal/consts"
"kami/internal/model"
"kami/internal/model/entity"
)
@@ -37,7 +38,7 @@ type (
// GetJdOrderHistoryByOrderId 根据订单ID获取所有关联的京东订单历史
GetJdOrderHistoryByOrderId(ctx context.Context, orderId string, page int, size int) (list []*v1.JdOrderHistoryInfo, total int, err error)
// CreateOrder 创建订单
CreateOrder(ctx context.Context, orderId string, amount float64, category consts.RedeemOrderCardCategory) (wxPayUrl string, jdOrderId string, err error)
CreateOrder(ctx context.Context, userOrderId string, amount float64, category consts.RedeemOrderCardCategory) (result *model.CreateOrderResult, err error)
// GetJdOrder 获取单个京东订单
GetJdOrder(ctx context.Context, jdOrderId string) (order *v1.JdOrderInfo, err error)
// ListJdOrder 京东订单列表查询
@@ -55,7 +56,7 @@ type (
// ReleaseExpiredJdOrders 释放过期京东订单的关联(使其可以被复用)
ReleaseExpiredJdOrders(ctx context.Context) error
// GetPaymentUrl 获取支付链接
GetPaymentUrl(ctx context.Context, orderId string) (wxPayUrl string, jdOrderId string, err error)
GetPaymentUrl(ctx context.Context, orderId string) (result *model.PaymentResult, err error)
// GetOrder 获取单个订单
GetOrder(ctx context.Context, orderId string) (order *v1.OrderInfo, err error)
// GetOrderStatus 查询订单状态

View File

@@ -104,7 +104,8 @@ func main() {
`DROP TABLE IF EXISTS jd_cookie_order`,
`CREATE TABLE jd_cookie_order (
id bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
order_id varchar(64) NOT NULL COMMENT '订单号',
order_id varchar(64) NOT NULL COMMENT '内部订单号',
user_order_id varchar(64) DEFAULT NULL COMMENT '用户订单号',
amount decimal(10,2) NOT NULL COMMENT '订单金额',
category varchar(50) NOT NULL COMMENT '商品品类',
jd_order_id varchar(64) DEFAULT NULL COMMENT '关联的京东订单号',
@@ -116,6 +117,7 @@ func main() {
deleted_at datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (id),
UNIQUE KEY uk_order_id (order_id),
KEY idx_user_order_id (user_order_id),
KEY idx_status (status),
KEY idx_jd_order_id (jd_order_id),
KEY idx_last_request (last_request_at),