package rchgutil import ( "crypto/rc4" "encoding/json" "errors" "fmt" "net/http" "strconv" "time" "91porn-server/app/appg" "91porn-server/common/httputil" "91porn-server/common/log" ) var ylws = config{ MercID: "10105", AppSecret: "DA1C5476400B1D", ExeUrl: "http://x.aee7.com/gateway/index/checkpoint.do?", NotifyUrl: "/3rd/defray/callback/rchg/", } // 订单请求体 type WsylInfo struct { AccountId string `json:"account_id"` // 商户ID ContentType string `json:"content_type"` // 返回的网页类型 Thoroughfare string `json:"thoroughfare"` // 通道 Type string `json:"type"` // 支付类型 OutTradeNo string `json:"out_trade_no"` // 商户订单号 Robin string `json:"robin"` // 轮训 UseCity string `json:"use_city"` // 按地区收款 Amount string `json:"amount"` // 支付金额 CallbackUrl string `json:"callback_url"` // 异步通知地址 SuccessUrl string `json:"success_url"` // 支付成功后网页自动跳转地址 ErrorUrl string `json:"error_url"` // 支付失败时,或支付超时后网页自动跳转地址 Sign string `json:"sign"` // 签名 必填 } type WsylMsgData struct { OrderId string `json:"order_id"` Qrcode string `json:"qrcode"` } type WsylMsg struct { Code int `json:"code"` // 交易返回码,返回SUCCESS 表示交易成功(不代表最终结果), Msg string `json:"msg"` // 签名 Data interface{} `json:"data,omitempty"` } // 回调函数参数 type WsylResultRes struct { AccountName string `form:"account_name" json:"account_name"` // 商户登录名 PayTime string `form:"pay_time" json:"pay_time"` // 支付成功的时间戳(10位) Status string `form:"status" json:"status"` // 状态 Amount string `form:"amount" json:"amount"` // 订单到账实际金额 OutTradeNo string `form:"out_trade_no" json:"out_trade_no"` // 订单信息,在发起订单时附加的信息,如用户名,充值订单号等字段参数 TradeNo string `form:"trade_no" json:"trade_no"` // 交易流水号,由系统生成的交易流水号 Fees string `form:"fees" json:"fees"` // 手续费,本次回调过程产生的手续费用(已经在平台账户中扣除) Sign string `form:"sign" json:"sign"` // 签名 CallbackTime string `form:"callback_time" json:"callback_time"` // 回调时间,在回调时产生的时间戳(10位) Type string `form:"type" json:"type"` // 支付类型 AccountKey string `form:"account_key" json:"account_key"` // 商户KEY } // ToPay 支付发起 func (wyi *WsylInfo) toPay() (res RchgMsg, err error) { var errLog string msg := WsylMsg{} wyi.fill() code, err := httputil.DefaultClientPostJsonWithResp(&msg, ylws.ExeUrl, wyi.getHeader(), wyi.getBody()) if err != nil { errLog = fmt.Sprintf("Wsyl ToPay requset fail \nerror:%+v\n\ndata:%+v;", err, wyi) log.Error(errLog) err = errors.New(errLog) return } if code != http.StatusOK { errLog = fmt.Sprintf("Wsyl ToPay response status exception;\nstatus %+v;", code) log.Error(errLog) err = errors.New(errLog) return } if msg.Code != 200 { errLog = fmt.Sprintf("Wsyl ToPay be rejected;\n msg:%+v:", msg) err = errors.New(errLog) log.Error(errLog) return } var data WsylMsgData bytes, err := json.Marshal(msg.Data) if err != nil { errLog = fmt.Sprintf("Wsyl 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("Wsyl payUrl urlDecode fail \nerror:%+v;", err) log.Error(errLog) err = errors.New(errLog) return } res.PayUrl = data.Qrcode res.Mode = "url" res.OID = data.OrderId return } // Notify 回调函数 func (this *WsylResultRes) Notify() (RchgBack, error) { r := RchgBack{} if this.SignRes() != this.Sign { log.Error(fmt.Sprintf("Wsyl callback sign verify fail ,data:%+v", this)) return r, errors.New("check sign fail") } if this.PayTime == "" { return r, errors.New("querry order err,no payTime") } sec, err := strconv.ParseInt(this.PayTime, 10, 64) if err != nil { log.Error("time.ParseInLocation failed", log.Any("TradeNo", this.TradeNo), log.E(err)) return r, err } paymentAt := time.Unix(sec, 0) payMoneyf, err := strconv.ParseFloat(this.Amount, 64) if err != nil { log.Error(fmt.Sprintf("Wsyl callback ParseFloat fail data:%+v:", this)) return r, fmt.Errorf("invalid payMoney %s", this.Amount) } r.PayMoney = int64(payMoneyf * 100) r.PaymentAt = paymentAt r.TransNo = this.OutTradeNo r.OID = this.TradeNo r.Code = 400 if this.Status == "success" { r.Code = 200 } return r, nil } func (this *WsylResultRes) Success() string { return "success" } // 补全配置信息和签名信息 func (wyi *WsylInfo) fill() { wyi.AccountId = ylws.MercID wyi.ContentType = "json" wyi.Thoroughfare = "paofen_auto" wyi.Type = "71" wyi.Robin = "2" wyi.UseCity = "2" wyi.CallbackUrl = wyi.getNotifyURL() wyi.SuccessUrl = wyi.getNotifyURL() wyi.ErrorUrl = wyi.getNotifyURL() wyi.Sign = wyi.signReq() } // 充值请求签名 func (wyi *WsylInfo) signReq() (sign string) { return DealSign(ylws.AppSecret, wyi.Amount, wyi.OutTradeNo) } func DealSign(key_id string, amount string, out_trade_no string) (sign string) { var data = amount + out_trade_no md5Str := md5Sign(data) c, err := rc4.NewCipher([]byte(key_id)) if err != nil { // log.Fatalln(err) return } src := []byte(md5Str) dst := make([]byte, len(src)) c.XORKeyStream(dst, src) fmt.Println(string(src), string(dst)) rc4Str := md5Sign(string(dst)) return rc4Str } // 充值成功回调签名 func (wyc *WsylResultRes) SignRes() (sign string) { return DealSign(ylws.AppSecret, wyc.Amount, wyc.OutTradeNo) } // 获取请求body func (wyi *WsylInfo) getBody() interface{} { m := make(map[string]string) jsonStr, err := json.Marshal(wyi) if err != nil { log.Info(fmt.Sprintf("WSYL GetBody json.Marshal is fail error:%+v/data:%+v", err, wyi)) } sstr := string(jsonStr) log.Info(fmt.Sprintf("==================%+v", sstr)) _ = json.Unmarshal(jsonStr, &m) return m } // 获取请求头 func (wyi *WsylInfo) getHeader() map[string]string { return nil } // 获取回掉函数 func (wyi *WsylInfo) getNotifyURL() (url string) { return appg.Conf.URL.LocalWebUrl + ylws.NotifyUrl + YongLiWanShun }