package rchgutil import ( "bytes" "encoding/json" "errors" "fmt" "net/http" "reflect" "sort" "strconv" "strings" _ "strings" "91porn-server/app/appg" "91porn-server/common/httputil" "91porn-server/common/log" v10 "91porn-server/common/v10" "91porn-server/web/webg" "github.com/go-ego/gpy" ) var lhc = config{ MercID: "2019888612875", AppSecret: "8ebff22391be4c88ff7398b63e6084ad", ExeUrl: "http://bizpay12875.kyjihua.cn/cashier/", NotifyUrl: "/3rd/defray/callback/leihuo", } // LeiHuo 充值订单请求体 type LeiHuo struct { TradeNo string `json:"bizorderid" sign:"1"` //商户订单号 Type string `json:"channel" sign:"1"` // 产品编码 NotifyURL string `json:"notifyurl" sign:"1"` // 回调地址 MercID string `json:"platformid" sign:"1"` //商户编号 SignType string `json:"signtype" sign:"1"` // ProductName string `json:"subject" sign:"1"` // 商品信息 Money string `json:"tradeamount" sign:"1"` // 充值⾦额 Sign string `json:"sign" form:"sign"` //签名 PayMethod string `json:"payMethod,omitempty"` //付款方式 扫码|h5 } // LeiHuoRes 回调函数参数model type LeiHuoRes struct { TradeNo string `json:"bizOrderID" form:"bizOrderID" sign:"1"` //商户订单号 MercID string `json:"PlatformID" form:"PlatformID" sign:"1"` //商户编号 OID string `json:"RequestID" form:"RequestID" sign:"1"` //系统流水号 SignType string `json:"SignType" form:"SignType" sign:"1"` //签名类型 Status string `json:"Status" form:"Status" sign:"1"` //支付平台订单号 PayMoney string `json:"TradeAmount" form:"TradeAmount" sign:"1"` //订单到账实际金额 Sign string `json:"sign" form:"sign"` //签名 } type LeiHuoData struct { Code int `json:"code"` Msg string `json:"msg"` OID int64 `json:"RequestID"` PayURL string `json:"Url"` //支付地址 } // ToPay 支付发起 func (this *LeiHuo) ToPay() (payURL string, err error) { var errlog string this.Fill() var msgModel LeiHuoData code, err := httputil.DefaultClientPostWithRespWithProxy(appg.ProxyCfg, &msgModel, this.GetURL(), this.GetHeader(), this.GetBody()) if err != nil { errlog = fmt.Sprintf("LeiHuo ToPay Http.PostJson fail error:%+v/,data:%+v;", err, this) err = errors.New(errlog) log.Error(errlog) return } if code != http.StatusOK { errlog = fmt.Sprintf("LeiHuo ToPay Http.PostJson fail error:%+v/,data:%+v;", err, code) err = errors.New(errlog) log.Error(errlog) return } if msgModel.Code == 1 && msgModel.Msg != "success" { bytes, _ := json.Marshal(msgModel) errlog = fmt.Sprintf("LeiHuo topay response err :%s:", string(bytes)) err = errors.New(errlog) log.Error(errlog) return } payURL = msgModel.PayURL return } // Fill 补全配置信息和签名信息 func (this *LeiHuo) Fill() { if v10.IsPureChineseChar(this.ProductName) { a := gpy.NewArgs() this.ProductName = strings.Join(gpy.LazyConvert(this.ProductName, &a), "-") } this.SignType = "MD5" this.MercID = this.GetMercID() this.NotifyURL = this.GetNotifyURL() this.Type = this.PayMethod this.PayMethod = "" this.Sign = this.sign() } // sign 签名 func (this *LeiHuo) 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(this.GetAppSecret()) log.Info(fmt.Sprintf("LeiHuo topay sign :%s", buf.String())) sign = md5Sign(buf.String()) return } // sign 签名 func (this *LeiHuoRes) ToSign() (sign string) { var buf bytes.Buffer t := reflect.TypeOf(*this) v := reflect.ValueOf(*this) 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) if signTag == "1" { if k != 0 { buf.WriteString("&") } buf.WriteString(jsonTag) buf.WriteString("=") switch fv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: buf.WriteString(strconv.FormatInt(v.Field(k).Int(), 10)) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: buf.WriteString(strconv.FormatUint(v.Field(k).Uint(), 10)) case reflect.String: content := v.Field(k).String() buf.WriteString(content) } } } buf.WriteString(lhc.AppSecret) sign = md5Sign(buf.String()) return } // ToStringSlice 转化为stirng切片切片 func (this *LeiHuo) ToStringSlice() StringList { t := reflect.TypeOf(*this) v := reflect.ValueOf(*this) data := make([]string, 0, v.NumField()) for k := 0; k < v.NumField(); k++ { fv := v.Field(k) jsonTag, _ := t.Field(k).Tag.Lookup("json") signTag, _ := t.Field(k).Tag.Lookup("sign") 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.Float32, reflect.Float64: data = append(data, jsonTag+"="+strconv.FormatFloat(v.Field(k).Float(), 'f', 2, 64)) case reflect.String: content := v.Field(k).String() if v10.IsPureChineseChar(content) { a := gpy.NewArgs() content = strings.Join(gpy.LazyConvert(content, &a), "-") } data = append(data, jsonTag+"="+content) } } } return data } // GetBody 获取请求body func (this *LeiHuo) GetBody() interface{} { m := make(map[string]string) jsonStr, err := json.Marshal(this) if err != nil { log.Info(fmt.Sprintf("LeiHuo GetBody json.Marshal is fail error:%+v/data:%+v", err, this)) } sstr := string(jsonStr) _ = json.Unmarshal(jsonStr, &m) log.Info(fmt.Sprintf("LeiHuo topay json data :%+v", sstr)) return m } // GetHeader 获取请求头信息 func (this *LeiHuo) GetHeader() map[string]string { header := make(map[string]string, 0) //header["Content-Type"] = "application/json;charset=utf-8" return header } // GetURL 获取请求地址 func (*LeiHuo) GetURL() string { return lhc.ExeUrl } // GetQueryURL 获取请求地址 func (*LeiHuo) GetQueryURL() string { return lhc.QueryUrl } // GetCallBackURL 获取回掉函数 func (*LeiHuo) GetNotifyURL() string { if appg.Conf != nil { return appg.Conf.URL.LocalWebUrl + lhc.NotifyUrl } return webg.Conf.URL.LocalAppUrl + lhc.NotifyUrl } // GetCallBackURL 获取回掉函数 func (*LeiHuo) GetCallBackURL() string { return lhc.CallbackURL } // GetMercID 获取商户编号 func (*LeiHuo) GetMercID() string { return lhc.MercID } // GetAppSecret 获取app签名密钥 func (*LeiHuo) GetAppSecret() string { return lhc.AppSecret }