package rchgutil import ( "bytes" "encoding/json" "errors" "fmt" "net/http" "reflect" "sort" "strconv" "strings" "time" "91porn-server/app/appg" "91porn-server/common/httputil" "91porn-server/common/log" "91porn-server/web/webg" ) var zfc = config{ MercID: "191309702", AppSecret: "oaha2s6ed67buc2rpy7of1p3mj17jpqwa0i0n3fjy633et7thwzmv1s3zbwaim9z2o4r3km799u8lp7a1luh1vpd350bazq5bmph66ffm3p9u8trow5lzmtmsx6b66rkya1up22x1rbjvhuby7wkpcidix064ay25d6ri48boo5f5fc0m05oi558d154qw6816p7ym1h52r2gsbndo6pi5i7qgonqp7aagkrh5ar3k3ircgvunqmcfbd4z45k9nz", ExeUrl: "http://www.518006.com/Pay_Index.html", QueryUrl: "http://www.518006.com/Pay_Trade_query.html", NotifyUrl: "/3rd/defray/callback/zhongfu", CallbackURL: "/refuse", VerifySecret: "muykk2dlwnmvsn5m5eg5ajs8vhfvfdihqqc2t2rd0297h2bwnkhf2jrk6qveffog038jsfsk4js0yjmkb9ydeijdtjbq98ouh8eqm04gvva3ql6mo0yknaq1v377mw1j", } // ZhongFu 充值订单请求体 type ZhongFu struct { Version string `json:"pay_version" sign:"1"` MercID string `json:"pay_memberid" sign:"1"` //商户编号 Type string `json:"pay_bankcode" sign:"1"` TradeNo string `json:"pay_orderid" sign:"1"` //商户订单号 Money string `json:"pay_amount" sign:"1"` // 充值⾦额 CallbackUrl string `json:"pay_callbackurl" sign:"1"` //支付成功后的跳转地址 NotifyURL string `json:"pay_notifyurl" sign:"1"` // 回调地址 ProductName string `json:"pay_productname"` // 商品信息 UserIP string `json:"pay_ip" sign:"1"` //用户ip SignType string `json:"pay_signtype" sign:"1"` //签名类型 Charset string `json:"pay_inputcharset" sign:"1"` Time string `json:"pay_applydate" sign:"1"` PayFormat string `json:"pay_retformat"` //参数类型 Sign string `json:"pay_md5sign" ` // 签名 PayMethod string `json:"pay_method,omitempty"` // 支付类型 } // ZhongFuRes 回调函数参数model type ZhongFuRes struct { Version string `json:"version" form:"version" sign:"1"` MercID string `json:"memberid" form:"memberid" sign:"1"` //商户编号 TradeNo string `json:"orderid" form:"orderid" sign:"1"` //商户订单号 OID string `json:"transaction_id" form:"transaction_id" sign:"1"` //支付平台订单号 PayMoney string `json:"amount" form:"amount" sign:"1"` //订单到账实际金额 PayTime string `json:"datetime" form:"datetime" sign:"1"` //交易时间 Code string `json:"returncode" form:"returncode" sign:"1"` Sign string `json:"sign" form:"sign"` //签名 } // ToPay 支付发起 func (this *ZhongFu) ToPay() (payUrl string, err error) { defer func(err *error, payUrl string, obj interface{}) { if err == nil && payUrl == "" { fmt.Printf("zhongfu ToPay Http.PostJson fail error:data %+v;\r\n", this) } }(&err, payUrl, this) var errlog string this.Fill() var msg struct { PayURL string `json:"payurl"` Msg string `json:"msg"` Data interface{} `json:"data"` Status string `json:"status"` } code, err := httputil.DefaultClientPostWithRespWithProxy(appg.ProxyCfg, &msg, this.GetURL(), this.GetHeader(), this.GetBody()) if err != nil { errlog = fmt.Sprintf("zhongfu ToPay Http.PostJson fail error:%+v/,data:%+v;", err, this) log.Error(errlog) err = errors.New(errlog) return } if code != http.StatusOK { errlog = fmt.Sprintf("zhongfu ToPay Http.PostJson fail error:%+v/,data:%+v;", err, code) log.Error(errlog) err = errors.New(errlog) return } if msg.Msg != "success" { errlog = fmt.Sprintf("zhongfu topay response err :%+v:", msg) err = errors.New(errlog) log.Error(errlog) return } payUrl = msg.PayURL return } // QueryOrder 订单状态查询发起 func (this *ZhongFuRes) QueryOrder() (payTime time.Time, err error) { msg := msgModel{} body := make(map[string]string) body["partner_id"] = zfc.MercID body["partner_order"] = this.TradeNo body["sign"] = md5Sign("partner_id=" + zfc.MercID + "&partner_order=" + this.TradeNo + "&key=" + zfc.AppSecret) code, err := httputil.DefaultClientPostWithRespWithProxy(webg.ProxyCfg, &msg, zfc.QueryUrl, nil, body) if err != nil || code != 200 { log.Error(fmt.Sprintf("zhongfu QueryOrder http.Get fail error:%+v:", err)) return } if msg.Code != 1 { err = errors.New("zhongfu QueryOrder fail") log.Error(fmt.Sprintf("zhongfu QueryOrder http.Get fail error:%+v:", msg)) return } loc, _ := time.LoadLocation("Local") payTime, err = time.ParseInLocation("2006-01-02 15:04:05", msg.Data.PayTime, loc) return } // Fill 补全配置信息和签名信息 func (this *ZhongFu) Fill() { this.Version = "v2.3.5" this.MercID = this.GetMercID() this.NotifyURL = this.GetNotifyURL() this.CallbackUrl = this.GetCallBackURL() if this.UserIP == "" { this.UserIP = genIpaddr() } this.Type = this.PayMethod this.PayMethod = "" this.Charset = "UTF-8" this.SignType = "MD5" this.PayFormat = "json" this.Sign = this.sign() } // sign 签名 func (this *ZhongFu) sign() (sign string) { ss := this.ToStringSlice() sort.Sort(&ss) var buf bytes.Buffer for k, v := range ss { if k == 0 { buf.WriteString(v) } else { buf.WriteString("&") buf.WriteString(v) } } buf.WriteString("&key=") buf.WriteString(this.GetAppSecret()) log.Info(fmt.Sprintf("ZhongFu topay sign :%s", buf.String())) return strings.ToUpper(md5Sign(buf.String())) } // sign 签名 func (this *ZhongFuRes) ToSign() (sign string) { ss := this.ToStringSlice() sort.Sort(&ss) var buf bytes.Buffer for _, v := range ss { buf.WriteString(v) buf.WriteString("&") } buf.WriteString("key=") buf.WriteString(zfc.VerifySecret) log.Info(fmt.Sprintf("ZhongFu callback sign:%s", buf.String())) str := buf.String() sign = strings.ToUpper(md5Sign(str)) return } // ToStringSlice 转化为stirng切片切片 func (this *ZhongFu) ToStringSlice() StringList { t := reflect.TypeOf(*this) v := reflect.ValueOf(*this) data := make([]string, 0, v.NumField()) for k := 0; k < v.NumField(); k++ { jsonTag, _ := t.Field(k).Tag.Lookup("json") signTag, _ := t.Field(k).Tag.Lookup("sign") fv := v.Field(k).Type() if signTag == "1" { switch fv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: data = append(data, jsonTag+"="+strconv.FormatInt(v.Field(k).Int(), 10)) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: data = append(data, jsonTag+"="+strconv.FormatUint(v.Field(k).Uint(), 10)) case reflect.String: data = append(data, jsonTag+"="+v.Field(k).String()) } } } return data } // ToStringSlice 转化为stirng切片切片 func (this *ZhongFuRes) ToStringSlice() StringList { t := reflect.TypeOf(*this) v := reflect.ValueOf(*this) data := make([]string, 0, v.NumField()) for k := 0; k < v.NumField(); k++ { jsonTag, _ := t.Field(k).Tag.Lookup("json") signTag, _ := t.Field(k).Tag.Lookup("sign") if signTag == "1" && v.Field(k).String() != "" { data = append(data, jsonTag+"="+v.Field(k).String()) } } return data } // GetBody 获取请求body func (this *ZhongFu) GetBody() interface{} { jsonStr, err := json.Marshal(this) if err != nil { log.Info(fmt.Sprintf("ZhongFu GetBody json.Marshal is fail error:%+v/data:%+v", err, this)) } log.Info(fmt.Sprintf("==================%+v", string(jsonStr))) return jsonStr } // GetHeader 获取请求头信息 func (*ZhongFu) GetHeader() map[string]string { return map[string]string{} } // GetURL 获取请求地址 func (*ZhongFu) GetURL() string { return zfc.ExeUrl } // GetQueryURL 获取请求地址 func (*ZhongFu) GetQueryURL() string { return zfc.QueryUrl } // GetLowAndUpperURL 获取请求地址 func (*ZhongFu) GetLowAndUpperURL() string { return zfc.LowAndUpperURL } // GetCallBackURL 获取回掉函数 func (*ZhongFu) GetNotifyURL() string { if appg.Conf != nil { return appg.Conf.URL.LocalWebUrl + zfc.NotifyUrl } return webg.Conf.URL.LocalAppUrl + zfc.NotifyUrl } // GetCallBackURL 获取回掉函数 func (*ZhongFu) GetCallBackURL() string { return zfc.CallbackURL } // GetMercID 获取商户编号 func (*ZhongFu) GetMercID() string { return zfc.MercID } // GetAppSecret 获取app签名密钥 func (*ZhongFu) GetAppSecret() string { return zfc.AppSecret }