feat(camel): 新增骆驼淘宝卡片发送及支付回调功能
- 新增 card_sender 包中 SendCardTaskTypeCamel 实现,支持订单创建和卡片提交接口调用 - 实现支付回调逻辑,更新订单状态和金额校验,并返回处理结果 - 在第三方供应商模块添加 CamelImpl,实现卡片发送、订单扫描、支付通知等接口 - 注册骆驼淘宝供应商实例,支持通过渠道码获取供应商实现 - 调整其他相关文件,实现骆驼淘宝支付渠道的路由和状态处理 - 补充单元测试,验证骆驼淘宝卡片发送功能正确性 - 优化支付回调失败信息处理,增强日志追踪与错误提示
This commit is contained in:
@@ -74,4 +74,5 @@ func init() {
|
||||
web.Router("/nuclear/notify", &third_party.NuclearImpl{}, "*:PayNotify")
|
||||
web.Router("/origin/notify", &third_party.OriginImpl{}, "*:PayNotify")
|
||||
web.Router("/lianIns/notify", &third_party.LianInsImpl{}, "*:PayNotify")
|
||||
web.Router("/camel/notify", &third_party.CamelImpl{}, "*:PayNotify")
|
||||
}
|
||||
|
||||
283
internal/service/supplier/third_party/camel.go
vendored
Normal file
283
internal/service/supplier/third_party/camel.go
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
package third_party
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"gateway/internal/config"
|
||||
"gateway/internal/otelTrace"
|
||||
"gateway/internal/service"
|
||||
"gateway/internal/service/supplier"
|
||||
"gateway/internal/service/supplier/third_party/pool/card_sender"
|
||||
|
||||
"gateway/internal/models/merchant"
|
||||
"gateway/internal/models/merchant_deploy"
|
||||
"gateway/internal/models/order"
|
||||
"gateway/internal/models/payfor"
|
||||
"gateway/internal/models/road"
|
||||
"gateway/internal/models/supply_model"
|
||||
"strconv"
|
||||
|
||||
"github.com/beego/beego/v2/client/httplib"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/beego/beego/v2/server/web"
|
||||
"github.com/widuu/gojson"
|
||||
)
|
||||
|
||||
type CamelImpl struct {
|
||||
web.Controller
|
||||
}
|
||||
|
||||
// HasDependencyHTML 是否有单独的支付页面
|
||||
func (c *CamelImpl) HasDependencyHTML() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *CamelImpl) SendCard(ctx context.Context, jsonStr string, cardInfo supplier.RedeemCardInfo, attach string, merchantInfo merchant.MerchantInfo, roadInfo road.RoadInfo) (bool, string) {
|
||||
returnIfAmountErr := gojson.Json(roadInfo.Params).Get("returnIfAmountErr").Tostring()
|
||||
orderAmount, err := (&cardTypeQuery{
|
||||
OrderNo: attach,
|
||||
QueryType: gojson.Json(roadInfo.Params).Get("queryType").Tostring(),
|
||||
CardNo: cardInfo.CardNo,
|
||||
CardPwd: cardInfo.Data,
|
||||
Balance: cardInfo.GetFaceTypeFloat(ctx),
|
||||
}).GetBalance(ctx)
|
||||
if returnIfAmountErr == "1" && err != nil {
|
||||
return false, err.Error()
|
||||
}
|
||||
cardInfo.FaceType = strconv.FormatFloat(orderAmount, 'f', 2, 64)
|
||||
merchantDeploy := merchant_deploy.GetMerchantDeployByUidAndRoadUid(ctx, merchantInfo.MerchantUid, roadInfo.RoadUid)
|
||||
if merchantDeploy.MerchantUid == "" {
|
||||
return false, "商户不存在"
|
||||
}
|
||||
if merchantDeploy.SubmitStrategy == merchant_deploy.SUBMIT_STRATEGY_POOL {
|
||||
if err := orderPoolService.PushOrder(ctx, card_sender.SendCardTask{
|
||||
CardInfo: cardInfo,
|
||||
RoadUid: roadInfo.RoadUid,
|
||||
LocalOrderID: attach,
|
||||
SendCardTaskType: card_sender.SendCardTaskTypeEnumCamel,
|
||||
NeedQuery: gojson.Json(roadInfo.Params).Get("needQuery").Tostring() == "1",
|
||||
}); err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("推送订单失败", zap.Error(err))
|
||||
return false, err.Error()
|
||||
}
|
||||
return true, "订单已提交"
|
||||
}
|
||||
if err := orderPoolService.SubmitOrder(ctx, card_sender.SendCardTask{
|
||||
CardInfo: cardInfo,
|
||||
RoadUid: roadInfo.RoadUid,
|
||||
LocalOrderID: attach,
|
||||
SendCardTaskType: card_sender.SendCardTaskTypeEnumCamel,
|
||||
NeedQuery: gojson.Json(roadInfo.Params).Get("needQuery").Tostring() == "1",
|
||||
}); err != nil {
|
||||
return false, err.Error()
|
||||
}
|
||||
return true, "订单已提交"
|
||||
}
|
||||
|
||||
func (c *CamelImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
|
||||
ctx, span := otelTrace.Span(ctx, "FlyFishImpl", "FlyFishImpl.Scan", trace.WithAttributes(
|
||||
attribute.String("bankOrderId", orderInfo.BankOrderId),
|
||||
attribute.String("merchantUid", orderInfo.MerchantUid),
|
||||
attribute.String("exValue", orderInfo.ExValue),
|
||||
))
|
||||
defer span.End()
|
||||
cdata := supplier.RedeemCardInfo{}
|
||||
err := json.Unmarshal([]byte(orderInfo.ExValue), &cdata)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("格式化数据失败", zap.String("ExValue", orderInfo.ExValue))
|
||||
return supplier.ScanData{Status: "-1", Msg: "订单有误,请稍后再试"}
|
||||
}
|
||||
ok, str := c.SendCard(ctx, roadInfo.Params, cdata, orderInfo.BankOrderId, merchantInfo, roadInfo)
|
||||
var scanData supplier.ScanData
|
||||
if !ok {
|
||||
scanData = supplier.ScanData{
|
||||
Status: "-1",
|
||||
Msg: "失败:" + str,
|
||||
BankNo: orderInfo.MerchantOrderId,
|
||||
OrderNo: orderInfo.BankOrderId,
|
||||
ReturnData: str,
|
||||
}
|
||||
return scanData
|
||||
}
|
||||
scanData.Status = "00"
|
||||
scanData.OrderNo = orderInfo.BankOrderId
|
||||
scanData.BankNo = orderInfo.MerchantOrderId
|
||||
scanData.OrderPrice = strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64)
|
||||
scanData.ReturnData = str
|
||||
return scanData
|
||||
}
|
||||
|
||||
func (c *CamelImpl) PayNotify() {
|
||||
ctx := c.Ctx.Request.Context()
|
||||
ctx, span := otelTrace.Span(ctx, "EggplantImpl", "CamelImpl.PayNotify")
|
||||
defer span.End()
|
||||
respData := struct {
|
||||
MchId string `json:"mchId" form:"mchId"`
|
||||
MchOrderNo string `json:"mchOrderNo" form:"mchOrderNo"`
|
||||
ProductId string `json:"productId" form:"productId"`
|
||||
OrderAmount string `json:"orderAmount" form:"orderAmount"`
|
||||
PayOrderId string `json:"payOrderId" form:"payOrderId"`
|
||||
PaySuccessTime string `json:"paySuccessTime" form:"paySuccessTime"`
|
||||
Sign string `json:"sign" form:"sign"`
|
||||
Extra string `json:"extra" form:"extra"`
|
||||
}{}
|
||||
err := c.Bind(&respData)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("回调数据解析失败", zap.Error(err))
|
||||
c.Ctx.WriteString("FAIL")
|
||||
return
|
||||
}
|
||||
otelTrace.Logger.WithContext(ctx).Info("回调通知", zap.Any("req", respData))
|
||||
|
||||
localId, err := orderPoolService.GetLocalIdByOrderId(ctx, respData.MchOrderNo)
|
||||
var orderInfo order.OrderInfo
|
||||
if err != nil {
|
||||
orderInfo = order.GetOrderByPoolOrderId(ctx, respData.MchOrderNo)
|
||||
if orderInfo.Id == 0 {
|
||||
otelTrace.Logger.WithContext(ctx).Error("获取本地订单ID失败", zap.Error(err))
|
||||
c.Ctx.WriteString("FAIL")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
orderInfo = order.GetOrderByBankOrderId(ctx, localId)
|
||||
}
|
||||
|
||||
if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
|
||||
otelTrace.Logger.WithContext(ctx).Error("回调的订单号不存在")
|
||||
c.Ctx.WriteString("FAIL")
|
||||
return
|
||||
}
|
||||
|
||||
if orderInfo.Status != "wait" {
|
||||
otelTrace.Logger.WithContext(ctx).Error("订单状态不正确", zap.String("status", orderInfo.Status),
|
||||
zap.String("bankOrderId", orderInfo.BankOrderId),
|
||||
)
|
||||
c.Ctx.WriteString("订单已经回调")
|
||||
return
|
||||
}
|
||||
|
||||
roadInfo := road.GetRoadInfoByRoadUid(ctx, orderInfo.RoadUid)
|
||||
if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 {
|
||||
otelTrace.Logger.WithContext(ctx).Error("支付通道已经关系或者删除,不进行回调")
|
||||
c.Ctx.WriteString("FAIL")
|
||||
return
|
||||
}
|
||||
inPrice, err := convertor.ToFloat(respData.OrderAmount)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("回调的金额格式化失败", zap.Error(err))
|
||||
c.Ctx.WriteString("FAIL")
|
||||
return
|
||||
}
|
||||
|
||||
isOk := false
|
||||
if inPrice/100 == orderInfo.OrderAmount {
|
||||
isOk = service.SolvePaySuccess(ctx, orderInfo.BankOrderId, orderInfo.OrderAmount, orderInfo.MerchantUid, "支付成功")
|
||||
} else {
|
||||
SolvePaySuccessByAmountDifferent(ctx, orderInfo.BankOrderId, inPrice, orderInfo.BankOrderId, convertor.ToString(respData))
|
||||
}
|
||||
// TODO 订单支付成功
|
||||
if isOk {
|
||||
c.Ctx.WriteString("SUCCESS")
|
||||
} else {
|
||||
c.Ctx.WriteString("FAIL")
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func (c *CamelImpl) PayQuery(orderInfo order.OrderInfo, roadInfo road.RoadInfo) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *CamelImpl) PayQueryV2(orderInfo order.OrderInfo, roadInfo road.RoadInfo) supply_model.MsgModel {
|
||||
return supply_model.RemoteDataErr
|
||||
}
|
||||
|
||||
func (c *CamelImpl) PayFor(info payfor.PayforInfo) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *CamelImpl) PayForQuery(payFor payfor.PayforInfo) (string, string) {
|
||||
cfg := config.Config{}
|
||||
url1, err := cfg.GetMFCardQueryUrl()
|
||||
if err != nil {
|
||||
return config.PAYFOR_FAIL, ""
|
||||
}
|
||||
ctx := context.Background()
|
||||
params := map[string]string{}
|
||||
params["order_id"] = payFor.BankOrderId
|
||||
params["app_key"] = gojson.Json("").Get("appKey").Tostring()
|
||||
|
||||
req := httplib.Post(url1)
|
||||
marshal, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("Map转化为byte数组失败,异常。", zap.Error(err))
|
||||
// fmt.Printf("Map转化为byte数组失败,异常:%s\n",zap.Error(err))
|
||||
return config.PAYFOR_FAIL, "内部错误请稍后再试试"
|
||||
}
|
||||
otelTrace.Logger.WithContext(ctx).Info("请求参数" + string(marshal))
|
||||
req.Header("Content-Type", "application/json")
|
||||
req.Body(marshal)
|
||||
req.Header("Accept-Charset", "utf-8")
|
||||
|
||||
response, err := req.String()
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("MF GetToken 请求失败:", zap.Error(err))
|
||||
return config.PAYFOR_FAIL, ""
|
||||
}
|
||||
|
||||
otelTrace.Logger.WithContext(ctx).Info("远端请求返回数据", zap.String("response", response))
|
||||
|
||||
if gojson.Json(response).Get("code").Tostring() == "" {
|
||||
otelTrace.Logger.WithContext(ctx).Error("远程调用失败")
|
||||
return config.PAYFOR_BANKING, ""
|
||||
}
|
||||
|
||||
if gojson.Json(response).Get("code").Tostring() == "0" {
|
||||
|
||||
type data struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
CardNo string `json:"card_no"`
|
||||
CardPwd string `json:"card_pwd"`
|
||||
Status int `json:"status"`
|
||||
RspInfo string `json:"rsp_info"`
|
||||
FaceVal int `json:"face_val"`
|
||||
Amount int `json:"amount"`
|
||||
Discount string `json:"discount"`
|
||||
}
|
||||
|
||||
var d data
|
||||
|
||||
err2 := json.Unmarshal([]byte(gojson.Json(response).Get("data").Tostring()), &d)
|
||||
if err2 != nil {
|
||||
return config.PAYFOR_FAIL, ""
|
||||
}
|
||||
|
||||
if d.Status == 9 {
|
||||
return config.PAYFOR_SUCCESS, ""
|
||||
}
|
||||
|
||||
if d.Status == 4 {
|
||||
return config.PAYFOR_BANKING, ""
|
||||
}
|
||||
|
||||
if d.Status == 7 || d.Status == 8 {
|
||||
return config.PAYFOR_FAIL, ""
|
||||
}
|
||||
}
|
||||
|
||||
otelTrace.Logger.WithContext(ctx).Error("远程调用失败")
|
||||
return config.PAYFOR_BANKING, ""
|
||||
}
|
||||
|
||||
func (c *CamelImpl) BalanceQuery(roadInfo road.RoadInfo) float64 {
|
||||
return 0.00
|
||||
}
|
||||
|
||||
func (c *CamelImpl) PayForNotify() string {
|
||||
return ""
|
||||
}
|
||||
@@ -224,14 +224,18 @@ func (c *FavorableCloudsCardImpl) PayNotify() {
|
||||
}
|
||||
cdata := supplier.RedeemCardInfo{}
|
||||
_ = json.Unmarshal([]byte(orderInfo.ExValue), &cdata)
|
||||
errMsg := "支付失败"
|
||||
if gojson.Json(roadInfo.Params).Get("jvnkaQuery").Tostring() == "1" {
|
||||
_, _ = client.NewHeePayClient().ToString(ctx, &client.QueryCardInput{
|
||||
retMsg, _ := client.NewHeePayClient().ToString(ctx, &client.QueryCardInput{
|
||||
OrderId: orderInfo.BankOrderId,
|
||||
CardNumber: cdata.CardNo,
|
||||
CardPassword: cdata.Data,
|
||||
})
|
||||
if retMsg != "" {
|
||||
errMsg = retMsg
|
||||
}
|
||||
}
|
||||
isOk := service.SolvePayFail(ctx, orderInfo.BankOrderId, orderInfo.BankOrderId, "支付失败")
|
||||
isOk := service.SolvePayFail(ctx, orderInfo.BankOrderId, orderInfo.BankOrderId, errMsg)
|
||||
if isOk {
|
||||
c.Ctx.WriteString("success")
|
||||
} else {
|
||||
|
||||
@@ -61,6 +61,7 @@ var supplierCode2Name = map[string]string{
|
||||
"SDPAY": "闪电核销平台",
|
||||
"ORIGIN": "山禾",
|
||||
"LIANINS": "燕子核销平台",
|
||||
"CAMEL": "骆驼淘宝",
|
||||
}
|
||||
|
||||
var registerSupplier = make(map[string]supplier.PayInterface)
|
||||
@@ -153,6 +154,8 @@ func init() {
|
||||
logs.Notice(CheckSupplierByCode("ORIGIN"))
|
||||
registerSupplier["LIANINS"] = new(LianInsImpl)
|
||||
logs.Notice(CheckSupplierByCode("LIANINS"))
|
||||
registerSupplier["CAMEL"] = new(CamelImpl)
|
||||
logs.Notice(CheckSupplierByCode("CAMEL"))
|
||||
}
|
||||
|
||||
func GetPaySupplierByCode(code string) supplier.PayInterface {
|
||||
|
||||
36
internal/service/supplier/third_party/origin.go
vendored
36
internal/service/supplier/third_party/origin.go
vendored
@@ -189,25 +189,25 @@ func (c *OriginImpl) PayNotify() {
|
||||
} else {
|
||||
c.Ctx.WriteString("FAIL")
|
||||
}
|
||||
return
|
||||
}
|
||||
cdata := supplier.RedeemCardInfo{}
|
||||
_ = json.Unmarshal([]byte(orderInfo.ExValue), &cdata)
|
||||
errMsg := ""
|
||||
if _, err2 := (&cardTypeQuery{
|
||||
OrderNo: orderInfo.BankOrderId,
|
||||
QueryType: gojson.Json(roadInfo.Params).Get("queryType").Tostring(),
|
||||
CardNo: cdata.CardNo,
|
||||
CardPwd: cdata.Data,
|
||||
Balance: cdata.GetFaceTypeFloat(ctx),
|
||||
}).GetBalance(ctx); err2 != nil {
|
||||
errMsg = err2.Error()
|
||||
}
|
||||
isOk := service.SolvePayFail(ctx, orderInfo.BankOrderId, response.PayOrderId, errMsg)
|
||||
if isOk {
|
||||
c.Ctx.WriteString("success")
|
||||
} else {
|
||||
cdata := supplier.RedeemCardInfo{}
|
||||
_ = json.Unmarshal([]byte(orderInfo.ExValue), &cdata)
|
||||
errMsg := ""
|
||||
if _, err2 := (&cardTypeQuery{
|
||||
OrderNo: orderInfo.BankOrderId,
|
||||
QueryType: gojson.Json(roadInfo.Params).Get("queryType").Tostring(),
|
||||
CardNo: cdata.CardNo,
|
||||
CardPwd: cdata.Data,
|
||||
Balance: cdata.GetFaceTypeFloat(ctx),
|
||||
}).GetBalance(ctx); err2 != nil {
|
||||
errMsg = err2.Error()
|
||||
}
|
||||
isOk := service.SolvePayFail(ctx, orderInfo.BankOrderId, response.PayOrderId, errMsg)
|
||||
if isOk {
|
||||
c.Ctx.WriteString("success")
|
||||
} else {
|
||||
c.Ctx.WriteString("FAIL")
|
||||
}
|
||||
c.Ctx.WriteString("FAIL")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
202
internal/service/supplier/third_party/pool/card_sender/camel.go
vendored
Normal file
202
internal/service/supplier/third_party/pool/card_sender/camel.go
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
package card_sender
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gateway/internal/config"
|
||||
"gateway/internal/models/road"
|
||||
"gateway/internal/otelTrace"
|
||||
"gateway/internal/utils"
|
||||
"gateway/internal/utils/useragent"
|
||||
"github.com/widuu/gojson"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dubonzi/otelresty"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type SendCardTaskTypeCamel struct {
|
||||
sendCardTaskTypeSendCardTaskBase
|
||||
}
|
||||
|
||||
func (s *SendCardTaskTypeCamel) CreateOrder(ctx context.Context, roadUid string, faceValue float64) (OrderPoolItem, error) {
|
||||
orderPoolItem := OrderPoolItem{}
|
||||
orderId := utils.GenerateId()
|
||||
cfg := config.Config{}
|
||||
roadInfo := road.GetRoadInfoByRoadUid(ctx, roadUid)
|
||||
|
||||
formData := map[string]string{
|
||||
"mchId": gojson.Json(roadInfo.Params).Get("mchId").Tostring(),
|
||||
"mchOrderNo": orderId,
|
||||
"productId": gojson.Json(roadInfo.Params).Get("productId").Tostring(),
|
||||
"orderAmount": fmt.Sprintf("%.0f", faceValue*100),
|
||||
"notifyUrl": fmt.Sprintf("%s%s", cfg.GatewayAddr(), "/camel/notify"),
|
||||
"clientIp": utils.GenerateIpv4(),
|
||||
"device": "android",
|
||||
}
|
||||
|
||||
formData["sign"] = s.sign(ctx, formData, gojson.Json(roadInfo.Params).Get("key").Tostring())
|
||||
|
||||
client := resty.New().SetTimeout(time.Second * 10).SetRetryCount(2).SetRetryMaxWaitTime(time.Second * 3)
|
||||
otelresty.TraceClient(client)
|
||||
|
||||
createdOrderUrl := "http://47.243.53.92:8089/api/pay/create_order"
|
||||
response, err := client.R().SetContext(ctx).SetFormData(formData).Post(createdOrderUrl)
|
||||
if err != nil {
|
||||
return orderPoolItem, errors.New("请求失败")
|
||||
}
|
||||
resp := struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data struct {
|
||||
PayOrderId string `json:"payOrderId"`
|
||||
OrderAmount int `json:"orderAmount"`
|
||||
PayUrl string `json:"payUrl"`
|
||||
} `json:"data"`
|
||||
}{}
|
||||
otelTrace.Logger.WithContext(ctx).Info("请求响应", zap.Any("formData", formData), zap.String("body", response.String()))
|
||||
|
||||
err = json.Unmarshal(response.Body(), &resp)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err))
|
||||
return orderPoolItem, errors.New("返回数据格式错误")
|
||||
}
|
||||
|
||||
if resp.Code != 200 {
|
||||
otelTrace.Logger.WithContext(ctx).Error("请求失败", zap.String("msg", resp.Message))
|
||||
return orderPoolItem, errors.New(resp.Message)
|
||||
}
|
||||
orderPoolItem = OrderPoolItem{
|
||||
OrderID: orderId,
|
||||
PayURL: resp.Data.PayUrl,
|
||||
RoadUid: roadUid,
|
||||
ProductCode: "",
|
||||
CreateTime: time.Now(),
|
||||
FaceValue: faceValue,
|
||||
DispatchCount: 0,
|
||||
SendCardTaskType: SendCardTaskTypeEnumCareless,
|
||||
RemoteOrderID: resp.Data.PayOrderId,
|
||||
}
|
||||
return orderPoolItem, nil
|
||||
}
|
||||
|
||||
func (s *SendCardTaskTypeCamel) channelOne(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error {
|
||||
ctx, span := otelTrace.Span(ctx, "SendCardTaskTypeCareless", "HandleSendCardTask", trace.WithAttributes(
|
||||
attribute.String("bankOrderId", task.LocalOrderID),
|
||||
attribute.String("cardNo", task.CardInfo.CardNo),
|
||||
attribute.String("cardPassword", task.CardInfo.Data),
|
||||
attribute.String("orderId", orderItem.OrderID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
payUrl, err := url.Parse(orderItem.PayURL)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("返回结果", zap.Error(err))
|
||||
return errors.New("提交链接解析失败")
|
||||
}
|
||||
|
||||
// 转换为Golang代码
|
||||
generateNonce := func() string {
|
||||
return strconv.FormatInt(time.Now().UnixMilli(), 36) +
|
||||
strconv.FormatInt(rand.Int63(), 36)[2:]
|
||||
}
|
||||
|
||||
sessionToken := generateNonce()
|
||||
requestToken := generateNonce()
|
||||
|
||||
client := resty.New().SetHeaders(map[string]string{
|
||||
"User-Agent": useragent.GetUserAgentByPlatform(useragent.PlatformPhone),
|
||||
"X-Request-Nonce": requestToken,
|
||||
"x-requested-with": "XMLHttpRequest",
|
||||
"X-Session-Token": sessionToken,
|
||||
"referer": payUrl.String(),
|
||||
})
|
||||
otelresty.TraceClient(client)
|
||||
|
||||
reqBody := struct {
|
||||
ChannelId string `json:"channelId"`
|
||||
OrderNo string `json:"orderNo"`
|
||||
Amount string `json:"amount"`
|
||||
CardNumber string `json:"cardNumber"`
|
||||
CardPassword string `json:"cardPassword"`
|
||||
SessionToken string `json:"sessionToken"`
|
||||
RequestNonce string `json:"requestNonce"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}{
|
||||
ChannelId: payUrl.Query().Get("channelId"),
|
||||
OrderNo: payUrl.Query().Get("orderNo"),
|
||||
Amount: payUrl.Query().Get("amount"),
|
||||
CardNumber: utils.Base64Encode([]byte(task.CardInfo.CardNo + sessionToken)),
|
||||
CardPassword: utils.Base64Encode([]byte(task.CardInfo.Data + sessionToken)),
|
||||
SessionToken: sessionToken,
|
||||
RequestNonce: requestToken,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
}
|
||||
response, err := client.R().SetContext(ctx).SetBody(reqBody).Post("http://47.243.53.92:8089/api/payment/submit")
|
||||
if err != nil {
|
||||
return errors.New("请求失败")
|
||||
}
|
||||
respData := struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
SubmitCount int `json:"submitCount"`
|
||||
MaxAttemptsReached bool `json:"maxAttemptsReached"`
|
||||
ErrorMessage string `json:"errorMessage"`
|
||||
OrderStatus string `json:"orderStatus"`
|
||||
MaxCount int `json:"maxCount"`
|
||||
PaymentStatus string `json:"paymentStatus"`
|
||||
} `json:"data,omitempty"`
|
||||
Message string `json:"message"`
|
||||
}{}
|
||||
otelTrace.Logger.WithContext(ctx).Info("结果", zap.Any("response", response.String()), zap.Any("params", reqBody))
|
||||
err = json.Unmarshal(response.Body(), &respData)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err))
|
||||
return errors.New("返回数据格式错误")
|
||||
}
|
||||
if respData.Code != 200 {
|
||||
otelTrace.Logger.WithContext(ctx).Error("请求失败", zap.String("msg", respData.Message))
|
||||
return errors.New(respData.Message)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SendCardTaskTypeCamel) HandleSendCardTask(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error {
|
||||
ctx, span := otelTrace.Span(ctx, "SendCardTaskTypeCareless", "SendCardTaskTypeCareless.HandleSendCardTask", trace.WithAttributes(
|
||||
attribute.String("bankOrderId", task.LocalOrderID),
|
||||
attribute.String("cardNo", task.CardInfo.CardNo),
|
||||
attribute.String("cardPassword", task.CardInfo.Data),
|
||||
attribute.String("orderId", orderItem.OrderID),
|
||||
))
|
||||
defer span.End()
|
||||
if strings.Contains(orderItem.PayURL, "47.243.53.92") {
|
||||
return s.channelOne(ctx, orderItem, task)
|
||||
}
|
||||
return errors.New("不支持的渠道")
|
||||
}
|
||||
|
||||
func (s *SendCardTaskTypeCamel) sign(ctx context.Context, params map[string]string, secret string) string {
|
||||
keys := maputil.Keys(params)
|
||||
sort.Strings(keys)
|
||||
signD := ""
|
||||
for _, key := range keys {
|
||||
signD += key + "=" + params[key] + "&"
|
||||
}
|
||||
signD += "key=" + secret
|
||||
return utils.EncodeMd5Str(signD)
|
||||
}
|
||||
|
||||
func (s *SendCardTaskTypeCamel) QueryOrder(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error {
|
||||
return nil
|
||||
}
|
||||
18
internal/service/supplier/third_party/pool/card_sender/camel_test.go
vendored
Normal file
18
internal/service/supplier/third_party/pool/card_sender/camel_test.go
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package card_sender
|
||||
|
||||
import (
|
||||
"gateway/internal/service/supplier"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSendCardTaskTypeCamel_CreateOrder(t *testing.T) {
|
||||
// 转换为Golang代码
|
||||
orderInfo, _ := (&SendCardTaskTypeCamel{}).CreateOrder(t.Context(), "123", 10)
|
||||
(&SendCardTaskTypeCamel{}).HandleSendCardTask(t.Context(), orderInfo, SendCardTask{
|
||||
CardInfo: supplier.RedeemCardInfo{
|
||||
CardNo: "2250920203626440063",
|
||||
Data: "2250920203626440063",
|
||||
},
|
||||
})
|
||||
t.Log(orderInfo)
|
||||
}
|
||||
@@ -48,6 +48,7 @@ const (
|
||||
SendCardTaskTypeEnumSdPay SendCardTaskEnum = "SDPAY"
|
||||
SendCardTaskTypeEnumOrigin SendCardTaskEnum = "ORIGIN"
|
||||
SendCardTaskTypeEnumLianIns SendCardTaskEnum = "LIANINS"
|
||||
SendCardTaskTypeEnumCamel SendCardTaskEnum = "CAMEL"
|
||||
)
|
||||
|
||||
func GetAllSendCardTaskType() []SendCardTaskEnum {
|
||||
@@ -74,6 +75,7 @@ func GetAllSendCardTaskType() []SendCardTaskEnum {
|
||||
SendCardTaskTypeEnumSdPay,
|
||||
SendCardTaskTypeEnumOrigin,
|
||||
SendCardTaskTypeEnumLianIns,
|
||||
SendCardTaskTypeEnumCamel,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +127,8 @@ func (sendCardTaskTypeEnum SendCardTaskEnum) GetSendCardTaskType() sendCardTaskT
|
||||
return &SendCardTaskTypeOrigin{}
|
||||
case SendCardTaskTypeEnumLianIns:
|
||||
return &SendCardTaskTypeLianIns{}
|
||||
case SendCardTaskTypeEnumCamel:
|
||||
return &SendCardTaskTypeCamel{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user