292 lines
9.0 KiB
Go
292 lines
9.0 KiB
Go
package third_party
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"gateway/internal/config"
|
|
"gateway/internal/otelTrace"
|
|
|
|
"gateway/internal/service/supplier"
|
|
"time"
|
|
|
|
"gateway/internal/models/merchant"
|
|
"gateway/internal/models/order"
|
|
"gateway/internal/models/payfor"
|
|
"gateway/internal/models/road"
|
|
"gateway/internal/models/supply_model"
|
|
"gateway/internal/service"
|
|
"net/http"
|
|
"net/url"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/beego/beego/v2/server/web"
|
|
"github.com/duke-git/lancet/v2/convertor"
|
|
"github.com/duke-git/lancet/v2/cryptor"
|
|
"github.com/duke-git/lancet/v2/formatter"
|
|
"github.com/duke-git/lancet/v2/maputil"
|
|
"github.com/duke-git/lancet/v2/netutil"
|
|
"github.com/duke-git/lancet/v2/pointer"
|
|
"github.com/duke-git/lancet/v2/structs"
|
|
"github.com/widuu/gojson"
|
|
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/trace"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type FatSixImpl struct {
|
|
*web.Controller
|
|
}
|
|
|
|
type sendCardReq struct {
|
|
Mid string `json:"mid"` // 商户号
|
|
MerOrderTid string `json:"merOrderTid"` // 商户单号
|
|
Money string `json:"money"` // 金额
|
|
ChannelCode string `json:"channelCode"` // 通道编码
|
|
//ClientUserPayRemark string `json:"clientUserPayRemark"` // 付款人备注
|
|
//ClientUserId string `json:"clientUserId"` // 商户端用户Id
|
|
NotifyUrl string `json:"notifyUrl"`
|
|
}
|
|
|
|
func sign(params map[string]any, keys []string, paySecret string) string {
|
|
sort.Strings(keys)
|
|
str := ""
|
|
for i := 0; i < len(keys); i++ {
|
|
k := keys[i]
|
|
if len(convertor.ToString(params[k])) == 0 || k == "sign" {
|
|
continue
|
|
}
|
|
str += k + "=" + convertor.ToString(params[k]) + "&"
|
|
}
|
|
str += paySecret
|
|
return strings.ToUpper(cryptor.Md5String(str))
|
|
}
|
|
|
|
type sendCardResp struct {
|
|
Status int `json:"status"`
|
|
ErrMsg string `json:"errMsg"`
|
|
Result struct {
|
|
Tid string `json:"tid"`
|
|
MerOrderTid string `json:"merOrderTid"`
|
|
PayUrl string `json:"payUrl"`
|
|
PayOrderStatus int `json:"payOrderStatus"`
|
|
} `json:"result"`
|
|
}
|
|
|
|
func (f *FatSixImpl) sendCard(ctx context.Context, jsonStr string, cardInfo supplier.RedeemCardInfo, attach string) (bool, *sendCardResp) {
|
|
response := &sendCardResp{}
|
|
req := sendCardReq{
|
|
Mid: gojson.Json(jsonStr).Get("mid").Tostring(),
|
|
MerOrderTid: attach,
|
|
Money: cardInfo.FaceType,
|
|
ChannelCode: gojson.Json(jsonStr).Get("channelCode").Tostring(),
|
|
NotifyUrl: config.GetConfig().GetSixFatNotifyUrl(),
|
|
}
|
|
params, _ := structs.ToMap(req)
|
|
params["sign"] = sign(params, maputil.Keys(params), gojson.Json(jsonStr).Get("paySecret").Tostring())
|
|
|
|
pretty, _ := formatter.Pretty(params)
|
|
otelTrace.Logger.WithContext(ctx).Info("请求参数:" + pretty)
|
|
|
|
//urlParams := url.Values{}
|
|
//for k, v := range params {
|
|
// urlParams.Add(k, v.(string))
|
|
//}
|
|
body, err := json.Marshal(params)
|
|
if err != nil {
|
|
otelTrace.Logger.WithContext(ctx).Error("解析参数失败", zap.Error(err))
|
|
return false, response
|
|
}
|
|
header := http.Header{}
|
|
header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
request := &netutil.HttpRequest{
|
|
Headers: header,
|
|
RawURL: "http://ti8lj4yj3am3mr4id0tl.itxitongsf.xyz/api/services/app/Api_PayOrder/CreateOrderPay",
|
|
Method: "POST",
|
|
//FormData: urlParams,
|
|
Body: body,
|
|
}
|
|
httpClient := netutil.NewHttpClient()
|
|
httpClient.Timeout = 30 * time.Second
|
|
httpClient.Transport = otelhttp.NewTransport(http.DefaultTransport)
|
|
resp, err := httpClient.SendRequest(request)
|
|
|
|
if err != nil || resp.StatusCode != 200 {
|
|
otelTrace.Logger.WithContext(ctx).Error("发送数据失败", zap.Error(err))
|
|
return false, response
|
|
}
|
|
err = httpClient.DecodeResponse(resp, &response)
|
|
if err != nil || pointer.IsNil(response) {
|
|
otelTrace.Logger.WithContext(ctx).Error("解析分解会结构失败", zap.Error(err), zap.Any("response", response))
|
|
return false, response
|
|
}
|
|
|
|
pretty, _ = formatter.Pretty(response)
|
|
otelTrace.Logger.WithContext(ctx).Info("返回参数:" + pretty)
|
|
if response.Status == 0 {
|
|
return true, response
|
|
}
|
|
|
|
return false, response
|
|
}
|
|
|
|
func (f *FatSixImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInfo road.RoadInfo, info3 merchant.MerchantInfo) supplier.ScanData {
|
|
ctx, cancel := otelTrace.Span(ctx, "胖小六", "Scan", trace.WithAttributes(
|
|
attribute.String("BankOrderId", orderInfo.BankOrderId),
|
|
attribute.String("MerchantUid", orderInfo.MerchantUid),
|
|
attribute.String("ExValue", orderInfo.ExValue),
|
|
))
|
|
defer cancel()
|
|
cdata := supplier.RedeemCardInfo{
|
|
FaceType: convertor.ToString(orderInfo.OrderAmount),
|
|
}
|
|
//err := json.Unmarshal([]byte(orderInfo.ExValue), &cdata)
|
|
//if err != nil {
|
|
// otel.Logger.WithContext(ctx).Error("格式化数据失败", orderInfo.ExValue)
|
|
// return supplier.ScanData{Status: "-1", Msg: "订单有有误,请稍后再试"}
|
|
//}
|
|
ok, response := f.sendCard(ctx, roadInfo.Params, cdata, orderInfo.BankOrderId)
|
|
if !ok {
|
|
return supplier.ScanData{
|
|
Status: "-1",
|
|
Msg: "订单有有误,请稍后再试:" + convertor.ToString(response.ErrMsg),
|
|
BankNo: orderInfo.MerchantOrderId,
|
|
OrderNo: orderInfo.BankOrderId,
|
|
ReturnData: convertor.ToString(response.ErrMsg),
|
|
}
|
|
}
|
|
scanData := supplier.ScanData{
|
|
OrderNo: orderInfo.BankOrderId,
|
|
BankNo: orderInfo.MerchantOrderId,
|
|
OrderPrice: strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64),
|
|
Status: "00",
|
|
PayUrl: response.Result.PayUrl,
|
|
Msg: "",
|
|
ReturnData: convertor.ToString(response.ErrMsg),
|
|
UpStreamOrderNo: response.Result.Tid,
|
|
}
|
|
return scanData
|
|
}
|
|
|
|
func (f *FatSixImpl) PayNotify() {
|
|
ctx := f.Ctx.Request.Context()
|
|
|
|
resp := struct {
|
|
MerOrderTid string `json:"merOrderTid"`
|
|
Tid string `json:"tid"`
|
|
Money string `json:"money"`
|
|
Sign string `json:"sign"`
|
|
Status int `json:"status"` // 状态 0=待处理 1=成功 2=失败 3=异常 4=超时关闭
|
|
}{}
|
|
err := f.Bind(&resp)
|
|
if err != nil {
|
|
otelTrace.Logger.WithContext(ctx).Error("解析参数失败", zap.Error(err))
|
|
f.Ctx.WriteString("fail")
|
|
return
|
|
}
|
|
orderInfo := order.GetOrderByBankOrderId(ctx, resp.MerOrderTid)
|
|
roadInfo := road.GetRoadInfoByRoadUid(ctx, orderInfo.RoadUid)
|
|
|
|
//解析token
|
|
params, _ := structs.ToMap(resp)
|
|
respSign := resp.Sign
|
|
tmpSign := sign(params, maputil.Keys(params), gojson.Json(roadInfo.Params).Get("paySecret").Tostring())
|
|
if tmpSign != respSign {
|
|
otelTrace.Logger.WithContext(ctx).Error("签名错误", zap.Error(err))
|
|
f.Ctx.WriteString("fail")
|
|
return
|
|
}
|
|
if resp.Status == 1 {
|
|
// TODO 订单支付成功
|
|
money, err := convertor.ToFloat(resp.Money)
|
|
if err != nil {
|
|
otelTrace.Logger.WithContext(ctx).Error("金额转换失败", zap.Error(err))
|
|
f.Ctx.WriteString("fail")
|
|
}
|
|
isOk := service.SolvePaySuccess(ctx, orderInfo.BankOrderId, money, resp.Tid, "支付成功")
|
|
if isOk {
|
|
f.Ctx.WriteString("SUCCESS")
|
|
} else {
|
|
f.Ctx.WriteString("FAIL")
|
|
}
|
|
} else {
|
|
isOk := service.SolvePayFail(f.Ctx.Request.Context(), orderInfo.BankOrderId, resp.Tid, "")
|
|
if isOk {
|
|
f.Ctx.WriteString("SUCCESS")
|
|
} else {
|
|
f.Ctx.WriteString("FAIL")
|
|
}
|
|
}
|
|
f.Ctx.WriteString("success")
|
|
}
|
|
|
|
func (f *FatSixImpl) PayQuery(info order.OrderInfo, info2 road.RoadInfo) bool {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (f *FatSixImpl) PayQueryV2(info order.OrderInfo, roadInfo road.RoadInfo) supply_model.MsgModel {
|
|
ctx := f.Ctx.Request.Context()
|
|
|
|
params := map[string]any{
|
|
"mid": "",
|
|
}
|
|
params["sign"] = sign(params, maputil.Keys(params), gojson.Json(roadInfo.Params).Get("paySecret").Tostring())
|
|
urlParams := url.Values{}
|
|
for k, v := range params {
|
|
urlParams.Add(k, v.(string))
|
|
}
|
|
request := &netutil.HttpRequest{
|
|
RawURL: "http://ti8lj4yj3am3mr4id0tl.itxitongsf.xyz/api/services/app/Api_PayOrder/QueryBalance",
|
|
Method: "POST",
|
|
FormData: urlParams,
|
|
}
|
|
httpClient := netutil.NewHttpClient()
|
|
resp, err := httpClient.SendRequest(request)
|
|
if err != nil || resp.StatusCode != 200 {
|
|
otelTrace.Logger.WithContext(ctx).Error("发送数据失败", zap.Error(err))
|
|
return "发送数据失败"
|
|
}
|
|
response := struct {
|
|
Status int `json:"status"`
|
|
ErrMsg interface{} `json:"errMsg"`
|
|
Result struct {
|
|
MerName string `json:"merName"`
|
|
Mid string `json:"mid"`
|
|
Balance string `json:"balance"`
|
|
} `json:"result"`
|
|
}{}
|
|
err = httpClient.DecodeResponse(resp, &response)
|
|
if err != nil || pointer.IsNil(response) {
|
|
otelTrace.Logger.WithContext(ctx).Error("解析分解会结构失败", zap.Error(err), zap.Any("response", response))
|
|
return "解析分解会结构失败"
|
|
}
|
|
return convertor.ToString(response.Result.Balance)
|
|
}
|
|
|
|
func (f *FatSixImpl) PayFor(info payfor.PayforInfo) string {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (f *FatSixImpl) PayForNotify() string {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (f *FatSixImpl) PayForQuery(info payfor.PayforInfo) (string, string) {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (f *FatSixImpl) BalanceQuery(info road.RoadInfo) float64 {
|
|
//TODO implement me
|
|
panic("implement me")
|
|
}
|
|
|
|
func (f *FatSixImpl) HasDependencyHTML() bool {
|
|
return true
|
|
}
|