package rchgutil import ( "bytes" "encoding/json" "errors" "fmt" "net/http" "reflect" "sort" "strings" "time" "91porn-server/app/appg" "91porn-server/common" "91porn-server/common/httputil" "91porn-server/common/log" "91porn-server/web/webg" ) var dc = config{ MercID: "191228889", AppSecret: "buptpyxrn8agj1pivx3bl90mu91rx6ih", ExeUrl: "https://api.parado.vip/Pay_Index.html", QueryUrl: "https://api.parado.vip/Pay_Trade_query.html", NotifyUrl: "/3rd/defray/callback/dx", CallbackURL: "/refuse", } // DXZhiFu 充值订单请求体 type DXZhiFu struct { MercID string `json:"pay_memberid" sign:"1"` //商户编号 TradeNo string `json:"pay_orderid" sign:"1"` //商户订单号 Time string `json:"pay_applydate" sign:"1"` //提交时间2016-12-26 18:18:18 Type string `json:"pay_bankcode" sign:"1"` // 产品编码 NotifyURL string `json:"pay_notifyurl" sign:"1"` // 回调地址 CallbackUrl string `json:"pay_callbackurl" sign:"1"` //支付成功后的跳转地址 Money string `json:"pay_amount" sign:"1"` // 充值⾦额 Format string `json:"format"` PayIP string `json:"pay_ip"` ProductName string `json:"pay_productname"` // 商品信息 Sign string `json:"pay_md5sign" ` // 签名 PayMethod string //付款方式 扫码|h5 } // DXZhiFuRes 回调函数参数model type DXZhiFuRes struct { MercID string `json:"memberid" form:"memberid" sign:"1"` //商户编号 TradeNo string `json:"orderid" form:"orderid" sign:"1"` //商户订单号 PayMoney string `json:"amount" form:"amount" sign:"1"` //订单到账实际金额 OID string `json:"transaction_id" form:"transaction_id" sign:"1"` //支付平台订单号 DateTime string `json:"datetime" form:"datetime" sign:"1"` //交易时间 Code string `json:"returncode" form:"returncode" sign:"1"` Sign string `json:"sign" form:"sign" ` //签名 } type DXZhiFuData struct { PageURL string `json:"pageUrl"` //支付地址 原生 PayURL string `json:"qrcodeUrl"` //支付地址 LockSeconds int `json:"lock_seconds"` //有效时间 Body string `json:"body"` //消息内容 Money string `json:"payAmount"` //实际支付金额 } // ToPay 支付发起 func (this *DXZhiFu) ToPay() (payURL string, err error) { var errlog string this.Fill() var msgModel struct { Status string `json:"status"` Msg string `json:"msg"` Data DXZhiFuData `json:"data"` } code, err := httputil.DefaultClientPostJsonWithRespWithProxy(appg.ProxyCfg, &msgModel, this.GetURL(), this.GetHeader(), this.GetBody()) if err != nil { errlog = fmt.Sprintf("DXZhiFu 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("DXZhiFu ToPay Http.PostJson fail error:%+v/,data:%+v;", err, code) err = errors.New(errlog) log.Error(errlog) return } if 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.Data.PageURL return } // QueryOrder 订单状态查询发起 func (this *DXZhiFuRes) QueryOrder() (*time.Time, error) { var msg struct { MercID string `json:"memberid" sign:"1"` OID string `json:"orderid" sign:"1"` Money string `json:"amount" sign:"1"` PayTime string `json:"time_end" sign:"1"` TradeNO string `json:"transaction_id" sign:"1"` Code string `json:"returncode" sign:"1"` Status string `json:"trade_state" sign:"1"` Sign string `json:"sign" sign:"1"` } this.MercID = dc.MercID this.Sign = this.ToSign() hearder := make(map[string]string) hearder["Content-Type"] = " application/x-www-form-urlencoded" code, err := httputil.DefaultClientPostWithRespWithProxy(webg.ProxyCfg, &msg, dc.QueryUrl, hearder, common.StructToMap(*this)) if err != nil || code != 200 { log.Error(fmt.Sprintf("DXZhiFu QueryOrder http.Get fail error:%+v:", err)) return nil, err } if msg.Code != "00" { err = errors.New("DXZhiFu QueryOrder http query fail") return nil, err } if msg.Status != "SUCCESS" { return nil, errors.New("DXZhiFu order not pay:" + this.TradeNo) } loc, _ := time.LoadLocation("Local") paymentAt, _ := time.ParseInLocation("20060102150405", msg.PayTime, loc) return &paymentAt, nil } // Fill 补全配置信息和签名信息 func (this *DXZhiFu) Fill() { this.Format = "json" this.MercID = this.GetMercID() this.NotifyURL = this.GetNotifyURL() this.Type = this.PayMethod this.CallbackUrl = this.GetCallBackURL() if this.PayIP == "" { this.PayIP = genIpaddr() } this.Sign = this.sign() } // sign 签名 func (this *DXZhiFu) 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("DXZhiFu topay sign :%s", buf.String())) sign = strings.ToUpper(md5Sign(buf.String())) return } // sign 签名 func (this *DXZhiFuRes) ToSign() (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(dc.AppSecret) sign = strings.ToUpper(md5Sign(buf.String())) return } // ToStringSlice 转化为stirng切片切片 func (this *DXZhiFu) ToStringSlice() StringList { data := make([]string, 0) 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") if v.Field(k).String() != "" && signTag == "1" { data = append(data, jsonTag+"="+v.Field(k).String()) } } return data } // ToStringSlice 转化为stirng切片切片 func (this *DXZhiFuRes) ToStringSlice() StringList { data := make([]string, 0) t := reflect.TypeOf(*this) v := reflect.ValueOf(*this) 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 *DXZhiFu) GetBody() interface{} { m := make(map[string]string) jsonStr, err := json.Marshal(this) if err != nil { log.Info(fmt.Sprintf("DXZhiFu GetBody json.Marshal is fail error:%+v/data:%+v", err, this)) } sstr := string(jsonStr) _ = json.Unmarshal(jsonStr, &m) log.Info(fmt.Sprintf("DXZhiFu topay json data :%+v", sstr)) return m } // GetHeader 获取请求头信息 func (this *DXZhiFu) GetHeader() map[string]string { header := make(map[string]string, 0) return header } // GetURL 获取请求地址 func (*DXZhiFu) GetURL() string { return dc.ExeUrl } // GetQueryURL 获取请求地址 func (*DXZhiFu) GetQueryURL() string { return dc.QueryUrl } // GetCallBackURL 获取回掉函数 func (*DXZhiFu) GetNotifyURL() string { if appg.Conf != nil { return appg.Conf.URL.LocalWebUrl + dc.NotifyUrl } return webg.Conf.URL.LocalAppUrl + dc.NotifyUrl } // GetCallBackURL 获取回掉函数 func (*DXZhiFu) GetCallBackURL() string { return dc.CallbackURL } // GetMercID 获取商户编号 func (*DXZhiFu) GetMercID() string { return dc.MercID } // GetAppSecret 获取app签名密钥 func (*DXZhiFu) GetAppSecret() string { return dc.AppSecret }