kra-oa/app/system/internal/service/payment.go

177 lines
8.0 KiB
Go

package service
import (
"context"
"errors"
"kra/app/system/internal/biz"
)
type PaymentService struct{ uc *biz.PaymentUsecase }
func NewPaymentService(uc *biz.PaymentUsecase) *PaymentService { return &PaymentService{uc: uc} }
func (s *PaymentService) Configs(ctx context.Context) ([]*PaymentConfigResponse, error) {
configs, err := s.uc.Configs(ctx)
if err != nil {
return nil, err
}
result := make([]*PaymentConfigResponse, 0, len(configs))
for _, config := range configs {
if config == nil {
continue
}
result = append(result, &PaymentConfigResponse{Provider: config.Provider, Enabled: config.Enabled, Config: config.Values})
}
return result, nil
}
func (s *PaymentService) SaveConfig(ctx context.Context, req *PaymentConfigRequest) error {
if req == nil {
return errors.New("支付配置请求为空")
}
return s.uc.SaveConfig(ctx, &biz.PaymentConfig{Provider: req.Provider, Enabled: req.Enabled, Values: req.Config})
}
func (s *PaymentService) Order(ctx context.Context, provider, tradeNo string) (*PaymentOrderResponse, error) {
order, err := s.uc.Order(ctx, provider, tradeNo)
if err != nil {
return nil, err
}
return &PaymentOrderResponse{
ID: order.ID,
Provider: order.Provider, TradeNo: order.TradeNo, ProviderTradeNo: order.ProviderTradeNo,
BusinessType: order.BusinessType, BusinessID: order.BusinessID, Subject: order.Subject,
PaymentMode: order.PaymentMode, OriginalAmount: order.OriginalAmount,
Amount: order.Amount, PaidAmount: order.PaidAmount, PayerPaidAmount: order.PayerPaidAmount,
CashPaidAmount: order.CashPaidAmount, PointPaidAmount: order.PointPaidAmount,
DiscountAmount: order.DiscountAmount, ProviderDiscountAmount: order.ProviderDiscountAmount,
MerchantDiscountAmount: order.MerchantDiscountAmount, SettlementAmount: order.SettlementAmount,
Currency: order.Currency, PayerCurrency: order.PayerCurrency, AmountBreakdownKnown: order.AmountBreakdownKnown,
PaymentStatus: order.PaymentStatus, ProviderStatus: order.ProviderStatus, FulfillmentStatus: order.FulfillmentStatus,
RefundStatus: order.RefundStatus, RefundedAmount: order.RefundedAmount, RefundRequestedAmount: order.RefundRequestedAmount, RefundNo: order.RefundNo, LastError: order.LastError,
CreatedAt: order.CreatedAt, UpdatedAt: order.UpdatedAt, PaidAt: order.PaidAt,
FulfilledAt: order.FulfilledAt, RefundedAt: order.RefundedAt,
}, nil
}
func (s *PaymentService) Orders(ctx context.Context, req *PaymentOrderListRequest) ([]*PaymentOrderResponse, int64, int, int, error) {
if req == nil {
return nil, 0, 1, 10, errors.New("支付订单列表请求为空")
}
page, pageSize := req.Page, req.PageSize
if page <= 0 {
page = 1
}
if pageSize <= 0 {
pageSize = 10
}
items, total, err := s.uc.Orders(ctx, page, pageSize, biz.PaymentOrderFilter{
Provider: req.Provider, TradeNo: req.TradeNo, BusinessType: req.BusinessType,
BusinessID: req.BusinessID, PaymentStatus: req.PaymentStatus, RefundStatus: req.RefundStatus,
})
if err != nil {
return nil, 0, page, pageSize, err
}
result := make([]*PaymentOrderResponse, 0, len(items))
for _, item := range items {
converted, convertErr := paymentOrderResponse(item)
if convertErr != nil {
return nil, 0, page, pageSize, convertErr
}
result = append(result, converted)
}
return result, total, page, pageSize, nil
}
func paymentOrderResponse(order *biz.PaymentOrder) (*PaymentOrderResponse, error) {
if order == nil {
return nil, errors.New("支付订单为空")
}
return &PaymentOrderResponse{
ID: order.ID, Provider: order.Provider, TradeNo: order.TradeNo, ProviderTradeNo: order.ProviderTradeNo,
BusinessType: order.BusinessType, BusinessID: order.BusinessID, Subject: order.Subject,
PaymentMode: order.PaymentMode, OriginalAmount: order.OriginalAmount, Amount: order.Amount, PaidAmount: order.PaidAmount,
PayerPaidAmount: order.PayerPaidAmount, CashPaidAmount: order.CashPaidAmount, PointPaidAmount: order.PointPaidAmount,
DiscountAmount: order.DiscountAmount, ProviderDiscountAmount: order.ProviderDiscountAmount,
MerchantDiscountAmount: order.MerchantDiscountAmount, SettlementAmount: order.SettlementAmount,
Currency: order.Currency, PayerCurrency: order.PayerCurrency, AmountBreakdownKnown: order.AmountBreakdownKnown,
PaymentStatus: order.PaymentStatus, ProviderStatus: order.ProviderStatus, FulfillmentStatus: order.FulfillmentStatus,
RefundStatus: order.RefundStatus, RefundedAmount: order.RefundedAmount, RefundRequestedAmount: order.RefundRequestedAmount,
RefundNo: order.RefundNo, LastError: order.LastError, CreatedAt: order.CreatedAt, UpdatedAt: order.UpdatedAt,
PaidAt: order.PaidAt, FulfilledAt: order.FulfilledAt, RefundedAt: order.RefundedAt,
}, nil
}
func (s *PaymentService) Create(ctx context.Context, req *PaymentRequest) (*PaymentResultResponse, error) {
if req == nil {
return nil, errors.New("支付请求为空")
}
result, err := s.uc.Create(ctx, &biz.PaymentRequest{
Provider: req.Provider, TradeNo: req.TradeNo, Subject: req.Subject,
Amount: req.Amount, OriginalAmount: req.OriginalAmount, Currency: req.Currency,
NotifyURL: req.NotifyURL, ReturnURL: req.ReturnURL, ClientIP: req.ClientIP,
Extra: req.Extra, BusinessType: req.BusinessType, BusinessID: req.BusinessID,
PaymentMode: req.PaymentMode,
})
return paymentResultResponse(result), err
}
func (s *PaymentService) Query(ctx context.Context, req *PaymentQueryRequest) (*PaymentResultResponse, error) {
if req == nil {
return nil, errors.New("支付查询请求为空")
}
result, err := s.uc.Query(ctx, req.Provider, req.TradeNo)
return paymentResultResponse(result), err
}
func (s *PaymentService) Refund(ctx context.Context, req *PaymentRefundRequest) (*PaymentResultResponse, error) {
if req == nil {
return nil, errors.New("支付退款请求为空")
}
result, err := s.uc.Refund(ctx, req.Provider, req.TradeNo, req.Amount)
return paymentResultResponse(result), err
}
func (s *PaymentService) Fulfill(ctx context.Context, req *PaymentFulfillRequest) (*PaymentResultResponse, error) {
if req == nil {
return nil, errors.New("支付发货请求为空")
}
result, err := s.uc.Fulfill(ctx, req.Provider, req.TradeNo)
return paymentResultResponse(result), err
}
func (s *PaymentService) Callback(ctx context.Context, req *PaymentCallbackRequest) (PaymentCallbackAck, error) {
if req == nil {
return paymentCallbackAckResponse(biz.DefaultPaymentCallbackAck("", false)), errors.New("支付回调请求为空")
}
result, err := s.uc.Callback(ctx, &biz.PaymentCallback{Provider: req.Provider, Headers: req.Headers, Body: req.Body, Query: req.Query})
if err != nil {
return paymentCallbackAckResponse(biz.CallbackFailure(err, biz.DefaultPaymentCallbackAck(req.Provider, false))), err
}
ack := biz.DefaultPaymentCallbackAck(req.Provider, true)
if result != nil && result.SuccessAck.StatusCode != 0 {
ack = result.SuccessAck
}
return paymentCallbackAckResponse(ack), nil
}
func DefaultPaymentCallbackAck(provider string, success bool) PaymentCallbackAck {
return paymentCallbackAckResponse(biz.DefaultPaymentCallbackAck(provider, success))
}
func paymentResultResponse(result *biz.PaymentResult) *PaymentResultResponse {
if result == nil {
return nil
}
return &PaymentResultResponse{
Provider: result.Provider, Status: result.Status, TradeNo: result.TradeNo,
ProviderTradeNo: result.ProviderTradeNo, Amount: result.Amount,
PayerPaidAmount: result.PayerPaidAmount, CashPaidAmount: result.CashPaidAmount,
PointPaidAmount: result.PointPaidAmount, DiscountAmount: result.DiscountAmount,
ProviderDiscountAmount: result.ProviderDiscountAmount,
MerchantDiscountAmount: result.MerchantDiscountAmount, SettlementAmount: result.SettlementAmount,
Currency: result.Currency, PayerCurrency: result.PayerCurrency,
AmountBreakdownKnown: result.AmountBreakdownKnown, Duplicate: result.Duplicate,
Payload: result.Payload, OrderStatus: result.OrderStatus,
FulfillmentStatus: result.FulfillmentStatus, RefundStatus: result.RefundStatus,
}
}
func paymentCallbackAckResponse(ack biz.PaymentCallbackAck) PaymentCallbackAck {
return PaymentCallbackAck{StatusCode: ack.StatusCode, ContentType: ack.ContentType, Body: ack.Body}
}