package rchgutil import ( "bytes" "encoding/json" "errors" "fmt" "net/http" "sort" "strings" "time" "91porn-server/app/appg" "91porn-server/common/httputil" "91porn-server/common/log" ) var ylc = config{ MercID: "xq032", AppSecret: "635379bb1abe7ed814c95e083480b09aa2d47d5a", ExeUrl: "https://www.hsipxix.cn/?c=Pay", NotifyUrl: "/3rd/defray/callback/rchg/yongli", } // YongLi 充值订单请求体 type YongLi struct { MercID string `json:"mch_id" sign:"1"` //商户编号 Type string `json:"ptype" sign:"1"` // 订单充值类型 TradeNo string `json:"order_sn" sign:"1"` //商户订单号 Money string `json:"money" sign:"1"` // 支付金额:元 NotifyURL string `json:"notify_url" sign:"1"` // 回调地址 Time string `json:"time" sign:"1"` Sign string `json:"sign"` // 签名 PayMethod string `json:"-"` Format string `json:"format" sign:"1"` Desc string `json:"goods_desc" sign:"1"` IP string `json:"client_ip" sign:"1"` } type YongLiMsgData struct { Type string `json:"ptype" sign:"1"` // 订单充值类型 PayTypeName string `json:"ptype_name"` RealNmae string `json:"realnmae"` //姓名 Act string `json:"account"` //账户 PayMoney string `json:"pay_money"` Bank string `json:"bank"` //银行 QRcode string `json:"qrcode"` //二维码 PayURL string `json:"pay_url"` // OID string `json:"order_sn"` } type YongLiMsg struct { Code string `json:"code" sign:"1"` //交易返回码,返回SUCCESS 表示交易成功(不代表最终结果), Data interface{} `json:"data"` Msg string `json:"msg"` //签名 } // RYRes 回调函数参数model type YongLiBack struct { TradeNo string `json:"sh_order" form:"sh_order" sign:"1"` //商户订单号 OID string `json:"pt_order" form:"pt_order" sign:"1"` //订单号 PayMoney float32 `json:"money" form:"money" sign:"1"` //订单到账实际金额 PayTime int64 `json:"time" form:"time" sign:"1"` //支付时间 Status string `json:"status" form:"status" sign:"1"` //交易结果 1(成功) Sign string `json:"sign" form:"sign" ` //签名 } // ToPay 支付发起 func (this *YongLi) ToPay() (res RchgMsg, err error) { var errlog string this.Fill() msg := YongLiMsg{} code, err := httputil.DefaultClientPostJsonWithResp(&msg, this.GetURL(), this.GetHeader(), this.GetBody()) if err != nil { errlog = fmt.Sprintf("yongli 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("yongli ToPay response status exception;\nstatus %+v;", code) log.Error(errlog) err = errors.New(errlog) return } if msg.Code != "1" { errlog = fmt.Sprintf("yongli ToPay be rejected;\n msg:%+v:", msg) err = errors.New(errlog) log.Error(errlog) return } var data YongLiMsgData bytes, err := json.Marshal(msg.Data) if err != nil { errlog = fmt.Sprintf("yongli payUrl urlDecode fail \nerror:%+v;", err) log.Error(errlog) err = errors.New(errlog) return } if err = json.Unmarshal(bytes, &data); err != nil { errlog = fmt.Sprintf("yongli payUrl urlDecode fail \nerror:%+v;", err) log.Error(errlog) err = errors.New(errlog) return } res.PayUrl = data.PayURL res.OID = data.OID res.Mode = "url" return } // ASenCallBack 阿森结构回调函数 func (this *YongLiBack) Notify() (RchgBack, error) { r := RchgBack{} if this.Sign != this.ToSign() { err := errors.New("check sign fail") log.Error(fmt.Sprintf("ASen callback sign verify fail error:%+v:", err)) return r, err } r.Code = 200 if this.Status != "success" { r.Code = 400 } r.PaymentAt = time.Unix(this.PayTime, 0) r.PayMoney = int64(this.PayMoney * 100) r.TransNo = this.TradeNo r.OID = this.OID return r, nil } func (this *YongLiBack) Success() string { return "success" } // Fill 补全配置信息和签名信息 func (this *YongLi) Fill() { switch this.PayMethod { case "alipay": this.Type = "12" case "wechat": this.Type = "2" } this.PayMethod = "" this.Format = "json" this.Desc = "充值" this.IP = genIpaddr() this.MercID = this.GetMercID() this.NotifyURL = this.GetCallBackURL() this.Sign = this.sign() } // sign 签名 func (this *YongLi) sign() string { ss := ToStringSlice(*this) sort.Sort(&ss) var buf bytes.Buffer for k := range ss { buf.WriteString(ss[k]) buf.WriteString("&") } buf.WriteString("key=" + ylc.AppSecret) s := buf.String() log.Info(fmt.Sprintf("--------------%s", s)) return strings.ToLower(md5Sign(s)) } // sign 签名 func (this *YongLiBack) ToSign() string { ss := ToStringSlice(*this) sort.Sort(&ss) var buf bytes.Buffer for k := range ss { buf.WriteString(ss[k]) buf.WriteString("&") } buf.WriteString("key=" + ylc.AppSecret) log.Info(fmt.Sprintf("--------------%s", buf.String())) return strings.ToLower(md5Sign(buf.String())) } // GetBody 获取请求body func (this *YongLi) GetBody() interface{} { m := make(map[string]string) jsonStr, err := json.Marshal(this) if err != nil { log.Info(fmt.Sprintf("YongLi GetBody json.Marshal is fail error:%+v/data:%+v", err, this)) } // sstr := string(jsonStr) _ = json.Unmarshal(jsonStr, &m) log.Info(fmt.Sprintf("==================%+v", m)) return m } // GetHeader 获取请求头信息 func (g *YongLi) GetHeader() map[string]string { header := make(map[string]string, 0) return header } // GetURL 获取请求地址 func (*YongLi) GetURL() string { return ylc.ExeUrl } // GetCallBackURL 获取回掉函数 func (*YongLi) GetCallBackURL() string { return appg.Conf.URL.LocalWebUrl + ylc.NotifyUrl } // GetMercID 获取商户编号 func (*YongLi) GetMercID() string { return ylc.MercID }