- 重新设计支付页面UI,采用毛玻璃效果和动态背景- 更新支付接口调用方式,从表单提交改为JSON请求 -优化支付签名验证逻辑,统一错误处理方式 - 修改京东支付接口参数和返回结构体 - 移除OpenTelemetry追踪相关代码 - 添加支付倒计时功能和本地存储支持 - 优化支付按钮加载状态和交互反馈 - 调整HTML结构和CSS样式,提升用户体验
129 lines
3.3 KiB
Go
129 lines
3.3 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"shop/internal/models"
|
|
"shop/internal/traceRouter"
|
|
"shop/internal/utils/client"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// VerifyPaySign 判断sign是否正确
|
|
func VerifyPaySign(ctx context.Context, sign string) (*models.OrderParams, error) {
|
|
m := models.OrderParams{}
|
|
if err := m.Decrypt(ctx, sign); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
traceRouter.Logger.WithContext(ctx).Info("订单参数", zap.Any("订单参数", m))
|
|
|
|
if time.Since(time.Unix(m.GeneratedTime, 0)).Hours() > float64(m.Duration) {
|
|
return nil, errors.New("订单超时")
|
|
}
|
|
|
|
if m.PayKey == "" {
|
|
return nil, errors.New("支付秘钥错误")
|
|
}
|
|
|
|
if m.NotifyUrl == "" {
|
|
return nil, errors.New("通知地址为空")
|
|
}
|
|
|
|
if m.OrderNo == "" {
|
|
return nil, errors.New("订单号为空")
|
|
}
|
|
|
|
return &m, nil
|
|
}
|
|
|
|
// Pay 抽离支付接口
|
|
func Pay(ctx context.Context, m *models.OriginalJdParams, order *models.OrderParams, ip string) (bool, error) {
|
|
marshal, err := json.Marshal(map[string]string{
|
|
"recoveryType": m.RecoveryType,
|
|
"data": m.Chard,
|
|
"cardNo": m.CardNo,
|
|
})
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
scanShop := new(ScanShopController)
|
|
scanShop.Params = map[string]string{
|
|
"orderPeriod": "24",
|
|
"notifyUrl": m.NotifyUrl,
|
|
"orderPrice": m.FactMMValue,
|
|
"orderNo": m.OrderId,
|
|
"productCode": m.ProductCode,
|
|
"exValue": string(marshal),
|
|
"ip": ip,
|
|
"deviceId": m.DeviceId,
|
|
}
|
|
|
|
res := scanShop.Shop(ctx, order.PayKey)
|
|
if res.Code == 200 {
|
|
return true, nil
|
|
}
|
|
|
|
if strings.Contains(res.Msg, "当前订单已存在") {
|
|
return true, nil
|
|
}
|
|
|
|
return false, errors.New(res.Msg)
|
|
}
|
|
|
|
// PayWithJd 京东原生支付
|
|
func PayWithJd(ctx context.Context, orderId, category string, orderAmount float64) (string, error) {
|
|
ctx, span := traceRouter.CreateSpan(ctx, "PayWithJd", "PayWithJd")
|
|
defer span.End()
|
|
|
|
orderResp, err := client.Post(ctx, "http://kami_backend:12401/api/jd-cookie/order/create",
|
|
nil, map[string]any{
|
|
"orderId": orderId,
|
|
"amount": orderAmount,
|
|
"category": category,
|
|
},
|
|
)
|
|
|
|
traceRouter.Logger.WithContext(ctx).Info("发送请求", zap.String("请求地址",
|
|
"http://kami_backend:12401/api/jd-cookie/order/create"), zap.Any("请求参数", map[string]any{
|
|
"merchantOrderId": orderId,
|
|
"orderAmount": orderAmount,
|
|
}))
|
|
|
|
if err != nil {
|
|
traceRouter.Logger.WithContext(ctx).Error("请求失败", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
traceRouter.Logger.WithContext(ctx).Info("请求结果", zap.String("response", orderResp))
|
|
|
|
type V1CardRedeemCookieOrder struct {
|
|
WxPayUrl string `json:"wxPayUrl" dc:"微信支付链接"`
|
|
ExpireTime string `json:"expireTime" dc:"链接过期时间"`
|
|
JdOrderId string `json:"jdOrderId" dc:"京东订单号"`
|
|
}
|
|
|
|
type Response struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data V1CardRedeemCookieOrder `json:"data"`
|
|
}
|
|
|
|
var res Response
|
|
err = json.Unmarshal([]byte(orderResp), &res)
|
|
if err != nil {
|
|
traceRouter.Logger.WithContext(ctx).Error("解析失败", zap.Error(err))
|
|
return "", err
|
|
}
|
|
|
|
traceRouter.Logger.WithContext(ctx).Info("订单拉单失败", zap.Any("订单状态", res.Data),
|
|
zap.String("订单号", res.Data.JdOrderId),
|
|
)
|
|
return res.Data.WxPayUrl, nil
|
|
}
|