package rchgutil import ( "bytes" "crypto/md5" "encoding/hex" "encoding/json" "errors" "fmt" "net/http" "strconv" "time" "91porn-server/app/appg" "91porn-server/common" "91porn-server/common/httputil" "91porn-server/common/log" "91porn-server/web/webg" ) var dbsc = config{ MercID: "10082", AppSecret: "b8f217afdcac162b569f856174bd811a", ExeUrl: "https://umio.zjcthbkj.com/api/shark/topay", QueryUrl: "https://umio.zjcthbkj.com/api/shark/order/queryOrder", NotifyUrl: "/3rd/defray/callback/rchg/dabaisha", } const ( DaBaiSha_Alipay_Code = "1001" DaBaiSha_Wechat_Code = "1002" DaBaiSha_Union_Code = "1003" ) // DaBaiSha 充值订单请求体 type DaBaiSha struct { MercID string `json:"mercId"` //商户编号 Type string `json:"type"` // 订单充值类型 Money string `json:"money"` // 充值⾦额 TradeNo string `json:"tradeNo"` //商户订单号 NotifyURL string `json:"notifyUrl"` // 回调地址 Info DaBaiShaInfo `json:"info"` // 用户信息 Time string `json:"time"` //UTC时间戳(13位) Mode string `json:"mode,omitempty"` //式模 持支 表代则传 值定固。填选 Sign string `json:"sign"` // 签名 PayMethod string } // DaBaiShaInfo 玩家信息 type DaBaiShaInfo struct { PlayerID string `json:"playerId"` // 玩家ID PlayerIP string `json:"playerIp"` // 玩家IP DeviceID string `json:"deviceId"` // 玩家设备ID DeviceType string `json:"deviceType"` // 玩家设备类型 ios pc android Name string `json:"name"` // 玩家姓名 Tel string `json:"tel"` // 玩家⼿机号 AlipayAct string `json:"alipayAct"` // 玩家支付宝账号 } // DaBaiShaRes 回调函数参数model type DaBaiShaRes struct { Code int `json:"code" binding:"required"` MercID string `json:"mercId" binding:"required"` //商户编号 OID string `json:"oid" binding:"required"` //支付平台订单号 PayMoney string `json:"payMoney" binding:"required"` //订单到账实际金额 TradeNo string `json:"tradeNo" binding:"required"` //商户订单号 Sign string `json:"sign" binding:"required"` //签名 } type QueryMSG struct { MercID string `json:"mercID"` TradeNo string `json:"tradeNo"` Money float32 `json:"money"` PayMoney float32 `json:"payMoney"` PayTime string `json:"payTime"` PayStatus string `json:"payStatus"` NotifyStatus string `json:"notifyStatus"` } // ToPay 支付发起 func (this *DaBaiSha) ToPay() (res RchgMsg, err error) { var errlog string this.Fill() msgModel := MsgModel{} code, err := httputil.DefaultClientPostJsonWithRespWithProxy(appg.ProxyCfg, &msgModel, this.GetURL(), this.GetHeader(), this.GetBody()) if err != nil { errlog = fmt.Sprintf("DaBaiSha ToPay requset fail \nerror:%+v\n\ndata:%+v;", err, this) log.Error(errlog) err = errors.New(errlog) return } if code != http.StatusOK { errlog = fmt.Sprintf("DaBaiSha ToPay response status exception;\nstatus %+v;", code) err = errors.New(errlog) log.Error(errlog) return } if msgModel.Code != 200 { switch msgModel.Code { case 40001: err = PAY_CHANNEL_CLOSE_ERROR case 80002: err = PAY_CHANNEL_BAN_ERROR default: bytes, _ := json.Marshal(msgModel) errlog = fmt.Sprintf("DaBaiSha ToPay be rejected;\n data:%+v:", string(bytes)) err = errors.New(errlog) } log.Error(errlog) return } msg := msgModel.Msg var buf bytes.Buffer buf.WriteString(msg["oid"]) buf.WriteString(msg["payUrl"]) buf.WriteString(this.GetAppSecret()) if !VerifySign(msg["sign"], buf.String()) { errlog = fmt.Sprintf("http goldfish VerifySign fail \nerr :%+v \ndata:%+v", err, msgModel) err = errors.New(errlog) log.Error(errlog) return } res.PayUrl = msg["payUrl"] res.OID = msg["oid"] res.Mode = msg["mode"] return } // QueryOrder 订单状态查询发起 func (g *DaBaiSha) QueryOrder() (msg QueryMSG, err error) { var res struct { Code int `json:"code"` MSG QueryMSG `json:"msg"` } body := make(map[string]string) body["mercId"] = g.GetMercID() body["tradeNo"] = g.TradeNo code, err := httputil.DefaultClientGetWithResp(&res, g.GetQueryURL(), nil, body) if err != nil || code != 200 { log.Error(fmt.Sprintf("goldfish QueryOrder http.Get fail error:%+v:", err)) return } if res.Code != 200 { err = errors.New("goldfish QueryOrder http query fail") return } msg = res.MSG return } // ASenCallBack 阿森结构回调函数 func (this *DaBaiShaRes) Notify() (RchgBack, error) { r := RchgBack{} buf := bytes.Buffer{} buf.WriteString(strconv.Itoa(this.Code)) buf.WriteString(this.MercID) buf.WriteString(this.OID) buf.WriteString(this.PayMoney) buf.WriteString(this.TradeNo) buf.WriteString(dbsc.AppSecret) if !VerifySign(this.Sign, buf.String()) { log.Error(fmt.Sprintf("DaBaiSha callback sign verify fail ,data:%+v", this)) return r, errors.New("check sign fail") } g := DaBaiSha{ TradeNo: this.TradeNo, } msg, err := g.QueryOrder() //订单状态查询发起 if err != nil { return r, err } if msg.PayTime == "" { return r, errors.New("querry order err,no payTime") } loc, _ := time.LoadLocation("Local") paymentAt, err := time.ParseInLocation("2006-01-02T15:04:05Z07:00", msg.PayTime, loc) if err != nil { log.Error("time.ParseInLocation failed", log.Any("TradeNo", this.TradeNo), log.E(err)) return r, err } payMoneyf, err := strconv.ParseFloat(this.PayMoney, 64) if err != nil { log.Error(fmt.Sprintf("DaBaiSha callback ParseFloat fail data:%+v:", this)) return r, fmt.Errorf("invalid payMoney %s", this.PayMoney) } r.PayMoney = int64(payMoneyf * 100) r.PaymentAt = paymentAt r.TransNo = this.TradeNo r.OID = this.OID r.Code = this.Code return r, nil } func (this *DaBaiShaRes) Success() string { return "success" } type PayType struct { Name string `json:"name"` PayMent string `json:"payMent"` Type string `json:"type"` } type PayTypes struct { Money string `json:"money"` Types []PayType `json:"types"` } // QueryOrder 订单状态查询发起 func (g *DaBaiSha) GetPayType(moneys []string, mode string) (payTypes []PayTypes, err error) { var errlog string var res struct { Code int `json:"code"` MSG []PayTypes `json:"msg"` Err string `json:"err"` } body := make(map[string]interface{}) body["mercId"] = g.GetMercID() body["money"] = moneys body["time"] = GetUTCTimeMS(time.Now()) if mode != "" { body["mode"] = mode } var moneysStr bytes.Buffer for k, v := range moneys { if k == 0 { moneysStr.WriteString(v) } else { moneysStr.WriteString(",") moneysStr.WriteString(v) } } fmt.Println(moneysStr.String()) body["sign"] = md5Sign(dbsc.MercID + moneysStr.String() + dbsc.AppSecret) code, err := httputil.DefaultClientPostJsonWithResp(&res, g.GetGetTypeURL(), nil, body) if err != nil { errlog = fmt.Sprintf("DaBaiSha GetPayType requset fail \nerror:%+v\n\ndata:%+v;", err, body) log.Error(errlog) err = errors.New(errlog) return } if code != http.StatusOK { errlog = fmt.Sprintf("DaBaiSha GetPayType response status exception;\nstatus %+v;", code) err = errors.New(errlog) log.Error(errlog) return } if res.Code != 200 { errlog = fmt.Sprintf("DaBaiSha GetPayType be rejected;\n err:%+v:", res.Err) err = errors.New(errlog) log.Error(errlog) return } log.Info(fmt.Sprintf("DaBaiSha GetPayType data:%+v:", res)) payTypes = res.MSG return } // Fill 补全配置信息和签名信息 func (g *DaBaiSha) Fill() { g.MercID = g.GetMercID() g.NotifyURL = g.GetCallBackURL() switch g.PayMethod { case "alipay": g.Type = "fixedAlipay" case "wechat": g.Type = "fixedWechat" case "union": g.Type = "union" } g.PayMethod = "" if g.Info.Name == "" { g.Info.Name = GetFullName() } if g.Info.PlayerIP == "" { g.Info.PlayerIP = genIpaddr() } if g.Info.DeviceID == "" { g.Info.DeviceID = common.UUID() } if g.Info.DeviceType == "" { g.Info.DeviceType = "ios" } g.Sign = g.sign() } // sign 签名 func (g *DaBaiSha) sign() (sign string) { var buf bytes.Buffer buf.WriteString(g.GetMercID()) buf.WriteString(g.Money) buf.WriteString(g.GetCallBackURL()) buf.WriteString(g.TradeNo) buf.WriteString(g.Type) buf.WriteString(g.GetAppSecret()) md5Ctx := md5.New() md5Ctx.Write(buf.Bytes()) cipherStr := md5Ctx.Sum(nil) return hex.EncodeToString(cipherStr) } // GetBody 获取请求body func (g *DaBaiSha) GetBody() interface{} { jsonStr, err := json.Marshal(g) if err != nil { log.Info(fmt.Sprintf("DaBaiSha GetBody json.Marshal is fail error:%+v/data:%+v", err, g)) } sstr := string(jsonStr) log.Info(fmt.Sprintf("==================%+v", sstr)) return jsonStr } // GetHeader 获取请求头信息 func (g *DaBaiSha) GetHeader() map[string]string { header := make(map[string]string, 0) return header } // GetURL 获取请求地址 func (*DaBaiSha) GetURL() string { return dbsc.ExeUrl } // GetQueryURL 获取请求地址 func (*DaBaiSha) GetQueryURL() string { return dbsc.QueryUrl } // GetQueryURL 获取请求地址 func (*DaBaiSha) GetGetTypeURL() string { return "https://umio.zjcthbkj.com/api/shark/getPayType" } // GetMercID 获取商户编号 func (*DaBaiSha) GetMercID() string { return dbsc.MercID } // GetAppSecret 获取app签名密钥 func (*DaBaiSha) GetAppSecret() string { return dbsc.AppSecret } // GetCallBackURL 获取回掉函数 func (*DaBaiSha) GetCallBackURL() string { if appg.Conf != nil { return appg.Conf.URL.LocalWebUrl + dbsc.NotifyUrl } return webg.Conf.URL.LocalAppUrl + dbsc.NotifyUrl }