更新第三方支付模块,新增 BatchSixImpl 实现
- 在 internal/service/supplier/third_party 目录下新增 BatchSixImpl 结构体及其相关方法,支持新的支付接口。 - 更新 init.go 文件,注册 BatchSix 供应商,确保系统能够识别并使用新的支付方式。 - 在 otelTrace 中增强日志记录,提升请求和响应的可追溯性。 - 新增测试用例 batch_six_test.go,验证 SendCard 方法的功能,确保其正确性和稳定性。
This commit is contained in:
@@ -56,7 +56,7 @@ func (l *LoggerStruct) WithContext(ctx context.Context) *zap.Logger {
|
||||
}
|
||||
return l.logger
|
||||
}
|
||||
return l.logger.With(zap.Reflect("ctx", ctx))
|
||||
return l.logger.With(zap.Reflect("ctx", ctx)).With(zap.String("span", span.SpanContext().TraceID().String()))
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
300
internal/service/supplier/third_party/batch_six.go
vendored
Normal file
300
internal/service/supplier/third_party/batch_six.go
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
package third_party
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"gateway/internal/config"
|
||||
"gateway/internal/otelTrace"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gateway/internal/service/supplier"
|
||||
|
||||
"gateway/internal/models/merchant"
|
||||
"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/slice"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"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 BatchSixImpl struct {
|
||||
web.Controller
|
||||
}
|
||||
|
||||
// WalMartOrderStatus 充值编码
|
||||
type BatchSixOrderStatus int
|
||||
|
||||
// HasDependencyHTML 是否有单独的支付页面
|
||||
func (c *BatchSixImpl) HasDependencyHTML() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *BatchSixImpl) SendCard(ctx context.Context, jsonStr string, cardInfo supplier.RedeemCardInfo, attach string) (bool, string) {
|
||||
|
||||
otelTrace.Logger.WithContext(ctx).Info("发送卡密", zap.String("jsonStr", jsonStr), zap.Any("cardInfo", cardInfo), zap.String("attach", attach))
|
||||
|
||||
request := httplib.NewBeegoRequest("https://duika.666dkw.com/getLogin", "POST").
|
||||
SetTransport(otelhttp.NewTransport(http.DefaultTransport)).
|
||||
SetTimeout(time.Second*3, time.Second*3).Retries(3)
|
||||
|
||||
loginReq := struct {
|
||||
Type int `json:"type"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}{
|
||||
Type: 0,
|
||||
Username: gojson.Json(jsonStr).Get("username").Tostring(),
|
||||
Password: gojson.Json(jsonStr).Get("password").Tostring(),
|
||||
}
|
||||
request, err := request.JSONBody(loginReq)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("JSONBody失败", zap.Error(err))
|
||||
return false, "内部错误请稍后再试"
|
||||
}
|
||||
response, err := request.Response()
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("请求失败", zap.Error(err))
|
||||
return false, "内部错误请稍后再试"
|
||||
}
|
||||
|
||||
var loginResp struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("读取响应体失败", zap.Error(err))
|
||||
return false, "内部错误请稍后再试"
|
||||
}
|
||||
err = json.Unmarshal(body, &loginResp)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err))
|
||||
return false, "内部错误请稍后再试"
|
||||
}
|
||||
if loginResp.Code != 200 {
|
||||
otelTrace.Logger.WithContext(ctx).Error("登录失败", zap.String("msg", loginResp.Msg))
|
||||
return false, "登录失败"
|
||||
}
|
||||
|
||||
otelTrace.Logger.WithContext(ctx).Info("登录成功", zap.String("data", loginResp.Data))
|
||||
request = httplib.NewBeegoRequest("https://duika.666dkw.com/apitocard", "POST").
|
||||
SetTransport(otelhttp.NewTransport(http.DefaultTransport)).
|
||||
SetTimeout(time.Second*3, time.Second*3).Retries(3)
|
||||
|
||||
loginCookie := response.Cookies()
|
||||
slice.ForEach(loginCookie, func(index int, item *http.Cookie) {
|
||||
otelTrace.Logger.WithContext(ctx).Info("cookie", zap.String("name", item.String()))
|
||||
if item.Name == "PHPSESSID" {
|
||||
request = request.SetCookie(item)
|
||||
}
|
||||
})
|
||||
|
||||
faceType, err := strconv.ParseFloat(cardInfo.FaceType, 64)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err))
|
||||
return false, "卡面值格式错误"
|
||||
}
|
||||
id := gojson.Json(jsonStr).Get("id").Tostring()
|
||||
if id == "" {
|
||||
otelTrace.Logger.WithContext(ctx).Error("id为空")
|
||||
return false, "id为空"
|
||||
}
|
||||
idInt, err := strconv.ParseInt(id, 10, 64)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err))
|
||||
return false, "卡编码设置错误"
|
||||
}
|
||||
|
||||
cardReq := struct {
|
||||
Id int64 `json:"id"`
|
||||
Cardlist []string `json:"cardlist"`
|
||||
Cardno string `json:"cardno"`
|
||||
Cardpwd string `json:"cardpwd"`
|
||||
Cardprice string `json:"cardprice"`
|
||||
Type int `json:"type"`
|
||||
Urgent int `json:"urgent"`
|
||||
Feilv string `json:"feilv"`
|
||||
}{
|
||||
Id: idInt,
|
||||
Cardlist: []string{},
|
||||
Cardno: cardInfo.CardNo,
|
||||
Cardpwd: cardInfo.Data,
|
||||
Cardprice: strconv.Itoa(int(faceType)),
|
||||
Type: 0,
|
||||
Urgent: 0,
|
||||
Feilv: "",
|
||||
}
|
||||
request, err = request.JSONBody(cardReq)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("JSONBody失败", zap.Error(err))
|
||||
return false, "内部错误请稍后再试"
|
||||
}
|
||||
responseStr, err := request.String()
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("请求失败", zap.Error(err))
|
||||
return false, "内部错误请稍后再试"
|
||||
}
|
||||
otelTrace.Logger.WithContext(ctx).Info("请求结果", zap.String("response", responseStr))
|
||||
|
||||
// {"response": "{\"code\":\"201\",\"msg\":\"失败\",\"data\":\"卡号或卡密格式错误\"}"}
|
||||
var resp struct {
|
||||
Response struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data string `json:"data"`
|
||||
} `json:"response"`
|
||||
}
|
||||
err = json.Unmarshal([]byte(responseStr), &resp)
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("解析失败", zap.Error(err))
|
||||
return false, "内部错误请稍后再试"
|
||||
}
|
||||
if resp.Response.Code != 200 {
|
||||
return false, resp.Response.Data
|
||||
}
|
||||
return true, resp.Response.Data
|
||||
}
|
||||
|
||||
func (c *BatchSixImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
|
||||
ctx, cancel := otelTrace.Span(ctx, "BatchSixImpl", "Scan", trace.WithAttributes(
|
||||
attribute.String("BankOrderId", orderInfo.BankOrderId),
|
||||
attribute.String("MerchantUid", orderInfo.MerchantUid),
|
||||
attribute.String("ExValue", orderInfo.ExValue),
|
||||
))
|
||||
defer cancel()
|
||||
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)
|
||||
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 *BatchSixImpl) PayNotify() {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *BatchSixImpl) PayQuery(orderInfo order.OrderInfo, roadInfo road.RoadInfo) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *BatchSixImpl) PayQueryV2(orderInfo order.OrderInfo, roadInfo road.RoadInfo) supply_model.MsgModel {
|
||||
return supply_model.RemoteDataErr
|
||||
}
|
||||
|
||||
func (c *BatchSixImpl) PayFor(info payfor.PayforInfo) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *BatchSixImpl) 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("远端请求返回数据:" + 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 *BatchSixImpl) BalanceQuery(roadInfo road.RoadInfo) float64 {
|
||||
return 0.00
|
||||
}
|
||||
|
||||
func (c *BatchSixImpl) PayForNotify() string {
|
||||
return ""
|
||||
}
|
||||
14
internal/service/supplier/third_party/batch_six_test.go
vendored
Normal file
14
internal/service/supplier/third_party/batch_six_test.go
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package third_party
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gateway/internal/service/supplier"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBatchSixImpl_SendCard(t *testing.T) {
|
||||
impl := &BatchSixImpl{}
|
||||
ok, str := impl.SendCard(context.Background(), "{\"card_no\":\"2326996875163755411\",\"card_pwd\":\"123555\",\"card_price\":\"100\"}", supplier.RedeemCardInfo{}, "")
|
||||
fmt.Println(ok, str)
|
||||
}
|
||||
@@ -25,7 +25,8 @@ var supplierCode2Name = map[string]string{
|
||||
"Ninja": "忍者API",
|
||||
"Heepay": "俊卡官方接口",
|
||||
"EGGPLANT": "茄子核销平台",
|
||||
"FAVORABLE_CLOUDS": "爱彼核销平台",
|
||||
"FAVORABLE_CLOUDS": "爱彼核销平台",
|
||||
"BATCH_SIX": "666核销充值",
|
||||
}
|
||||
|
||||
var registerSupplier = make(map[string]supplier.PayInterface)
|
||||
@@ -67,7 +68,9 @@ func init() {
|
||||
registerSupplier["EGGPLANT"] = new(EggplantImpl)
|
||||
logs.Notice(CheckSupplierByCode("EGGPLANT"))
|
||||
registerSupplier["FAVORABLE_CLOUDS"] = new(FavorableCloudsCardImpl)
|
||||
logs.Notice(CheckSupplierByCode("爱彼"))
|
||||
logs.Notice(CheckSupplierByCode("FAVORABLE_CLOUDS"))
|
||||
registerSupplier["BATCH_SIX"] = new(BatchSixImpl)
|
||||
logs.Notice(CheckSupplierByCode("BATCH_SIX"))
|
||||
}
|
||||
|
||||
func GetPaySupplierByCode(code string) supplier.PayInterface {
|
||||
|
||||
3180
internal/service/supplier/third_party/面值.json
vendored
Normal file
3180
internal/service/supplier/third_party/面值.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user