fix:支付

This commit is contained in:
momo
2023-09-22 16:27:17 +08:00
parent ddb4ec944d
commit 7e400ed761
7 changed files with 303 additions and 148 deletions

View File

@@ -15,6 +15,8 @@ import (
"time"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/stripe/stripe-go/v74"
"github.com/zeromicro/go-zero/core/logc"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
@@ -40,6 +42,16 @@ type (
List(ctx context.Context, in *ListReq) (res *ListRes, err error)
// 详情
Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error)
// 支付成功
PaymentSuccessful(ctx context.Context, in *PaymentSuccessfulReq) (res *PaymentSuccessfulRes, err error)
}
PayInfo struct {
PayMethod int64 `json:"pay_method"` // 交易方式
PayTime time.Time `json:"pay_time"` // 支付时间
Status gmodel.PayStatus `json:"status"` // 当前状态
StatusLink []gmodel.PayStatus `json:"status_link"` // 状态链路
TradeNo string `json:"trade_no"` // 支付交易号
}
OrderAddress struct {
@@ -63,6 +75,16 @@ type (
Amount int64 `json:"amount"` // 金额
Label string `json:"label"` // 标签
}
/* 支付成功 */
PaymentSuccessfulReq struct {
EventId string
PaymentMethod int64
PaymentIntent *stripe.PaymentIntent
}
PaymentSuccessfulRes struct{}
/* 支付成功 */
/* 预支付--定金 */
CreatePrePaymentByDepositReq struct {
StripeKey string `json:"stripe_key"`
@@ -139,6 +161,175 @@ type (
/* 列表 */
)
// 支付成功
func (d *defaultOrder) PaymentSuccessful(ctx context.Context, in *PaymentSuccessfulReq) (res *PaymentSuccessfulRes, err error) {
var orderSn string
var payStage string
var ok bool
var card string
var brand string
var country string
var currency string
var tradeSn string
var payAmount int64
var payTitle string
var payTime time.Time
if in.PaymentIntent != nil {
paymentIntent := in.PaymentIntent
orderSn, ok = paymentIntent.Metadata["order_sn"]
if !ok || orderSn == "" {
err = errors.New("order_sn is empty")
logc.Errorf(ctx, "PaymentSuccessful failed param, eventId:%s,err:%v", in.EventId, err)
return &PaymentSuccessfulRes{}, err
}
payStage, ok = paymentIntent.Metadata["pay_stage"]
if !ok || payStage == "" {
err = errors.New("pay_stage is empty")
logc.Errorf(ctx, "PaymentSuccessful failed param, eventId:%s,err:%v", in.EventId, err)
return &PaymentSuccessfulRes{}, err
}
country, ok = paymentIntent.Metadata["country"]
if !ok || country == "" {
err = errors.New("country is empty")
logc.Errorf(ctx, "PaymentSuccessful failed param, eventId:%s,err:%v", in.EventId, err)
return &PaymentSuccessfulRes{}, err
}
if paymentIntent.LatestCharge.PaymentMethodDetails != nil {
if paymentIntent.LatestCharge.PaymentMethodDetails.Card != nil {
if paymentIntent.LatestCharge.PaymentMethodDetails.Card.Last4 != "" {
card = paymentIntent.LatestCharge.PaymentMethodDetails.Card.Last4
}
if paymentIntent.LatestCharge.PaymentMethodDetails.Card.Brand != "" {
brand = string(paymentIntent.LatestCharge.PaymentMethodDetails.Card.Brand)
}
}
}
if paymentIntent.Currency != "" {
currency = string(paymentIntent.Currency)
}
tradeSn = paymentIntent.ID
payAmount = paymentIntent.Amount
payTitle = paymentIntent.Description
payTime = time.Unix(paymentIntent.Created, 0)
}
err = d.MysqlConn.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var orderInfo gmodel.FsOrder
result := tx.Where("is_del = ?", 0).Where("order_sn = ?", orderSn).Take(&orderInfo)
err = result.Error
if err != nil {
logx.Errorf("PaymentSuccessful failed order Take, eventId:%s,err: %v", in.EventId, err)
return err
}
ress, err := d.OrderDetailHandler(ctx, &orderInfo, 0)
if err != nil {
logx.Errorf("PaymentSuccessful failed DetailOrderDetailHandler,eventId:%s, err: %v", in.EventId, err)
return err
}
var ntime = time.Now().UTC()
if (payStage == "deposit" && *orderInfo.PayStatus == int64(constants.ORDERPAYSTATUSUNPAIDDEPOSIT)) || (payStage == "remaining_balance" && *orderInfo.PayStatus == int64(constants.ORDERPAYSTATUSPAIDDEPOSIT)) {
var payStatus = int64(constants.PAYSTATUSPAID)
var payStageInt int64
var orderPayStatusCode constants.OrderPayStatusCode
// 订单状态--当前
var status gmodel.OrderStatus
var statusLink []gmodel.OrderStatus
var uOrderDetail = make(map[string]interface{})
var payInfo PayInfo
payInfo.PayMethod = in.PaymentMethod
payInfo.PayTime = payTime
payInfo.TradeNo = tradeSn
if payStage == "deposit" {
payStageInt = 1
orderPayStatusCode = constants.ORDERPAYSTATUSPAIDDEPOSIT
status = gmodel.OrderStatus{
Ctime: &ntime,
Utime: &ntime,
StatusCode: constants.ORDERSTATUSDIRECTMAILORDERED,
StatusTitle: constants.OrderStatusMessage[constants.ORDERSTATUSDIRECTMAILORDERED],
}
statusLink = order.UpdateOrderStatusLink(ress.OrderDetailOriginal.OrderInfo.StatusLink, gmodel.OrderStatus{
Utime: &ntime,
StatusCode: constants.ORDERSTATUSDIRECTMAILORDERED,
StatusTitle: constants.OrderStatusMessage[constants.ORDERSTATUSDIRECTMAILORDERED],
})
payInfo.Status = gmodel.PayStatus{
StatusCode: int64(constants.PAYSTATUSPAID),
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSPAID],
}
payInfo.StatusLink = append(ress.OrderDetail.OrderAmount.Deposit.StatusLink, payInfo.Status)
uOrderDetail["order_amount"] = struct {
Deposit PayInfo `json:"deposit"`
}{
Deposit: payInfo,
}
}
if payStage == "remaining_balance" {
payStageInt = 2
orderPayStatusCode = constants.ORDERPAYSTATUSPAIDDREMAINING
status = gmodel.OrderStatus{
Ctime: &ntime,
Utime: &ntime,
StatusCode: constants.ORDERSTATUSCLOUDSTOREORDERED,
StatusTitle: constants.OrderStatusMessage[constants.ORDERSTATUSCLOUDSTOREORDERED],
}
statusLink = order.UpdateOrderStatusLink(ress.OrderDetailOriginal.OrderInfo.StatusLink, gmodel.OrderStatus{
Utime: &ntime,
StatusCode: constants.ORDERSTATUSCLOUDSTOREORDERED,
StatusTitle: constants.OrderStatusMessage[constants.ORDERSTATUSCLOUDSTOREORDERED],
})
payInfo.StatusLink = append(ress.OrderDetail.OrderAmount.RemainingBalance.StatusLink, payInfo.Status)
uOrderDetail["order_amount"] = struct {
RemainingBalance PayInfo `json:"remaining_balance"`
}{
RemainingBalance: payInfo,
}
}
// 新增交易信息
tx.Create(&gmodel.FsOrderTrade{
UserId: orderInfo.UserId,
OrderSn: &orderSn,
OrderSource: orderInfo.OrderSource,
TradeSn: &tradeSn,
PayAmount: &payAmount,
PayStatus: &payStatus,
PaymentMethod: &in.PaymentMethod,
PayStage: &payStageInt,
CardSn: &card,
CardBrand: &brand,
Country: &country,
Currency: &currency,
Ctime: &ntime,
Utime: &ntime,
PayTitle: &payTitle,
})
// 更新订单信息
var sql string = fmt.Sprintf(", `utime` = '%s'", ntime)
uOrderDetail["pay_status"] = orderPayStatusCode
uOrderDetail["order_info"] = struct {
Utime *time.Time `json:"utime"`
Status gmodel.OrderStatus `json:"status"`
StatusLink []gmodel.OrderStatus `json:"status_link"`
}{
Utime: &ntime,
Status: status,
StatusLink: statusLink,
}
if len(uOrderDetail) > 0 {
err = fssql.MetadataOrderPATCH(d.MysqlConn, sql, orderSn, gmodel.FsOrder{}, uOrderDetail, "id = ?", orderInfo.Id)
if err != nil {
logx.Errorf("PaymentSuccessful failed MetadataOrderPATCH,eventId:%s, err: %v", in.EventId, err)
return err
}
}
}
return nil
})
return &PaymentSuccessfulRes{}, nil
}
// 预支付--尾款
func (d *defaultOrder) CreatePrePaymentByBalance(ctx context.Context, in *CreatePrePaymentByBalanceReq) (res *CreatePrePaymentByBalanceRes, err error) {
var errorCode basic.StatusResponse
@@ -172,7 +363,7 @@ func (d *defaultOrder) CreatePrePaymentByBalance(ctx context.Context, in *Create
}, err
}
ress, err := d.OrderDetailHandler(ctx, &order)
ress, err := d.OrderDetailHandler(ctx, &order, 1)
if err != nil {
logx.Errorf("create prePayment balance failed DetailOrderDetailHandler, err: %v", err)
errorCode = *basic.CodeServiceErr
@@ -185,8 +376,13 @@ func (d *defaultOrder) CreatePrePaymentByBalance(ctx context.Context, in *Create
payConfig := &pay.Config{}
payConfig.Stripe.PayType = "intent"
payConfig.Stripe.Key = in.StripeKey
var metadata = make(map[string]string, 2)
metadata["model"] = "product_order"
metadata["order_sn"] = in.OrderSn
metadata["pay_stage"] = "remaining_balance"
metadata["country"] = in.Country
var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
OrderSn: in.OrderSn,
Metadata: metadata,
ProductName: "支付尾款后期统一调整",
Amount: amount,
Currency: "usd",
@@ -270,7 +466,7 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
}, err
}
ress, err := d.OrderDetailHandler(ctx, &order)
ress, err := d.OrderDetailHandler(ctx, &order, 0)
if err != nil {
logx.Errorf("create prePayment deposit failed DetailOrderDetailHandler, err: %v", err)
errorCode = *basic.CodeServiceErr
@@ -342,8 +538,13 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
payConfig := &pay.Config{}
payConfig.Stripe.PayType = "intent"
payConfig.Stripe.Key = in.StripeKey
var metadata = make(map[string]string, 2)
metadata["model"] = "product_order"
metadata["order_sn"] = in.OrderSn
metadata["pay_stage"] = "deposit"
metadata["country"] = in.Country
var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
OrderSn: in.OrderSn,
Metadata: metadata,
ProductName: "支付首款",
Amount: amount,
Currency: "usd",
@@ -417,7 +618,7 @@ func (d *defaultOrder) List(ctx context.Context, in *ListReq) (res *ListRes, err
return nil, result.Error
}
for _, order := range orderList {
ress, err := d.OrderDetailHandler(ctx, &order)
ress, err := d.OrderDetailHandler(ctx, &order, 1)
if err != nil {
return nil, err
}
@@ -474,7 +675,7 @@ func (d *defaultOrder) Detail(ctx context.Context, in *DetailReq) (res *DetailRe
}, err
}
ress, err := d.OrderDetailHandler(ctx, &order)
ress, err := d.OrderDetailHandler(ctx, &order, 1)
if err != nil {
logx.Errorf("order detail failed, err: %v", err)
errorCode = *basic.CodeServiceErr
@@ -718,6 +919,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
StatusCode: int64(constants.PAYSTATUSUNPAID),
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSUNPAID],
},
StatusLink: make([]gmodel.PayStatus, 0),
PayAmount: order.GetAmountInfo(order.GetAmountInfoReq{
ExchangeRate: in.ExchangeRate,
Initiate: depositInt,
@@ -734,6 +936,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
StatusCode: int64(constants.PAYSTATUSUNPAID),
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSUNPAID],
},
StatusLink: make([]gmodel.PayStatus, 0),
PayAmount: order.GetAmountInfo(order.GetAmountInfoReq{
ExchangeRate: in.ExchangeRate,
Initiate: remainingBalanceInt,
@@ -817,7 +1020,7 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
}
// 详情处理
func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel.FsOrder) (res *DetailRes, err error) {
func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel.FsOrder, original int64) (res *DetailRes, err error) {
var orderDetail gmodel.OrderDetail
err = json.Unmarshal(*orderInfo.Metadata, &orderDetail)
@@ -826,18 +1029,21 @@ func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel
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
if original == 1 {
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())
}
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,