From be786a4d4c50a72d787787b2363550d70ee0ab4f Mon Sep 17 00:00:00 2001 From: momo <1012651275@qq.com> Date: Thu, 21 Sep 2023 19:01:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- model/gmodel/fs_order_logic.go | 1 + server/order/internal/config/config.go | 8 + .../logic/createprepaymentbybalancelogic.go | 4 + .../logic/createprepaymentbydepositlogic.go | 39 +- .../order/internal/logic/orderdetaillogic.go | 2 +- server/order/internal/logic/orderlistlogic.go | 20 +- server/order/internal/types/types.go | 14 +- server_api/order.api | 14 +- service/repositories/order.go | 368 ++++++++++++++++-- utils/basic/basic.go | 16 +- utils/fssql/metadata.go | 45 ++- utils/pay/pay.go | 4 +- utils/pay/stripe.go | 3 - 13 files changed, 480 insertions(+), 58 deletions(-) diff --git a/model/gmodel/fs_order_logic.go b/model/gmodel/fs_order_logic.go index 5c8ce661..6fa62a1a 100644 --- a/model/gmodel/fs_order_logic.go +++ b/model/gmodel/fs_order_logic.go @@ -14,6 +14,7 @@ type OrderDetail struct { OrderInfo OrderInfo `json:"order_info"` // 订单信息 OrderProduct []OrderProduct `json:"order_product"` // 订单商品 PayStatus constants.OrderPayStatusCode `json:"pay_status"` // 支付状态 + PayTimeout time.Duration `json:"pay_timeout"` // 支付状态 } // 收货地址 diff --git a/server/order/internal/config/config.go b/server/order/internal/config/config.go index a88bb7a7..8ebf0d57 100644 --- a/server/order/internal/config/config.go +++ b/server/order/internal/config/config.go @@ -11,4 +11,12 @@ type Config struct { SourceMysql string Auth types.Auth SourceRabbitMq string + PayConfig struct { + Stripe struct { + EndpointSecret string + Key string + CancelURL string + SuccessURL string + } + } } diff --git a/server/order/internal/logic/createprepaymentbybalancelogic.go b/server/order/internal/logic/createprepaymentbybalancelogic.go index 3a4915ee..04d1894c 100644 --- a/server/order/internal/logic/createprepaymentbybalancelogic.go +++ b/server/order/internal/logic/createprepaymentbybalancelogic.go @@ -33,6 +33,10 @@ func NewCreatePrePaymentByBalanceLogic(ctx context.Context, svcCtx *svc.ServiceC func (l *CreatePrePaymentByBalanceLogic) CreatePrePaymentByBalance(req *types.CreatePrePaymentByBalanceReq, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null + if !userinfo.IsUser() { + // 如果是,返回未授权的错误码 + return resp.SetStatus(basic.CodeUnAuth) + } return resp.SetStatus(basic.CodeOK) } diff --git a/server/order/internal/logic/createprepaymentbydepositlogic.go b/server/order/internal/logic/createprepaymentbydepositlogic.go index 23f54c69..584c3511 100644 --- a/server/order/internal/logic/createprepaymentbydepositlogic.go +++ b/server/order/internal/logic/createprepaymentbydepositlogic.go @@ -1,6 +1,8 @@ package logic import ( + "fusenapi/constants" + "fusenapi/service/repositories" "fusenapi/utils/auth" "fusenapi/utils/basic" @@ -33,8 +35,43 @@ func NewCreatePrePaymentByDepositLogic(ctx context.Context, svcCtx *svc.ServiceC func (l *CreatePrePaymentByDepositLogic) CreatePrePaymentByDeposit(req *types.CreatePrePaymentByDepositReq, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null + if !userinfo.IsUser() { + // 如果是,返回未授权的错误码 + return resp.SetStatus(basic.CodeUnAuth) + } + if req.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL { + if req.DeliveryAddress == nil { + return resp.SetStatus(basic.CodeErrOrderCreatePrePaymentParam) + } else { + if req.DeliveryAddress.Address == "" || req.DeliveryAddress.Mobile == "" || req.DeliveryAddress.Name == "" { + return resp.SetStatus(basic.CodeErrOrderCreatePrePaymentParam) + } + } + } + var orderAddress repositories.OrderAddress + if req.DeliveryAddress != nil { + orderAddress.Address = req.DeliveryAddress.Address + orderAddress.Mobile = req.DeliveryAddress.Mobile + orderAddress.Name = req.DeliveryAddress.Name + } + res, err := l.svcCtx.Repositories.NewOrder.CreatePrePaymentByDeposit(l.ctx, &repositories.CreatePrePaymentByDepositReq{ + UserId: userinfo.UserId, + OrderSn: req.OrderSn, + DeliveryMethod: req.DeliveryMethod, + DeliveryAddress: &orderAddress, + Country: "US", + Currency: "usd", + StripeKey: l.svcCtx.Config.PayConfig.Stripe.Key, + }) - return resp.SetStatus(basic.CodeOK) + if err != nil { + return resp.SetStatus(&res.ErrorCode) + } + + return resp.SetStatus(basic.CodeOK, map[string]interface{}{ + "order_detail": res.OrderDetail, + "order_pay": res.OrderPay, + }) } // 处理逻辑后 w,r 如:重定向, resp 必须重新处理 diff --git a/server/order/internal/logic/orderdetaillogic.go b/server/order/internal/logic/orderdetaillogic.go index cd974870..274fe42a 100644 --- a/server/order/internal/logic/orderdetaillogic.go +++ b/server/order/internal/logic/orderdetaillogic.go @@ -43,7 +43,7 @@ func (l *OrderDetailLogic) OrderDetail(req *types.OrderDetailReq, userinfo *auth UserId: userinfo.UserId, }) if err != nil { - return resp.SetStatus(basic.CodeApiErr) + return resp.SetStatus(&res.ErrorCode) } return resp.SetStatus(basic.CodeOK, map[string]interface{}{ diff --git a/server/order/internal/logic/orderlistlogic.go b/server/order/internal/logic/orderlistlogic.go index 235b7dfb..cff5d97b 100644 --- a/server/order/internal/logic/orderlistlogic.go +++ b/server/order/internal/logic/orderlistlogic.go @@ -1,6 +1,7 @@ package logic import ( + "fusenapi/service/repositories" "fusenapi/utils/auth" "fusenapi/utils/basic" @@ -33,8 +34,25 @@ func NewOrderListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OrderLi func (l *OrderListLogic) OrderList(req *types.OrderListReq, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null + if !userinfo.IsUser() { + // 如果是,返回未授权的错误码 + return resp.SetStatus(basic.CodeUnAuth) + } + res, err := l.svcCtx.Repositories.NewOrder.List(l.ctx, &repositories.ListReq{ + UserId: userinfo.UserId, + DeliveryMethod: req.DeliveryMethod, + OrderCycle: req.OrderCycle, + CurrentPage: req.CurrentPage, + PerPage: req.PerPage, + }) + if err != nil { + return resp.SetStatus(basic.CodeApiErr) + } - return resp.SetStatus(basic.CodeOK) + return resp.SetStatus(basic.CodeOK, map[string]interface{}{ + "list": res.OrderDetailList, + "meta": res.Meta, + }) } // 处理逻辑后 w,r 如:重定向, resp 必须重新处理 diff --git a/server/order/internal/types/types.go b/server/order/internal/types/types.go index 68118bcc..a27a0c52 100644 --- a/server/order/internal/types/types.go +++ b/server/order/internal/types/types.go @@ -15,12 +15,12 @@ type CreateOrderReq struct { } type CreatePrePaymentByDepositReq struct { - OrderSn string `json:"order_sn"` - DeliveryMethod int64 `json:"delivery_method,options=[1,2]"` - DeliveryAddres DeliveryAddres `json:"delivery_addres,optional"` + OrderSn string `json:"order_sn"` + DeliveryMethod int64 `json:"delivery_method,options=[1,2]"` + DeliveryAddress *DeliveryAddress `json:"delivery_address,optional"` } -type DeliveryAddres struct { +type DeliveryAddress struct { Address string `json:"address,optional"` Name string `json:"name,optional"` Mobile string `json:"mobile,optional"` @@ -32,9 +32,9 @@ type CreatePrePaymentByBalanceReq struct { type OrderListReq struct { DeliveryMethod int64 `json:"delivery_method,options=[0,1,2],optional"` - OrderCycle string `json:"order_cycle,optional"` - Current_page int64 `json:"current_page,optional,default=1"` - Page_size int64 `json:"page_size,optional,default=10"` + OrderCycle string `json:"order_cycle,optional,options=[within_one_month,within_three_month,within_six_month,within_one_year]"` + CurrentPage int64 `json:"current_page,optional,default=1"` + PerPage int64 `json:"per_page,optional,default=10"` } type Request struct { diff --git a/server_api/order.api b/server_api/order.api index 1a0747e7..571f615f 100644 --- a/server_api/order.api +++ b/server_api/order.api @@ -38,12 +38,12 @@ type CreateOrderReq { } type CreatePrePaymentByDepositReq { - OrderSn string `json:"order_sn"` - DeliveryMethod int64 `json:"delivery_method,options=[1,2]"` - DeliveryAddres DeliveryAddres `json:"delivery_addres,optional"` + OrderSn string `json:"order_sn"` + DeliveryMethod int64 `json:"delivery_method,options=[1,2]"` + DeliveryAddress *DeliveryAddress `json:"delivery_address,optional"` } -type DeliveryAddres { +type DeliveryAddress { Address string `json:"address,optional"` Name string `json:"name,optional"` Mobile string `json:"mobile,optional"` @@ -55,7 +55,7 @@ type CreatePrePaymentByBalanceReq { type OrderListReq { DeliveryMethod int64 `json:"delivery_method,options=[0,1,2],optional"` - OrderCycle string `json:"order_cycle,optional"` - Current_page int64 `json:"current_page,optional,default=1"` - Page_size int64 `json:"page_size,optional,default=10"` + OrderCycle string `json:"order_cycle,optional,options=[within_one_month,within_three_month,within_six_month,within_one_year]"` + CurrentPage int64 `json:"current_page,optional,default=1"` + PerPage int64 `json:"per_page,optional,default=10"` } \ No newline at end of file diff --git a/service/repositories/order.go b/service/repositories/order.go index b6afc6ae..976f5c2d 100644 --- a/service/repositories/order.go +++ b/service/repositories/order.go @@ -4,10 +4,14 @@ import ( "context" "encoding/json" "errors" + "fmt" "fusenapi/constants" "fusenapi/model/gmodel" "fusenapi/utils/basic" + "fusenapi/utils/fssql" + "fusenapi/utils/handlers" "fusenapi/utils/order" + "fusenapi/utils/pay" "time" "github.com/aws/aws-sdk-go/aws/session" @@ -28,8 +32,10 @@ type ( Order interface { // 下单 Create(ctx context.Context, in *CreateReq) (res *CreateRes, err error) - // 预支付 + // 预支付--定金 + CreatePrePaymentByDeposit(ctx context.Context, in *CreatePrePaymentByDepositReq) (res *CreatePrePaymentByDepositRes, err error) // 列表 + List(ctx context.Context, in *ListReq) (res *ListRes, err error) // 详情 Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error) } @@ -39,6 +45,38 @@ type ( Mobile string `json:"mobile"` // 手机 Name string `json:"name"` // 姓名 } + OrderPay struct { + ClientSecret string `json:"client_secret"` // 支付方--秘钥 + Country string `json:"country"` // 国家 + Currency string `json:"currency"` // 货币 + Metadata map[string]interface{} `json:"metadata"` // 额外参数 + Method string `json:"method"` // 支付方--途径 + OrderSn string `json:"order_sn"` // 订单编码 + PayStage int64 `json:"pay_stage"` // 支付阶段 + RedirectURL *string `json:"redirect_url"` // 支付方--重定向地址 + Total OrderPayTotal `json:"total"` // 支付参数 + } + // 支付参数 + OrderPayTotal struct { + Amount int64 `json:"amount"` // 金额 + Label string `json:"label"` // 标签 + } + /* 预支付--定金 */ + CreatePrePaymentByDepositReq struct { + StripeKey string `json:"stripe_key"` + Currency string `json:"currency"` + Country string `json:"country"` + UserId int64 `json:"user_id"` + OrderSn string `json:"order_sn"` + DeliveryMethod int64 `json:"delivery_method"` + DeliveryAddress *OrderAddress `json:"delivery_address"` // 收货地址 + } + CreatePrePaymentByDepositRes struct { + ErrorCode basic.StatusResponse + OrderDetail gmodel.OrderDetail + OrderPay OrderPay + } + /* 预支付--定金 */ /* 下单 */ CreateReq struct { @@ -63,49 +101,291 @@ type ( OrderSn string `json:"order_sn"` } DetailRes struct { - OrderDetail gmodel.OrderDetail + ErrorCode basic.StatusResponse + OrderDetail gmodel.OrderDetail + OrderDetailOriginal gmodel.OrderDetail } /* 详情 */ + + /* 列表 */ + ListReq struct { + UserId int64 `json:"user_id"` + DeliveryMethod int64 `json:"delivery_method"` + OrderCycle string `json:"order_cycle"` + CurrentPage int64 `json:"current_page"` + PerPage int64 `json:"per_page"` + } + ListRes struct { + OrderDetailList []gmodel.OrderDetail + Meta interface{} + } + /* 列表 */ ) -// 详情 -func (d *defaultOrder) Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error) { +// 预支付--定金 +func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *CreatePrePaymentByDepositReq) (res *CreatePrePaymentByDepositRes, err error) { + var errorCode basic.StatusResponse var order gmodel.FsOrder - result := d.MysqlConn.Where("order_sn = ?", in.OrderSn).Where("user_id = ?", in.UserId).Take(&order) - if result.Error != nil { - logx.Errorf("detail failed, err: %v", err) - return nil, result.Error + model := d.MysqlConn.Where("is_del = ?", 0) + if in.UserId != 0 { + model.Where("user_id = ?", in.UserId) } + if in.OrderSn != "" { + model.Where("order_sn = ?", in.OrderSn) + } + result := model.Take(&order) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound + } else { + errorCode = *basic.CodeServiceErr + } + logx.Errorf("create prePayment deposit failed, err: %v", err) + return &CreatePrePaymentByDepositRes{ + ErrorCode: errorCode, + }, result.Error + } + + // 非未支付 + if *order.PayStatus != int64(constants.ORDERPAYSTATUSUNPAIDDEPOSIT) { + errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound + err = errors.New("order pay status is not unPaidDeposit") + logx.Errorf("create prePayment deposit failed, err: %v", err) + return &CreatePrePaymentByDepositRes{ + ErrorCode: errorCode, + }, err + } + + // 是否超时支付 + ntime := time.Now().UTC() + ctime := *order.Ctime + ctimeTimeOut := ctime.Add(30 * time.Minute).UTC().Unix() + ntimeTimeOut := ntime.Unix() + if ctimeTimeOut == ntimeTimeOut { + errorCode = *basic.CodeErrOrderCreatePrePaymentTimeout + err = errors.New("order pay timeout") + logx.Errorf("create prePayment deposit failed, err: %v", err) + return &CreatePrePaymentByDepositRes{ + ErrorCode: errorCode, + }, err + } + ress, err := d.OrderDetailHandler(ctx, &order) if err != nil { - return nil, err + logx.Errorf("create prePayment deposit failed DetailOrderDetailHandler, err: %v", err) + errorCode = *basic.CodeServiceErr + return &CreatePrePaymentByDepositRes{ + ErrorCode: errorCode, + }, err } - return &DetailRes{ - ress.OrderDetail, + + var uOrderDetail = make(map[string]interface{}) + + var orderAddress *gmodel.OrderAddress + if in.DeliveryAddress != nil { + if in.DeliveryAddress.Name != ress.OrderDetailOriginal.DeliveryAddress.Name || in.DeliveryAddress.Address != ress.OrderDetail.DeliveryAddress.Address || in.DeliveryAddress.Mobile != ress.OrderDetail.DeliveryAddress.Mobile { + orderAddress = &gmodel.OrderAddress{ + Name: in.DeliveryAddress.Name, + Mobile: in.DeliveryAddress.Mobile, + Address: in.DeliveryAddress.Address, + } + } + } + + var sql string = fmt.Sprintf(", `utime` = '%s'", ntime) + // 是否更新 + if in.DeliveryMethod != *order.DeliveryMethod { + sql = sql + fmt.Sprintf(",`delivery_method` = %d", in.DeliveryMethod) + if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL { + uOrderDetail["delivery_address"] = orderAddress + } else { + uOrderDetail["delivery_address"] = nil + } + uOrderDetail["order_info"] = struct { + DeliveryMethod int64 `json:"delivery_method"` + Utime *time.Time `json:"utime"` + }{ + DeliveryMethod: in.DeliveryMethod, + Utime: &ntime, + } + } else { + if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL { + // 更新收货地址 + if orderAddress != nil { + uOrderDetail["delivery_address"] = orderAddress + uOrderDetail["order_info"] = struct { + DeliveryMethod int64 `json:"delivery_method"` + Utime *time.Time `json:"utime"` + }{ + DeliveryMethod: in.DeliveryMethod, + Utime: &ntime, + } + } + } + } + if len(uOrderDetail) > 0 { + err = fssql.MetadataOrderPATCH(d.MysqlConn, sql, in.OrderSn, gmodel.FsOrder{}, uOrderDetail, "id = ?", order.Id) + if err != nil { + errorCode = *basic.CodeServiceErr + logx.Errorf("create prePayment deposit failed MetadataOrderPATCH, err: %v", err) + return &CreatePrePaymentByDepositRes{ + ErrorCode: errorCode, + }, result.Error + } + } + + ress.OrderDetail.OrderInfo.Utime = &ntime + ress.OrderDetail.OrderInfo.DeliveryMethod = in.DeliveryMethod + ress.OrderDetail.DeliveryAddress = orderAddress + + // 支付初始化 + amount := int64(ress.OrderDetailOriginal.OrderAmount.Deposit.PayAmount.Current.CurrentAmount.(float64) / float64(10)) + payConfig := &pay.Config{} + payConfig.Stripe.PayType = "intent" + payConfig.Stripe.Key = in.StripeKey + var generatePrepaymentReq = &pay.GeneratePrepaymentReq{ + OrderSn: in.OrderSn, + ProductName: "支付标题", + Amount: amount, + Currency: "usd", + Quantity: 1, + ProductDescription: "支付描述", + } + payDriver := pay.NewPayDriver(1, payConfig) + + prepaymentRes, err := payDriver.GeneratePrepayment(generatePrepaymentReq) + if err != nil { + logx.Errorf("create prePayment deposit failed GeneratePrepayment, err: %v", err) + errorCode = *basic.CodeServiceErr + return &CreatePrePaymentByDepositRes{ + ErrorCode: errorCode, + }, nil + } + return &CreatePrePaymentByDepositRes{ + OrderDetail: ress.OrderDetail, + OrderPay: OrderPay{ + ClientSecret: prepaymentRes.ClientSecret, + Country: in.Country, + Currency: in.Currency, + Method: payConfig.Stripe.PayType, + OrderSn: in.OrderSn, + PayStage: 1, + Total: OrderPayTotal{ + Amount: amount, + Label: "", + }, + }, }, nil } -func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel.FsOrder) (res *DetailRes, err error) { - var orderDetail gmodel.OrderDetail +// 列表 +func (d *defaultOrder) List(ctx context.Context, in *ListReq) (res *ListRes, err error) { + var orderList []gmodel.FsOrder + model := d.MysqlConn.Model(&gmodel.FsOrder{}).Where("is_del = ?", 0) + if in.UserId != 0 { + model.Where("user_id = ?", in.UserId) + } - err = json.Unmarshal(*orderInfo.Metadata, &orderDetail) + // Where("pay_status > ?", 0) + if in.DeliveryMethod != 0 { + model.Where("delivery_method = ?", in.DeliveryMethod) + } + if in.OrderCycle != "" { + // 下单时间 + switch in.OrderCycle { + case "within_one_month": + model.Where("ctime >?", time.Now().UTC().AddDate(0, -1, 0).Unix()) + case "within_three_month": + model.Where("ctime >?", time.Now().UTC().AddDate(0, -3, 0).Unix()) + case "within_six_month": + model.Where("ctime >?", time.Now().UTC().AddDate(0, -6, 0).Unix()) + case "within_one_year": + model.Where("ctime >?", time.Now().UTC().AddDate(-1, 0, 0).Unix()) + } + } + var count int64 + resultCount := model.Count(&count) + if resultCount.Error != nil { + logx.Errorf("order count failed, err: %v", err) + return nil, resultCount.Error + } + var orderDetailList []gmodel.OrderDetail + if count > 0 { + m := model.Scopes(handlers.Paginate(&in.CurrentPage, &in.PerPage)) + result := m.Find(&orderList) + if result.Error != nil { + logx.Errorf("order list failed, err: %v", err) + return nil, result.Error + } + for _, order := range orderList { + ress, err := d.OrderDetailHandler(ctx, &order) + if err != nil { + return nil, err + } + orderDetailList = append(orderDetailList, ress.OrderDetail) + } + } else { + orderDetailList = make([]gmodel.OrderDetail, 0) + } + return &ListRes{ + OrderDetailList: orderDetailList, + Meta: map[string]int64{ + "total_count": count, + "page_count": count / in.PerPage, + "current_page": in.CurrentPage, + "per_page": in.PerPage, + }, + }, nil +} + +// 详情 +func (d *defaultOrder) Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error) { + var errorCode basic.StatusResponse + var order gmodel.FsOrder + model := d.MysqlConn.Where("is_del = ?", 0) + if in.UserId != 0 { + model.Where("user_id = ?", in.UserId) + } + if in.OrderSn != "" { + model.Where("order_sn = ?", in.OrderSn) + } + result := model.Take(&order) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound + } else { + errorCode = *basic.CodeServiceErr + } + logx.Errorf("order detail failed, err: %v", err) + return &DetailRes{ + ErrorCode: errorCode, + }, result.Error + } + + // 是否超时支付 + ctime := *order.Ctime + ctimeTimeOut := ctime.Add(30 * time.Minute).UTC().Unix() + ntimeTimeOut := time.Now().UTC().Unix() + if ctimeTimeOut < ntimeTimeOut { + errorCode = *basic.CodeErrOrderCreatePrePaymentTimeout + err = errors.New("order pay timeout") + logx.Errorf("order detail failed, err: %v", err) + return &DetailRes{ + ErrorCode: errorCode, + }, err + } + + ress, err := d.OrderDetailHandler(ctx, &order) if err != nil { - logx.Errorf("detail handler unmarshal metadata failed, err: %v", err) - return nil, err + logx.Errorf("order detail failed, err: %v", err) + errorCode = *basic.CodeServiceErr + return &DetailRes{ + ErrorCode: errorCode, + }, err } - for orderProductKey, orderProduct := range orderDetail.OrderProduct { - orderDetail.OrderProduct[orderProductKey].TotalPrice = order.GetAmountInfoFormat(&orderProduct.TotalPrice) - orderDetail.OrderProduct[orderProductKey].ItemPrice = order.GetAmountInfoFormat(&orderProduct.ItemPrice) - orderDetail.OrderProduct[orderProductKey].ShoppingCartSnapshot = nil - orderDetail.OrderProduct[orderProductKey].ProductSnapshot = nil - } - orderDetail.OrderInfo.StatusLink = order.GetOrderStatusLinkUser(orderDetail.OrderInfo.DeliveryMethod, orderDetail.OrderInfo.StatusLink) - orderDetail.OrderAmount.Deposit.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Deposit.PayAmount) - orderDetail.OrderAmount.RemainingBalance.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.RemainingBalance.PayAmount) - orderDetail.OrderAmount.Subtotal = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Subtotal) - orderDetail.OrderAmount.Total = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Total) return &DetailRes{ - OrderDetail: orderDetail, + ErrorCode: errorCode, + OrderDetail: ress.OrderDetail, }, nil } @@ -396,6 +676,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe OrderInfo: orderInfo, OrderProduct: orderProductList, PayStatus: payStatus, + PayTimeout: 30 * time.Minute, } // 数据库操作 @@ -419,7 +700,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe return nil }) if err != nil { - logx.Errorf("create order failed, err: %v", err) + logx.Errorf("order create order failed, err: %v", err) if errorCode.Code == 0 { errorCode.Code = basic.CodeApiErr.Code @@ -435,3 +716,32 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe ErrorCode: errorCode, }, nil } + +// 详情处理 +func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel.FsOrder) (res *DetailRes, err error) { + var orderDetail gmodel.OrderDetail + + err = json.Unmarshal(*orderInfo.Metadata, &orderDetail) + if err != nil { + logx.Errorf("order detail handler unmarshal metadata failed, err: %v", err) + return nil, err + } + orderDetailOriginal := orderDetail + for orderProductKey, orderProduct := range orderDetail.OrderProduct { + orderDetail.OrderProduct[orderProductKey].TotalPrice = order.GetAmountInfoFormat(&orderProduct.TotalPrice) + orderDetail.OrderProduct[orderProductKey].ItemPrice = order.GetAmountInfoFormat(&orderProduct.ItemPrice) + orderDetail.OrderProduct[orderProductKey].ShoppingCartSnapshot = nil + orderDetail.OrderProduct[orderProductKey].ProductSnapshot = nil + } + orderDetail.OrderInfo.StatusLink = order.GetOrderStatusLinkUser(orderDetail.OrderInfo.DeliveryMethod, orderDetail.OrderInfo.StatusLink) + orderDetail.OrderAmount.Deposit.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Deposit.PayAmount) + orderDetail.OrderAmount.RemainingBalance.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.RemainingBalance.PayAmount) + orderDetail.OrderAmount.Subtotal = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Subtotal) + orderDetail.OrderAmount.Total = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Total) + orderDetail.PayTimeout = time.Duration(orderDetail.OrderInfo.Ctime.Add(orderDetail.PayTimeout).UTC().Unix() - time.Now().UTC().Unix()) + + return &DetailRes{ + OrderDetail: orderDetail, + OrderDetailOriginal: orderDetailOriginal, + }, nil +} diff --git a/utils/basic/basic.go b/utils/basic/basic.go index c99004fe..b857247b 100644 --- a/utils/basic/basic.go +++ b/utils/basic/basic.go @@ -100,12 +100,16 @@ var ( CodeLogoCombineErr = &StatusResponse{5115, "logo combine fail"} // 合图失败 CodeLogoCombineNoFoundErr = &StatusResponse{5116, "template record not found"} // 模版不存在 - CodeErrOrder = &StatusResponse{5300, "create order failed"} // 订单错误 - CodeErrOrderCreatShoppingCartEmpty = &StatusResponse{5301, "create order failed, shopping cart is empty"} // 订单创建失败,购物车为空 - CodeErrOrderCreatShoppingCartNotMatched = &StatusResponse{5302, "create order failed, shopping cart not matched"} // 订单创建失败,购物车不相符 - CodeErrOrderCreatProductAbsent = &StatusResponse{5303, "create order failed, product is absent"} // 订单创建失败,商品不存在 - CodeErrOrderCreatProductPriceAbsent = &StatusResponse{5304, "create order failed, price of product is absent"} // 订单创建失败,商品价格不存在 - CodeErrOrderCreatProductAccessoryAbsent = &StatusResponse{5305, "create order failed, accessory of product is absent"} // 订单创建失败,商品配件不存在 + CodeErrOrder = &StatusResponse{5300, "create order failed"} // 订单错误 + CodeErrOrderCreatShoppingCartEmpty = &StatusResponse{5301, "create order failed, shopping cart is empty"} // 订单创建失败,购物车为空 + CodeErrOrderCreatShoppingCartNotMatched = &StatusResponse{5302, "create order failed, shopping cart not matched"} // 订单创建失败,购物车不相符 + CodeErrOrderCreatProductAbsent = &StatusResponse{5303, "create order failed, product is absent"} // 订单创建失败,商品不存在 + CodeErrOrderCreatProductPriceAbsent = &StatusResponse{5304, "create order failed, price of product is absent"} // 订单创建失败,商品价格不存在 + CodeErrOrderCreatProductAccessoryAbsent = &StatusResponse{5305, "create order failed, accessory of product is absent"} // 订单创建失败,商品配件不存在 + CodeErrOrderCreatePrePaymentParam = &StatusResponse{5306, "create payment failed, the shipping address is illegal"} // 订单创建失败,商品配件不存在 + CodeErrOrderCreatePrePaymentInfoNoFound = &StatusResponse{5307, "create payment failed, order info not found"} + CodeErrOrderCreatePrePaymentPaidDeposit = &StatusResponse{5308, "create payment failed, order is paid"} + CodeErrOrderCreatePrePaymentTimeout = &StatusResponse{5309, "create payment failed, timeout"} ) type Response struct { diff --git a/utils/fssql/metadata.go b/utils/fssql/metadata.go index 5e671a81..357a5f27 100644 --- a/utils/fssql/metadata.go +++ b/utils/fssql/metadata.go @@ -58,7 +58,7 @@ func MetadataModulePATCH(tx *gorm.DB, module string, tableStructPointer any, upd WHEN metadata IS NULL THEN ? ELSE JSON_MERGE_PATCH(metadata, ?) END - WHERE module = '%s' and %s;` + WHERE order_sn = '%s' and %s;` var err error var metadata []byte @@ -147,3 +147,46 @@ func MetadataResourcePATCH(tx *gorm.DB, rid string, updateMetadata any, values . return nil } + +func MetadataOrderPATCH(tx *gorm.DB, sql string, orderSn string, tableStructPointer any, updateMetadata any, WhereKeysCond string, values ...any) error { + stype := reflect.TypeOf(tableStructPointer) + if stype.Kind() == reflect.Pointer { + stype = stype.Elem() + } + + updatesql := `UPDATE %s + SET metadata = CASE + WHEN metadata IS NULL THEN ? + ELSE JSON_MERGE_PATCH(metadata, ?) + END%s + WHERE order_sn = '%s' and %s;` + + var err error + var metadata []byte + + switch mdata := updateMetadata.(type) { + case []byte: + metadata = mdata + case string: + metadata = []byte(mdata) + default: + metadata, err = json.Marshal(updateMetadata) + if err != nil { + return err + } + } + + var args []any + + args = append(args, metadata, metadata) + args = append(args, values...) + + updatesql = fmt.Sprintf(updatesql, tx.NamingStrategy.TableName(stype.Name()), sql, orderSn, WhereKeysCond) + // logx.Error(updatesql) + err = tx.Exec(updatesql, args...).Error + if err != nil { + return err + } + + return nil +} diff --git a/utils/pay/pay.go b/utils/pay/pay.go index e982139e..12c7998f 100644 --- a/utils/pay/pay.go +++ b/utils/pay/pay.go @@ -11,9 +11,9 @@ type Config struct { func NewPayDriver(PayMethod int64, config *Config) Pay { switch PayMethod { case int64(constants.PAYMETHOD_STRIPE): - return &Stripe{Key: config.Stripe.Key} + return &Stripe{Key: config.Stripe.Key, PayType: config.Stripe.PayType} default: - return &Stripe{Key: config.Stripe.Key} + return &Stripe{Key: config.Stripe.Key, PayType: config.Stripe.PayType} } } diff --git a/utils/pay/stripe.go b/utils/pay/stripe.go index 2b9ea9cc..75325677 100644 --- a/utils/pay/stripe.go +++ b/utils/pay/stripe.go @@ -81,9 +81,6 @@ func (stripePay *Stripe) GeneratePrepayment(req *GeneratePrepaymentReq) (res *Ge params := &stripe.PaymentIntentParams{ Amount: stripe.Int64(req.Amount), Currency: stripe.String(string(req.Currency)), - AutomaticPaymentMethods: &stripe.PaymentIntentAutomaticPaymentMethodsParams{ - Enabled: stripe.Bool(true), - }, PaymentMethodTypes: stripe.StringSlice([]string{ "card", // "ideal",