package rchgutil import ( "bytes" "crypto/md5" "encoding/hex" "encoding/json" "errors" "fmt" "net/http" "91porn-server/app/appg" "91porn-server/common" "91porn-server/common/httputil" "91porn-server/common/log" "91porn-server/web/webg" ) var sc = config{ MercID: "10230", AppSecret: "9500fd843c02fe8ca2607e1295215f8b", ExeUrl: "https://lias.huimu311.com/api/shark/topay", NotifyUrl: "/3rd/defray/callback/shark", QueryUrl: "https://lias.huimu311.com/api/shark/order/queryOrder", } // Shark 充值订单请求体 type Shark struct { MercID string `json:"mercId"` Type string `json:"type"` Money string `json:"money"` TradeNo string `json:"tradeNo"` NotifyURL string `json:"notifyUrl"` Info SharkInfo `json:"info"` Time string `json:"time"` Sign string `json:"sign"` PayMethod string } // SharkInfo 玩家信息 type SharkInfo struct { PlayerID string `json:"playerId"` PlayerIP string `json:"playerIp"` DeviceID string `json:"deviceId"` DeviceType string `json:"deviceType"` Name string `json:"name"` Tel string `json:"tel"` PayAct string `json:"payAct"` } // SharkRes 回调函数参数model type SharkRes 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"` //签名 } // ToPay 支付发起 func (s *Shark) ToPay() (payUrl string, oid string, err error) { var errlog string s.Fill() msgModel := MsgModel{} code, err := httputil.DefaultClientPostWithRespWithProxy(appg.ProxyCfg, &msgModel, s.GetURL(), s.GetHeader(), s.GetBody()) if err != nil { errlog = fmt.Sprintf("shark ToPay Http.PostJson fail error:%+v/,data:%+v;", err, s) log.Error(errlog) err = errors.New(errlog) return } if code != http.StatusOK { errlog = fmt.Sprintf("shark ToPay Http.PostJson fail error:%+v/,data:%+v;", err, code) err = errors.New(errlog) log.Error(errlog) return } if msgModel.Code != 200 { switch msgModel.Code { case 40001: err = PAY_CHANNEL_CLOSE_ERROR default: errlog = fmt.Sprintf("shark topay response err :%+v/,data:%+v;", err, msgModel) 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(s.GetAppSecret()) if !VerifySign(msg["sign"], buf.String()) { errlog = fmt.Sprintf("http shark VerifySign fail err :%+v/data:%+v", err, msgModel) err = errors.New(errlog) log.Error(errlog) return } payUrl = msg["payUrl"] oid = msg["oid"] return } // QueryOrder 订单状态查询发起 func (s *Shark) QueryOrder() (msg QueryMSG, err error) { var res struct { Code int `json:"code"` MSG QueryMSG `json:"msg"` } body := make(map[string]string) body["mercId"] = s.GetMercID() body["tradeNo"] = s.TradeNo code, err := httputil.DefaultClientPostWithRespWithProxy(webg.ProxyCfg, &res, s.GetQueryURL(), nil, body) if err != nil || code != 200 { log.Error(fmt.Sprintf("shark QueryOrder http.Get fail error:%+v:", err)) return } if res.Code != 200 { err = errors.New("shark QueryOrder fail") return } msg = res.MSG return } // Fill 补全配置信息和签名信息 func (s *Shark) Fill() { s.Type = s.PayMethod s.MercID = s.GetMercID() s.NotifyURL = s.GetCallBackURL() if s.Info.Name == "" { s.Info.Name = GetFullName() } if s.Info.PlayerIP == "" { s.Info.PlayerIP = genIpaddr() } if s.Info.DeviceID == "" { s.Info.DeviceID = common.UUID() } if s.Info.DeviceType == "" { s.Info.DeviceType = "ios" } s.Sign = s.sign() } // sign 签名 func (s *Shark) sign() (sign string) { var buf bytes.Buffer buf.WriteString(s.GetMercID()) buf.WriteString(s.Money) buf.WriteString(s.GetCallBackURL()) buf.WriteString(s.TradeNo) buf.WriteString(s.Type) buf.WriteString(s.GetAppSecret()) md5Ctx := md5.New() md5Ctx.Write(buf.Bytes()) cipherStr := md5Ctx.Sum(nil) return hex.EncodeToString(cipherStr) } // GetBody 获取请求body func (s *Shark) GetBody() interface{} { jsonStr, err := json.Marshal(s) if err != nil { log.Error(fmt.Sprintf("shark GetBody json.Marshal fail error:%+v/data:%+v", err, s)) } log.Error(fmt.Sprintf("shark topay json body:%+v:", string(jsonStr))) return jsonStr } // GetHeader 获取请求头 func (s *Shark) GetHeader() map[string]string { header := make(map[string]string, 0) return header } // GetURL 获取请求地址 func (s *Shark) GetURL() string { return sc.ExeUrl } // GetQueryURL 获取查询请求地址 func (s *Shark) GetQueryURL() string { return sc.QueryUrl } // GetCallBackURL 获取回掉函数 func (s *Shark) GetCallBackURL() string { if appg.Conf != nil { return appg.Conf.URL.LocalWebUrl + sc.NotifyUrl } return webg.Conf.URL.LocalAppUrl + sc.NotifyUrl } // GetMercID 获取商户编号 func (s *Shark) GetMercID() string { return sc.MercID } // GetAppSecret 获取app签名密钥 func (s *Shark) GetAppSecret() string { return sc.AppSecret }