feat: integrate unified payment and wallet refunds
This commit is contained in:
61
backend/api/internal/logic/payment/service.go
Normal file
61
backend/api/internal/logic/payment/service.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/config"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
StatusPending = 10
|
||||
StatusPaid = 23
|
||||
StatusClosed = 30
|
||||
)
|
||||
|
||||
type CreateInput struct {
|
||||
RequestNo, BusinessType, BusinessIdentity, UserIdentity string
|
||||
Channel, PayType, Subject, OpenID string
|
||||
Amount int64
|
||||
}
|
||||
|
||||
// Create 创建幂等支付单并向渠道请求客户端调起参数。
|
||||
func Create(ctx context.Context, input CreateInput) (models.PaymentOrder, error) {
|
||||
if input.Amount <= 0 || input.RequestNo == "" || input.BusinessIdentity == "" || input.UserIdentity == "" {
|
||||
return models.PaymentOrder{}, gorm.ErrInvalidData
|
||||
}
|
||||
var existing models.PaymentOrder
|
||||
if err := impl.DBService.Where("business_type = ? AND request_no = ?", input.BusinessType, input.RequestNo).First(&existing).Error; err == nil {
|
||||
if existing.BusinessIdentity != input.BusinessIdentity || existing.Amount != input.Amount || existing.Channel != input.Channel || existing.PayType != input.PayType {
|
||||
return existing, errors.New("idempotency conflict")
|
||||
}
|
||||
return existing, nil
|
||||
}
|
||||
order := models.PaymentOrder{Entity: models.Entity{Identity: models.NewIdentity(), Status: 1}, PaymentStatus: StatusPending,
|
||||
PaymentNo: "PAY" + time.Now().Format("20060102150405.000000"), RequestNo: input.RequestNo, BusinessType: input.BusinessType,
|
||||
BusinessIdentity: input.BusinessIdentity, UserIdentity: input.UserIdentity, MerchantIdentity: "platform", Channel: input.Channel,
|
||||
PayType: input.PayType, Amount: input.Amount, Subject: input.Subject, ExpiresAt: time.Now().Add(time.Duration(config.Spec.Payment.ExpireMinutes) * time.Minute)}
|
||||
args, err := createChannelOrder(ctx, order, input.OpenID)
|
||||
if err != nil {
|
||||
return order, err
|
||||
}
|
||||
order.ClientArgs = args
|
||||
if err = impl.DBService.Create(&order).Error; err != nil {
|
||||
return order, err
|
||||
}
|
||||
return order, nil
|
||||
}
|
||||
|
||||
// PublicResponse 仅返回客户端调起支付所需的非密钥参数。
|
||||
func PublicResponse(order models.PaymentOrder) map[string]any {
|
||||
response := map[string]any{"identity": order.Identity, "payment_no": order.PaymentNo, "payment_status": order.PaymentStatus,
|
||||
"channel": order.Channel, "pay_type": order.PayType, "amount": order.Amount, "client_args": order.ClientArgs, "expires_at": order.ExpiresAt}
|
||||
if order.Channel == "wechat" && order.PayType == "app" {
|
||||
response["app_id"] = config.Spec.Payment.Wechat.AppAppID
|
||||
}
|
||||
return response
|
||||
}
|
||||
Reference in New Issue
Block a user