Files
kami_gateway/internal/entities/supplier/third_party/t_mall_game.go
2024-09-03 21:52:44 +08:00

427 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package third_party
import (
"encoding/json"
"gateway/internal/config"
"gateway/internal/consts"
"gateway/internal/entities/supplier"
"gateway/internal/models/merchant"
"gateway/internal/models/order"
"gateway/internal/models/payfor"
"gateway/internal/models/road"
"gateway/internal/models/supply_model"
"gateway/internal/service"
"gateway/internal/utils"
"strconv"
"strings"
"time"
"github.com/astaxie/beego/httplib"
"github.com/astaxie/beego/logs"
"github.com/beego/beego/v2/server/web"
"github.com/bytedance/sonic"
"github.com/widuu/gojson"
)
type TMAllGameImpl struct {
web.Controller
}
// TMallGameStatus 充值编码
type TMallGameStatus int
const (
TMallGameFail TMallGameStatus = 0 // 充值失败
TMallGameSuccess TMallGameStatus = 1 // 充值成功
)
func (c *TMAllGameImpl) SendCard(jsonStr string, cardInfo supplier.CardInfo, orderInfo order.OrderInfo) (bool, string) {
if _, ok := cardInfo.(*supplier.RedeemCardInfo); ok {
return false, "传输数据格式错误"
}
cfg := config.Config{}
var err error
info := cardInfo.(*supplier.RechargeCardInfo)
notifyUrl, err := cfg.GetTMallGameNotifyUrl()
if err != nil {
return false, "获取回调地址失败"
}
params := map[string]string{
"accountNumber": info.AccountNumber,
"account": strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64),
"merchantOrder": orderInfo.BankOrderId,
"callbackUrl": notifyUrl,
"timestamp": strconv.FormatInt(time.Now().Unix(), 10),
}
params["sign"] = utils.TmpEncrypt(params["merchantOrder"] + params["accountNumber"] + params["timestamp"])
url, err := cfg.GetTMallGameSubmitUrl()
if err != nil {
return false, "获取天猫充值地址失败!"
}
req := httplib.Post(url)
marshal, err := json.Marshal(params)
if err != nil {
logs.Error("Map转化为byte数组失败,异常。", err)
return false, "内部错误请稍后再试试01"
}
logs.Info("请求参数:" + string(marshal))
req.Header("Content-Type", "application/json")
req.Body(marshal)
req.Header("Accept-Charset", "utf-8")
req.Header("tokenFrom", "iframe")
response, err := req.String()
if err != nil {
logs.Error("天猫店铺请求失败:", err)
return false, ""
}
logs.Info("远端请求返回数据:" + response)
if gojson.Json(response).Get("code").Tostring() == "" {
logs.Error("远程调用失败")
return false, ""
}
type AutoGenerated struct {
Code int `json:"code"`
Message string `json:"message"`
Data struct {
Status TMallGameStatus `json:"status"`
Message string `json:"message"`
} `json:"data"`
}
var resData AutoGenerated
err = json.Unmarshal([]byte(response), &resData)
if err != nil {
logs.Error("json解析失败", err, response)
return false, "内部数据处理失败"
}
if resData.Code != 0 {
logs.Error("充值错误", resData.Message)
return false, resData.Message
}
switch resData.Data.Status {
case TMallGameFail:
return false, "充值失败"
case TMallGameSuccess:
return true, "等待兑换"
}
return false, response
}
func (c *TMAllGameImpl) Scan(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
var cdata supplier.CardInfo
if roadInfo.TransactionType == string(consts.TransactionTypeRedeem) {
cdata = &supplier.RedeemCardInfo{}
err := json.Unmarshal([]byte(orderInfo.ExValue), &cdata)
if err != nil {
logs.Error("格式化数据失败", orderInfo.ExValue)
return supplier.ScanData{Status: "-1", Msg: "订单有有误,请稍后再试"}
}
} else {
cdata = &supplier.RechargeCardInfo{}
err := json.Unmarshal([]byte(orderInfo.ExValue), &cdata)
if err != nil {
logs.Error("格式化数据失败", orderInfo.ExValue)
return supplier.ScanData{Status: "-1", Msg: "订单有有误,请稍后再试"}
}
}
ok, str := c.SendCard(roadInfo.Params, cdata, orderInfo)
if !ok {
return supplier.ScanData{Status: "-1", Msg: "订单有有误,请稍后再试:" + str}
}
if str == "" {
return supplier.ScanData{Status: "-1", Msg: "订单有有误,请稍后再试:" + str}
}
retStr := gojson.Json(str).Get("code").Tostring()
if retStr != "0" {
return supplier.ScanData{Status: "-1", Msg: gojson.Json(str).Get("msg").Tostring()}
}
var scanData supplier.ScanData
scanData.Status = "00"
scanData.OrderNo = orderInfo.BankOrderId
scanData.BankNo = orderInfo.MerchantOrderId
scanData.OrderPrice = strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64)
if jsStr, err2 := sonic.GetFromString(str); err2 == nil {
if s, err3 := jsStr.Get("data").Get("cards").Index(0).Raw(); err3 == nil {
scanData.ReturnData = s
}
}
return scanData
}
func (c *TMAllGameImpl) PayNotify() {
orderInfo := order.GetOrderByBankOrderId(strings.TrimSpace(c.GetString("merchantOrder"))) // OrderId
if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
logs.Error("【TMALLGAME】回调的订单号不存在订单号=", strings.TrimSpace(c.GetString("merchantOrder")))
c.Ctx.WriteString("FAIL")
return
}
roadInfo := road.GetRoadInfoByRoadUid(orderInfo.RoadUid)
if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 {
logs.Error("【TMALLGAME】支付通道已经关系或者删除不进行回调")
c.Ctx.WriteString("FAIL")
return
}
merchantUid := orderInfo.MerchantUid
merchantInfo := merchant.GetMerchantByUid(merchantUid)
if merchantInfo.MerchantUid == "" || len(merchantInfo.MerchantUid) == 0 {
logs.Error("【TMALLGAME】快付回调失败该商户不存在或者已经删除商户uid=", merchantUid)
c.Ctx.WriteString("FAIL")
return
}
params := map[string]string{
"orderId": strings.TrimSpace(c.GetString("orderId")),
"merchantOrder": strings.TrimSpace(c.GetString("merchantOrder")),
"timestamp": strings.TrimSpace(c.GetString("timestamp")),
"status": strings.TrimSpace(c.GetString("status")),
"remark": strings.TrimSpace(c.GetString("remark")),
"amount": strings.TrimSpace(c.GetString("amount")),
"sign": strings.TrimSpace(c.GetString("sign")),
}
tmpSign := utils.TmpEncrypt(strings.TrimSpace(c.GetString("merchantOrder")) + params["orderId"] + params["timestamp"])
if tmpSign != params["sign"] {
logs.Error("【TMALLGAME】回调签名错误签名=", params["sign"], "计算签名=", tmpSign)
c.Ctx.WriteString("FAIL")
return
}
orderInfo.BankTransId = params["orderId"]
if params["status"] == "1" {
// TODO 订单支付成功
isOk := service.SolvePaySuccess(orderInfo.BankOrderId, orderInfo.FactAmount, params["orderId"])
if isOk {
c.Ctx.WriteString("SUCCESS")
} else {
c.Ctx.WriteString("FAIL")
}
} else {
isOk := service.SolvePayFail(orderInfo.BankOrderId, "")
if isOk {
c.Ctx.WriteString("SUCCESS")
} else {
c.Ctx.WriteString("FAIL")
}
}
order.InsertCardReturnData(orderInfo.MerchantOrderId, params["remark"])
}
func (c *TMAllGameImpl) PayQuery(orderInfo order.OrderInfo, roadInfo road.RoadInfo) bool {
params := map[string]string{}
cardData, err := sonic.GetFromString(orderInfo.CardReturnData)
if err != nil {
return false
}
orderId, err := cardData.Get("order_id").String()
if err != nil {
return false
}
params["order_id"] = orderId
params["app_key"] = gojson.Json(roadInfo.Params).Get("appKey").Tostring()
params["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
params["sign"] = utils.GetMD5SignMF(params, gojson.Json(roadInfo.Params).Get("appSecret").Tostring())
cfg := config.Config{}
url, err := cfg.GetMFCardQueryUrl()
req := httplib.Post(url)
marshal, err := json.Marshal(params)
if err != nil {
logs.Error("Map转化为byte数组失败,异常。", err)
// fmt.Printf("Map转化为byte数组失败,异常:%s\n", err)
return false
}
logs.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 {
logs.Error("MF GetToken 请求失败:", err)
return false
}
logs.Info("远端请求返回数据:" + response)
resData, err := sonic.GetFromString(response)
if err != nil {
return false
}
resStatus, err := resData.Get("data").Get("status").Int64()
if err != nil {
return false
}
resCode, err := resData.Get("code").Int64()
if err != nil {
return false
}
if resCode == 0 && resStatus == 9 {
return true
}
return false
}
func (c *TMAllGameImpl) PayQueryV2(orderInfo order.OrderInfo, roadInfo road.RoadInfo) supply_model.MsgModel {
params := map[string]string{}
cardData, err := sonic.GetFromString(orderInfo.CardReturnData)
if err != nil {
return supply_model.CardMsgErr
}
orderId, err := cardData.Get("order_id").String()
if err != nil {
return supply_model.CardMsgErr
}
params["order_id"] = orderId
params["app_key"] = gojson.Json(roadInfo.Params).Get("appKey").Tostring()
params["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
params["sign"] = utils.GetMD5SignMF(params, gojson.Json(roadInfo.Params).Get("appSecret").Tostring())
cfg := config.Config{}
url, err := cfg.GetMFCardQueryUrl()
req := httplib.Post(url)
marshal, err := json.Marshal(params)
if err != nil {
logs.Error("Map转化为byte数组失败,异常。", err)
// fmt.Printf("Map转化为byte数组失败,异常:%s\n", err)
return supply_model.DataErr
}
logs.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 {
return supply_model.RemoteDataErr
}
logs.Info("远端请求返回数据:" + response)
resData, err := sonic.GetFromString(response)
if err != nil {
return supply_model.RemoteDataErr
}
resStatus, err := resData.Get("data").Get("status").Int64()
if err != nil {
return supply_model.RemoteDataErr
}
resCode, err := resData.Get("code").Int64()
if err != nil {
return supply_model.RemoteDataErr
}
if resCode == 0 {
switch resStatus {
case 9:
return supply_model.RemoteSuccess
case 2, 3, 4:
return supply_model.RemoteDataDealing
case 7:
return supply_model.RemoteDataHandErr
case 8:
return supply_model.RemoteDataHealingErr
}
}
return supply_model.RemoteDataErr
}
func (c *TMAllGameImpl) PayFor(info payfor.PayforInfo) string {
return ""
}
func (c *TMAllGameImpl) PayForQuery(payFor payfor.PayforInfo) (string, string) {
cfg := config.Config{}
url, err := cfg.GetMFCardQueryUrl()
if err != nil {
return config.PAYFOR_FAIL, ""
}
params := map[string]string{}
params["order_id"] = payFor.BankOrderId
params["app_key"] = gojson.Json("").Get("appKey").Tostring()
req := httplib.Post(url)
marshal, err := json.Marshal(params)
if err != nil {
logs.Error("Map转化为byte数组失败,异常。", err)
// fmt.Printf("Map转化为byte数组失败,异常:%s\n", err)
return config.PAYFOR_FAIL, "内部错误请稍后再试试01"
}
logs.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 {
logs.Error("MF GetToken 请求失败:", err)
return config.PAYFOR_FAIL, ""
}
logs.Info("远端请求返回数据:" + response)
if gojson.Json(response).Get("code").Tostring() == "" {
logs.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, ""
}
}
logs.Error("远程调用失败")
return config.PAYFOR_BANKING, ""
}
func (c *TMAllGameImpl) BalanceQuery(roadInfo road.RoadInfo) float64 {
return 0.00
}
func (c *TMAllGameImpl) PayForNotify() string {
return ""
}