package rchgutil import ( "bytes" "encoding/json" "errors" "fmt" "net/http" "reflect" "sort" "strings" "91porn-server/app/appg" "91porn-server/common/httputil" "91porn-server/common/log" "91porn-server/web/webg" ) var yc = config{ MercID: "cm0020983778", AppSecret: "8EB5C35ED06CC6EFE8020D8B67B7E867", ExeUrl: "http://api.nb536.com/gateway", NotifyUrl: "/3rd/defray/callback/yilianfu", } // YiLIanFu 充值订单请求体 type YiLIanFu struct { Type string `sign:"1" json:"method"` // 产品编码 Version string `sign:"1" json:"version" ` //版本 MercID string `sign:"1" json:"mch_id"` //商户编号 SignType string `sign:"1" json:"sign_type"` //签名类型 Money string `sign:"1" json:"total_amount" ` // 充值⾦额 NonceStr string `sign:"1" json:"nonce_str"` //随机字符串 TradeNo string `sign:"1" json:"mch_order_no"` //商户订单号 ProductName string `sign:"1" json:"body"` // 商品信息 CurCode string `sign:"1" json:"cur_code"` //币种 PayIP string `sign:"1" json:"spbill_create_ip"` //终端ip Time string `sign:"1" json:"mch_req_time"` //提交时间2016-12-26 18:18:18 NotifyURL string `sign:"1" json:"notify_url"` // 回调地址 Sign string `sign:"1" json:"sign" ` // 签名 PayMethod string `json:"paymethod,omitempty"` //付款方式 扫码|h5 } // YiLIanFuRes 回调函数参数model type YiLIanFuRes struct { Type string `sign:"1" json:"method"` // 产品编码 Version string `sign:"1" json:"version"` Charset string `sign:"1" json:"charset"` SignType string `sign:"1" json:"sign_type"` MercID string `sign:"1" json:"mch_id"` NonceStr string `sign:"1" json:"nonce_str"` Sign string `json:"sign"` ResCode string `sign:"1" json:"result_code"` //业务状态码 ErrCode string `sign:"1" json:"err_code"` //错误码 ErrCodeDes string `sign:"1" json:"err_code_des"` //错误原因 CurCode string `sign:"1" json:"cur_code"` //币种 Money string `sign:"1" json:"total_amount"` // 充值⾦额 PayMoney string `sign:"1" json:"real_amount"` //实付金额 BankOrderNo string `sign:"1" json:"bank_order_no"` //银行订单号 ChannelOrderNo string `sign:"1" json:"channel_order_no"` //通道订单号 OID string `sign:"1" json:"order_no"` TradeNo string `sign:"1" json:"mch_order_no"` //商户订单号 PayTime string `sign:"1" json:"order_finish_time"` //支付时间 } type YiLIanFuData struct { Version string `sign:"1" json:"version"` Charset string `sign:"1" json:"charset"` SignType string `sign:"1" json:"sign_type"` Code string `sign:"1" json:"return_code"` Msg string `sign:"1" json:"return_msg"` NonceStr string `sign:"1" json:"nonce_str"` MercID string `sign:"1" json:"mch_id"` ResCode string `sign:"1" json:"result_code"` //业务状态码 Sign string `json:"sign"` ErrCode string `sign:"1" json:"err_code"` //错误码 ErrCodeDes string `sign:"1" json:"err_code_des"` //错误原因 OID string `sign:"1" json:"order_no"` PayUrl string `sign:"1" json:"code_url"` TimeExpire string `sign:"1" json:"time_expire"` } // ToPay 支付发起 func (this *YiLIanFu) ToPay() (payURL string, err error) { var errlog string this.Fill() var msg YiLIanFuData code, err := httputil.DefaultClientPostWithRespWithProxy(appg.ProxyCfg, &msg, this.GetURL(), this.GetHeader(), this.GetBody()) if err != nil { errlog = fmt.Sprintf("YiLIanFu 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("YiLIanFu ToPay Http.PostJson fail error:%+v/,data:%+v;", err, code) err = errors.New(errlog) log.Error(errlog) return } if msg.ResCode != "SUCCESS" { bytes, _ := json.Marshal(msg) errlog = fmt.Sprintf("YiLIanFu topay response err :%+v:", string(bytes)) err = errors.New(errlog) log.Error(errlog) return } payURL = msg.PayUrl return } // Fill 补全配置信息和签名信息 func (this *YiLIanFu) Fill() { this.Version = "1.0" this.Type = this.PayMethod this.PayMethod = "" this.MercID = this.GetMercID() this.NotifyURL = this.GetNotifyURL() this.SignType = "MD5" this.NonceStr = RandStringBytesMaskImpr(10) this.CurCode = "CNY" if this.PayIP == "" { this.PayIP = genIpaddr() } this.Sign = this.sign() } // sign 签名 func (this *YiLIanFu) 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()) str := buf.String() log.Info(fmt.Sprintf("YiLIanFu topay sign :%s", str)) return strings.ToUpper(md5Sign(buf.String())) } // sign 签名 func (this *YiLIanFuRes) ToSign() 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(yc.AppSecret) return strings.ToUpper(md5Sign(buf.String())) } // ToStringSlice 转化为stirng切片切片 func (this *YiLIanFu) 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 v.Field(k).String() != "" && signTag == "1" { data = append(data, jsonTag+"="+v.Field(k).String()) } } return data } // ToStringSlice 转化为stirng切片切片 func (this *YiLIanFuRes) ToStringSlice() StringList { t := reflect.TypeOf(*this) v := reflect.ValueOf(*this) data := make([]string, 0, t.NumField()) for k := 0; k < t.NumField(); k++ { jsonTag, _ := t.Field(k).Tag.Lookup("json") signTag, _ := t.Field(k).Tag.Lookup("sign") if v.Field(k).String() != "" && signTag == "1" { data = append(data, jsonTag+"="+v.Field(k).String()) } } return data } // ToStringSlice 转化为stirng切片切片 func (this *YiLIanFuData) ToStringSlice() StringList { t := reflect.TypeOf(*this) v := reflect.ValueOf(*this) data := make([]string, 0, t.NumField()) for k := 0; k < t.NumField(); k++ { jsonTag, _ := t.Field(k).Tag.Lookup("json") signTag, _ := t.Field(k).Tag.Lookup("sign") if v.Field(k).String() != "" && signTag == "1" { data = append(data, jsonTag+"="+v.Field(k).String()) } } return data } // GetBody 获取请求body func (this *YiLIanFu) GetBody() interface{} { m := make(map[string]string) jsonStr, err := json.Marshal(this) if err != nil { log.Info(fmt.Sprintf("YiLIanFu GetBody json.Marshal is fail error:%+v/data:%+v", err, this)) } sstr := string(jsonStr) _ = json.Unmarshal(jsonStr, &m) log.Info(fmt.Sprintf("YiLIanFu topay json data :%+v", sstr)) return m } // GetHeader 获取请求头信息 func (this *YiLIanFu) GetHeader() map[string]string { header := make(map[string]string, 0) return header } // GetURL 获取请求地址 func (*YiLIanFu) GetURL() string { return yc.ExeUrl } // GetQueryURL 获取请求地址 func (*YiLIanFu) GetQueryURL() string { return yc.QueryUrl } // GetCallBackURL 获取回掉函数 func (*YiLIanFu) GetNotifyURL() string { if appg.Conf != nil { return appg.Conf.URL.LocalWebUrl + yc.NotifyUrl } return webg.Conf.URL.LocalAppUrl + yc.NotifyUrl } // GetCallBackURL 获取回掉函数 func (*YiLIanFu) GetCallBackURL() string { return yc.CallbackURL } // GetMercID 获取商户编号 func (*YiLIanFu) GetMercID() string { return yc.MercID } // GetAppSecret 获取app签名密钥 func (*YiLIanFu) GetAppSecret() string { return yc.AppSecret }