func ServeHTTP(w http.ResponseWriter, r *http.Request, queryValues url.Values, srv Server, errHandler ErrorHandler) { switch r.Method { case "POST": RawMsgXML, err := ioutil.ReadAll(r.Body) if err != nil { errHandler.ServeError(w, r, err) return } msg, err := util.ParseXMLToMap(bytes.NewReader(RawMsgXML)) if err != nil { errHandler.ServeError(w, r, err) return } ReturnCode, ok := msg["return_code"] if ReturnCode == ReturnCodeSuccess || !ok { haveAppId := msg["appid"] wantAppId := srv.AppId() if wantAppId != "" && !security.SecureCompareString(haveAppId, wantAppId) { err = fmt.Errorf("the message's appid mismatch, have: %s, want: %s", haveAppId, wantAppId) errHandler.ServeError(w, r, err) return } haveMchId := msg["mch_id"] wantMchId := srv.MchId() if wantMchId != "" && !security.SecureCompareString(haveMchId, wantMchId) { err = fmt.Errorf("the message's mch_id mismatch, have: %s, want: %s", haveMchId, wantMchId) errHandler.ServeError(w, r, err) return } // 认证签名 signature1, ok := msg["sign"] if !ok { err = errors.New("no sign parameter") errHandler.ServeError(w, r, err) return } signature2 := Sign(msg, srv.APIKey(), nil) if !security.SecureCompareString(signature1, signature2) { err = fmt.Errorf("check signature failed, \r\ninput: %q, \r\nlocal: %q", signature1, signature2) errHandler.ServeError(w, r, err) return } } req := &Request{ HttpRequest: r, RawMsgXML: RawMsgXML, Msg: msg, } srv.MessageHandler().ServeMessage(w, req) default: errHandler.ServeError(w, r, errors.New("Not expect Request.Method: "+r.Method)) } }
// 微信支付通用请求方法. // 注意: err == nil 表示协议状态都为 SUCCESS. func (proxy *Proxy) PostXML(url string, req map[string]string) (resp map[string]string, err error) { bodyBuf := textBufferPool.Get().(*bytes.Buffer) bodyBuf.Reset() defer textBufferPool.Put(bodyBuf) if err = util.FormatMapToXML(bodyBuf, req); err != nil { return } LogInfoln("[WECHAT_DEBUG] request url:", url) LogInfoln("[WECHAT_DEBUG] request xml:", bodyBuf.String()) httpResp, err := proxy.httpClient.Post(url, "text/xml; charset=utf-8", bodyBuf) if err != nil { return } defer httpResp.Body.Close() if httpResp.StatusCode != http.StatusOK { err = fmt.Errorf("http.Status: %s", httpResp.Status) return } respBody, err := ioutil.ReadAll(httpResp.Body) if err != nil { return } LogInfoln("[WECHAT_DEBUG] response xml:", string(respBody)) if resp, err = util.ParseXMLToMap(bytes.NewReader(respBody)); err != nil { return } // 判断协议状态 ReturnCode, ok := resp["return_code"] if !ok { err = errors.New("no return_code parameter") return } if ReturnCode != ReturnCodeSuccess { err = &Error{ ReturnCode: ReturnCode, ReturnMsg: resp["return_msg"], } return } // 认证签名 signature1, ok := resp["sign"] if !ok { err = errors.New("no sign parameter") return } signature2 := Sign(resp, proxy.apiKey, nil) if signature1 != signature2 { err = fmt.Errorf("check signature failed, \r\ninput: %q, \r\nlocal: %q", signature1, signature2) return } return }
// 微信支付通用请求方法. // 注意: err == nil 表示协议状态都为 SUCCESS. func (clt *Client) PostXML(url string, req map[string]string) (resp map[string]string, err error) { bodyBuf := textBufferPool.Get().(*bytes.Buffer) bodyBuf.Reset() defer textBufferPool.Put(bodyBuf) if err = util.FormatMapToXML(bodyBuf, req); err != nil { return } httpResp, err := clt.httpClient.Post(url, "text/xml; charset=utf-8", bodyBuf) if err != nil { return } defer httpResp.Body.Close() if httpResp.StatusCode != http.StatusOK { err = fmt.Errorf("http.Status: %s", httpResp.Status) return } if resp, err = util.ParseXMLToMap(httpResp.Body); err != nil { return } // 判断协议状态 ReturnCode, ok := resp["return_code"] if !ok { err = errors.New("no return_code parameter") return } if ReturnCode != ReturnCodeSuccess { err = &Error{ ReturnCode: ReturnCode, ReturnMsg: resp["return_msg"], } return } // 认证签名 signature1, ok := resp["sign"] if !ok { err = errors.New("no sign parameter") return } signature2 := Sign(resp, clt.apiKey, nil) if signature1 != signature2 { err = fmt.Errorf("check signature failed, \r\ninput: %q, \r\nlocal: %q", signature1, signature2) return } return }
func ServeHTTP(w http.ResponseWriter, r *http.Request, urlValues url.Values, messageServer MessageServer, invalidRequestHandler InvalidRequestHandler) { switch r.Method { case "POST": RawMsgXML, err := ioutil.ReadAll(r.Body) if err != nil { invalidRequestHandler.ServeInvalidRequest(w, r, err) return } msg, err := util.ParseXMLToMap(bytes.NewReader(RawMsgXML)) if err != nil { invalidRequestHandler.ServeInvalidRequest(w, r, err) return } ReturnCode, ok := msg["return_code"] if !ok || ReturnCode == ReturnCodeSuccess { haveAppId := msg["appid"] wantAppId := messageServer.AppId() if len(haveAppId) != len(wantAppId) { err = fmt.Errorf("the message's appid mismatch, have: %s, want: %s", haveAppId, wantAppId) invalidRequestHandler.ServeInvalidRequest(w, r, err) return } if subtle.ConstantTimeCompare([]byte(haveAppId), []byte(wantAppId)) != 1 { err = fmt.Errorf("the message's appid mismatch, have: %s, want: %s", haveAppId, wantAppId) invalidRequestHandler.ServeInvalidRequest(w, r, err) return } haveMchId := msg["mch_id"] wantMchId := messageServer.MchId() if len(haveMchId) != len(wantMchId) { err = fmt.Errorf("the message's mch_id mismatch, have: %s, want: %s", haveMchId, wantMchId) invalidRequestHandler.ServeInvalidRequest(w, r, err) return } if subtle.ConstantTimeCompare([]byte(haveMchId), []byte(wantMchId)) != 1 { err = fmt.Errorf("the message's mch_id mismatch, have: %s, want: %s", haveMchId, wantMchId) invalidRequestHandler.ServeInvalidRequest(w, r, err) return } // 认证签名 signature1, ok := msg["sign"] if !ok { err = errors.New("no sign parameter") invalidRequestHandler.ServeInvalidRequest(w, r, err) return } signature2 := Sign(msg, messageServer.APIKey(), nil) if len(signature1) != len(signature2) { err = fmt.Errorf("check signature failed, \r\ninput: %q, \r\nlocal: %q", signature1, signature2) invalidRequestHandler.ServeInvalidRequest(w, r, err) return } if subtle.ConstantTimeCompare([]byte(signature1), []byte(signature2)) != 1 { err = fmt.Errorf("check signature failed, \r\ninput: %q, \r\nlocal: %q", signature1, signature2) invalidRequestHandler.ServeInvalidRequest(w, r, err) return } } req := &Request{ HttpRequest: r, RawMsgXML: RawMsgXML, Msg: msg, } messageServer.MessageHandler().ServeMessage(w, req) default: invalidRequestHandler.ServeInvalidRequest(w, r, errors.New("Request.Method: "+r.Method)) } }
// 微信支付通用请求方法. // 注意: err == nil 表示协议状态都为 SUCCESS. func (clt *Client) PostXML(url string, req map[string]string) (resp map[string]string, err error) { bodyBuf := textBufferPool.Get().(*bytes.Buffer) bodyBuf.Reset() defer textBufferPool.Put(bodyBuf) if err = util.FormatMapToXML(bodyBuf, req); err != nil { return } debugPrefix := "pay.Client.PostXML" if _, file, line, ok := runtime.Caller(1); ok { debugPrefix += fmt.Sprintf("(called at %s:%d)", file, line) } log.Println(debugPrefix, "request url:", url) log.Println(debugPrefix, "request xml:", bodyBuf.String()) httpResp, err := clt.httpClient.Post(url, "text/xml; charset=utf-8", bodyBuf) if err != nil { return } defer httpResp.Body.Close() if httpResp.StatusCode != http.StatusOK { err = fmt.Errorf("http.Status: %s", httpResp.Status) return } respBody, err := ioutil.ReadAll(httpResp.Body) if err != nil { return } log.Println(debugPrefix, "response xml:", string(respBody)) if resp, err = util.ParseXMLToMap(bytes.NewReader(respBody)); err != nil { return } // 判断协议状态 ReturnCode, ok := resp["return_code"] if !ok { err = errors.New("no return_code parameter") return } if ReturnCode != ReturnCodeSuccess { err = &Error{ ReturnCode: ReturnCode, ReturnMsg: resp["return_msg"], } return } // 认证签名 signature1, ok := resp["sign"] if !ok { err = errors.New("no sign parameter") return } signature2 := Sign(resp, clt.apiKey, nil) if signature1 != signature2 { err = fmt.Errorf("check signature failed, \r\ninput: %q, \r\nlocal: %q", signature1, signature2) return } return }