// 根据 URL RawQuery 来初始化 data *OrderNotifyURLData. // 如果 RawQuery 里的参数不合法(包括签名不正确) 则返回错误信息, 否则返回 nil. // partnerKey: 财付通商户权限密钥Key func (data *OrderNotifyURLData) CheckAndInit(RawQuery string, partnerKey string) (err error) { urlValues, err := url.ParseQuery(RawQuery) if err != nil { return } var signature string if vs := urlValues["sign"]; len(vs) > 0 && len(vs[0]) > 0 { signature = vs[0] } else { return errors.New("sign is empty") } var signMethod string if vs := urlValues["sign_type"]; len(vs) > 0 && len(vs[0]) > 0 { signMethod = vs[0] } else { signMethod = "MD5" } // 验证签名是否正确 =========================================================== switch signMethod { case "MD5", "md5": if len(signature) != md5.Size*2 { err = fmt.Errorf(`不正确的签名: %q, 长度不对, have: %d, want: %d`, signature, len(signature), md5.Size*2) return } urlValues.Del("sign") // sign 不参与签名 keys := make([]string, 0, len(urlValues)) for key := range urlValues { keys = append(keys, key) } sort.Strings(keys) Hash := md5.New() for _, key := range keys { // len(urlValues[key]) == 1, 都是单值 value := urlValues[key][0] if len(value) == 0 { continue } Hash.Write([]byte(key)) Hash.Write([]byte{'='}) Hash.Write([]byte(value)) Hash.Write([]byte{'&'}) } Hash.Write([]byte("key=")) Hash.Write([]byte(partnerKey)) SignatureHave := make([]byte, md5.Size*2) hex.Encode(SignatureHave, Hash.Sum(nil)) copy(SignatureHave, bytes.ToUpper(SignatureHave)) if subtle.ConstantTimeCompare(SignatureHave, []byte(signature)) != 1 { err = fmt.Errorf("不正确的签名, \r\nhave: %q, \r\nwant: %q", SignatureHave, signature) return } default: return fmt.Errorf("没有实现对签名方法 %q 的支持", signMethod) } // 初始化 =================================================================== data.Signature = signature data.SignMethod = signMethod if vs := urlValues["input_charset"]; len(vs) > 0 && len(vs[0]) > 0 { data.Charset = vs[0] } else { data.Charset = CHARSET_GBK } if vs := urlValues["notify_id"]; len(vs) > 0 && len(vs[0]) > 0 { data.NotifyId = vs[0] } else { return errors.New("notify_id is empty") } if vs := urlValues["trade_mode"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := strconv.ParseInt(vs[0], 10, 64) if err != nil { return err } data.TradeMode = int(v0) } else { return errors.New("trade_mode is empty") } if vs := urlValues["trade_state"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := strconv.ParseInt(vs[0], 10, 64) if err != nil { return err } data.TradeState = int(v0) } else { return errors.New("trade_state is empty") } if vs := urlValues["bank_billno"]; len(vs) > 0 { data.BankBillNo = vs[0] } if vs := urlValues["transaction_id"]; len(vs) > 0 && len(vs[0]) > 0 { data.TransactionId = vs[0] } else { return errors.New("transaction_id is empty") } if vs := urlValues["time_end"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := util.ParseTime(vs[0]) if err != nil { return err } data.TimeEnd = v0 } else { return errors.New("time_end is empty") } if vs := urlValues["bank_type"]; len(vs) > 0 && len(vs[0]) > 0 { data.BankType = vs[0] } else { return errors.New("bank_type is empty") } if vs := urlValues["partner"]; len(vs) > 0 && len(vs[0]) > 0 { data.PartnerId = vs[0] } else { return errors.New("partner is empty") } if vs := urlValues["out_trade_no"]; len(vs) > 0 && len(vs[0]) > 0 { data.OutTradeNo = vs[0] } else { return errors.New("out_trade_no is empty") } if vs := urlValues["attach"]; len(vs) > 0 { data.Attach = vs[0] } if vs := urlValues["total_fee"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := strconv.ParseInt(vs[0], 10, 64) if err != nil { return err } data.TotalFee = int(v0) } else { return errors.New("total_fee is empty") } if vs := urlValues["discount"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := strconv.ParseInt(vs[0], 10, 64) if err != nil { return err } data.Discount = int(v0) } if vs := urlValues["transport_fee"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := strconv.ParseInt(vs[0], 10, 64) if err != nil { return err } data.TransportFee = int(v0) } if vs := urlValues["product_fee"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := strconv.ParseInt(vs[0], 10, 64) if err != nil { return err } data.ProductFee = int(v0) } if vs := urlValues["fee_type"]; len(vs) > 0 && len(vs[0]) > 0 { v0, err := strconv.ParseInt(vs[0], 10, 64) if err != nil { return err } data.FeeType = int(v0) } else { return errors.New("fee_type is empty") } return }
func (this *OrderQueryResponse) GetTimeEnd() (t time.Time, err error) { return util.ParseTime(this.TimeEnd) }