diff --git a/rpc/order/pb/order.pb.go b/rpc/order/pb/order.pb.go index c9e0fa4..31eb8c9 100644 --- a/rpc/order/pb/order.pb.go +++ b/rpc/order/pb/order.pb.go @@ -7,12 +7,13 @@ package order import ( - _ "google.golang.org/genproto/googleapis/api/annotations" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" unsafe "unsafe" + + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/services/payment/internal/logic/notifyLogic.go b/services/payment/internal/logic/notifyLogic.go index e13f379..a685337 100644 --- a/services/payment/internal/logic/notifyLogic.go +++ b/services/payment/internal/logic/notifyLogic.go @@ -4,13 +4,11 @@ import ( "context" "errors" - "lone-services/pkg/modelbase" pkgpay "lone-services/pkg/payment" "lone-services/pkg/utils" payment "lone-services/rpc/payment/pb" "lone-services/services/payment/internal/channel" "lone-services/services/payment/internal/dao" - "lone-services/services/payment/internal/model" "lone-services/services/payment/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -51,7 +49,7 @@ func (l *NotifyLogic) Notify(in *payment.NotifyReq) (*payment.Response, error) { return outResponse(utils.Fail, "支付未成功"), nil } - if err := markOrderPaid(result); err != nil { + if err := l.markOrderPaid(result); err != nil { l.Errorf("notify mark paid: %v", err) return outResponse(utils.Fail, err.Error()), nil } @@ -59,38 +57,20 @@ func (l *NotifyLogic) Notify(in *payment.NotifyReq) (*payment.Response, error) { return okResponse(result), nil } -func markOrderPaid(result *pkgpay.NotifyResult) error { +func (l *NotifyLogic) markOrderPaid(result *pkgpay.NotifyResult) error { if result.OutTradeNo == utils.StringEmpty { return errors.New("out_trade_no empty") } - var row dao.OrderPayRow - err := model.OrderModel{}.Init().GetOne(modelbase.Params{ - Eq: map[string]string{"order_sn": result.OutTradeNo}, - }, &row) - if err != nil { - return err - } - if row.Id < utils.NumberOne { - return errors.New("order not found") - } - if row.Status == dao.PayStatusOk { - return nil // idempotent - } - - expected := yuanToFen(row.PayPrice) - if expected > 0 && result.AmountFen > 0 && expected != result.AmountFen { - return errors.New("amount mismatch") - } - - updates := map[string]any{ - "status": dao.PayStatusOk, - } - if result.OutTradeNo != utils.StringEmpty { - updates["out_trade_no"] = result.OutTradeNo - } - _, err = model.OrderModel{}.Init().Edit(modelbase.Params{ - Eq: map[string]string{"order_sn": result.OutTradeNo}, - }, updates) + // 回调无登录态:先按支付中状态回写;金额校验依赖 order 服务 UpdateOrderDPayStatus 内实现。 + err := updateOrderPayStatus( + l.ctx, + l.svcCtx.OrderSvcName, + result.OutTradeNo, + dao.PayStatusOk, + float64(result.AmountFen)/100, + result.TransactionID, + 0, + ) return err } diff --git a/services/payment/internal/logic/orderRpc.go b/services/payment/internal/logic/orderRpc.go new file mode 100644 index 0000000..52ffb21 --- /dev/null +++ b/services/payment/internal/logic/orderRpc.go @@ -0,0 +1,73 @@ +package logic + +import ( + "context" + "fmt" + + "lone-services/pkg/utils" + orderpb "lone-services/rpc/order/pb" + "lone-services/services/payment/internal/svc" +) + +func getOrderInfo(ctx context.Context, orderSvcName string, userID int64, orderSn string, typ uint8) (*orderpb.OrderInfoResponse, error) { + if orderSvcName == utils.StringEmpty { + return nil, fmt.Errorf("order service not configured") + } + if userID < utils.NumberOne || orderSn == utils.StringEmpty || typ < utils.NumberOne { + return nil, fmt.Errorf("invalid get order params") + } + + cli, err := svc.GetRpcClient(orderSvcName) + if err != nil { + return nil, err + } + client := orderpb.NewOrderClient(cli.Conn()) + info, err := client.GetOrderInfo(ctx, &orderpb.GetOrderInfoRequest{ + UserId: userID, + OrderSn: orderSn, + Type: int32(typ), + }) + if err != nil { + return nil, err + } + if info == nil || info.Id < utils.NumberOne { + return nil, fmt.Errorf("order not found") + } + return info, nil +} + +func updateOrderPayStatus(ctx context.Context, orderSvcName, orderSn string, status uint8, payPrice float64, remitNo string, typ uint8) error { + if orderSvcName == utils.StringEmpty { + return fmt.Errorf("order service not configured") + } + cli, err := svc.GetRpcClient(orderSvcName) + if err != nil { + return err + } + client := orderpb.NewOrderClient(cli.Conn()) + _, err = client.UpdateOrderDPayStatus(ctx, &orderpb.UpdateOrderPayStatusRequest{ + OrderSn: orderSn, + Status: int32(status), + PayPrice: payPrice, + RemitNo: remitNo, + Type: int32(typ), + }) + return err +} + +func orderPayStatus(info *orderpb.OrderInfoResponse) uint8 { + if info == nil { + return 0 + } + return uint8(info.Status) +} + +func orderOutTradeNo(info *orderpb.OrderInfoResponse) string { + if info == nil { + return utils.StringEmpty + } + if info.OutTradeNo != utils.StringEmpty { + return info.OutTradeNo + } + return info.OrderSn +} diff --git a/services/payment/internal/logic/payLogic.go b/services/payment/internal/logic/payLogic.go index 36b0c2a..16bb119 100644 --- a/services/payment/internal/logic/payLogic.go +++ b/services/payment/internal/logic/payLogic.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "math" - "strconv" "lone-services/pkg/modelbase" pkgpay "lone-services/pkg/payment" @@ -12,7 +11,6 @@ import ( payment "lone-services/rpc/payment/pb" "lone-services/services/payment/internal/channel" "lone-services/services/payment/internal/dao" - "lone-services/services/payment/internal/model" "lone-services/services/payment/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -45,22 +43,23 @@ func (l *PayLogic) Pay(in *payment.PayReq) (*payment.Response, error) { client := resolveClient(in.Client, loginUser.ClientCode) channelCode := resolveChannel(in.Channel) - order, err := loadPayableOrder(in.OrderSn, loginUser.ID) + orderInfo, err := getOrderInfo(l.ctx, l.svcCtx.OrderSvcName, loginUser.ID, in.OrderSn, loginUser.Type) if err != nil { l.Errorf("pay load order: %v", err) return failResponse(utils.ErrorNotFund), nil } - if order.Status == dao.PayStatusOk { + if orderPayStatus(orderInfo) == dao.PayStatusOk { return &payment.Response{ Code: int32(utils.ErrorRepeatPayment.GetCode()), Msg: utils.ErrorRepeatPayment.GetMsg(), }, nil } - if order.Status != dao.PayStatusWait && order.Status != dao.PayStatusIn && order.Status != dao.PayStatusFail { + status := orderPayStatus(orderInfo) + if status != dao.PayStatusWait && status != dao.PayStatusIn && status != dao.PayStatusFail { return outResponse(utils.Fail, "订单状态不可支付"), nil } - amountFen := yuanToFen(order.PayPrice) + amountFen := yuanToFen(orderInfo.PayPrice) if amountFen <= 0 { return outResponse(utils.Fail, "支付金额无效"), nil } @@ -97,39 +96,17 @@ func (l *PayLogic) Pay(in *payment.PayReq) (*payment.Response, error) { return outResponse(utils.Fail, err.Error()), nil } - _ = markOrderPaying(in.OrderSn, channelCode, in.OrderSn) + _ = updateOrderPayStatus(l.ctx, l.svcCtx.OrderSvcName, in.OrderSn, dao.PayStatusIn, 0, in.OrderSn, loginUser.Type) return okResponse(result), nil } -func loadPayableOrder(orderSn string, userID int64) (*dao.OrderPayRow, error) { - var row dao.OrderPayRow - err := model.OrderModel{}.Init().GetOne(modelbase.Params{ - Eq: map[string]string{ - "order_sn": orderSn, - }, - }, &row) - if err != nil { - return nil, err - } - if row.Id < utils.NumberOne { - return nil, fmt.Errorf("order not found") - } - if row.UserId > 0 && row.UserId != userID { - return nil, fmt.Errorf("order user mismatch") - } - return &row, nil -} - func loadOpenID(userID int64) (string, error) { var cred dao.UserCredential - err := model.UserCredentialModel{}.Init().GetOne(modelbase.Params{ - Eq: map[string]string{ - "user_id": strconv.FormatInt(userID, 10), - "credential_type": dao.CredentialTypeOpenid, - "status": strconv.Itoa(int(dao.CredentialEnabled)), - }, - }, &cred) + err := modelbase.DB().Table(modelbase.Prefix()+"user_credential"). + Where("user_id = ? AND credential_type = ? AND status = ?", + userID, dao.CredentialTypeOpenid, dao.CredentialEnabled). + Take(&cred).Error if err != nil { return "", err } @@ -139,21 +116,6 @@ func loadOpenID(userID int64) (string, error) { return cred.Identifier, nil } -func markOrderPaying(orderSn, channelCode, outTradeNo string) error { - payType := dao.ChannelToPayType(channelCode) - updates := map[string]any{ - "status": dao.PayStatusIn, - "out_trade_no": outTradeNo, - } - if payType > 0 { - updates["pay_type"] = payType - } - _, err := model.OrderModel{}.Init().Edit(modelbase.Params{ - Eq: map[string]string{"order_sn": orderSn}, - }, updates) - return err -} - func yuanToFen(yuan float64) int64 { return int64(math.Round(yuan * 100)) } diff --git a/services/payment/internal/logic/refundLogic.go b/services/payment/internal/logic/refundLogic.go index ea7e19e..bf85d82 100644 --- a/services/payment/internal/logic/refundLogic.go +++ b/services/payment/internal/logic/refundLogic.go @@ -6,13 +6,11 @@ import ( "strconv" "time" - "lone-services/pkg/modelbase" pkgpay "lone-services/pkg/payment" "lone-services/pkg/utils" payment "lone-services/rpc/payment/pb" "lone-services/services/payment/internal/channel" "lone-services/services/payment/internal/dao" - "lone-services/services/payment/internal/model" "lone-services/services/payment/internal/svc" "github.com/zeromicro/go-zero/core/logx" @@ -45,14 +43,11 @@ func (l *RefundLogic) Refund(in *payment.RefundReq) (*payment.Response, error) { channelCode := resolveChannel(in.Channel) client := resolveClient(utils.StringEmpty, loginUser.ClientCode) - var row dao.OrderPayRow - err := model.OrderModel{}.Init().GetOne(modelbase.Params{ - Eq: map[string]string{"order_sn": in.OrderSn}, - }, &row) - if err != nil || row.Id < utils.NumberOne { + orderInfo, err := getOrderInfo(l.ctx, l.svcCtx.OrderSvcName, loginUser.ID, in.OrderSn, loginUser.Type) + if err != nil { return failResponse(utils.ErrorNotFund), nil } - if row.Status != dao.PayStatusOk { + if orderPayStatus(orderInfo) != dao.PayStatusOk { return outResponse(utils.Fail, "订单未支付,无法退款"), nil } @@ -61,7 +56,7 @@ func (l *RefundLogic) Refund(in *payment.RefundReq) (*payment.Response, error) { return failResponse(utils.ErrorParams), nil } refundFen := yuanToFen(refundYuan) - totalFen := yuanToFen(row.PayPrice) + totalFen := yuanToFen(orderInfo.PayPrice) if refundFen > totalFen { return outResponse(utils.Fail, "退款金额不能大于支付金额"), nil } @@ -71,11 +66,8 @@ func (l *RefundLogic) Refund(in *payment.RefundReq) (*payment.Response, error) { return outResponse(utils.Fail, err.Error()), nil } - outTradeNo := row.OutTradeNo - if outTradeNo == utils.StringEmpty { - outTradeNo = row.OrderSn - } - outRefundNo := fmt.Sprintf("RF%s%d", row.OrderSn, time.Now().UnixNano()) + outTradeNo := orderOutTradeNo(orderInfo) + outRefundNo := fmt.Sprintf("RF%s%d", orderInfo.OrderSn, time.Now().UnixNano()) result, err := ch.Refund(l.ctx, &pkgpay.RefundRequest{ OutTradeNo: outTradeNo,