Ejemplo n.º 1
0
// 微信支付通用请求方法.
//  注意: 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
}
Ejemplo n.º 2
0
// 下载对账单到 io.Writer.
func downloadBillToWriter(writer io.Writer, req map[string]string, httpClient *http.Client) (written int64, err error) {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	buf := make([]byte, 32*1024) // 与 io.copyBuffer 里的默认大小一致

	reqBuf := bytes.NewBuffer(buf[:0])
	if err = util.FormatMapToXML(reqBuf, req); err != nil {
		return
	}

	httpResp, err := httpClient.Post("https://api.mch.weixin.qq.com/pay/downloadbill", "text/xml; charset=utf-8", reqBuf)
	if err != nil {
		return
	}
	defer httpResp.Body.Close()

	if httpResp.StatusCode != http.StatusOK {
		err = fmt.Errorf("http.Status: %s", httpResp.Status)
		return
	}

	n, err := io.ReadFull(httpResp.Body, buf)
	switch {
	case err == nil:
		// n == len(buf), 可以认为返回的是对账单而不是xml格式的错误信息
		written, err = bytes.NewReader(buf).WriteTo(writer)
		if err != nil {
			return
		}
		var n2 int64
		n2, err = CopyBuffer(writer, httpResp.Body, buf)
		written += n2
		return
	case err == io.ErrUnexpectedEOF:
		readBytes := buf[:n]
		if index := bytes.Index(readBytes, downloadBillErrorRootNodeStartElement); index != -1 {
			if bytes.Contains(readBytes[index+len(downloadBillErrorRootNodeStartElement):], downloadBillErrorReturnCodeNodeStartElement) {
				// 可以认为是错误信息了, 尝试解析xml
				var result mch.Error
				if err = xml.Unmarshal(readBytes, &result); err == nil {
					err = &result
					return
				}
				// err != nil 执行默认的动作, 写入 writer
			}
		}
		return bytes.NewReader(readBytes).WriteTo(writer)
	case err == io.EOF: // 返回空的body
		err = nil
		return
	default: // 其他的错误
		return
	}
}
Ejemplo n.º 3
0
// 微信支付通用请求方法.
//  注意: 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
}
Ejemplo n.º 4
0
// 下载对账单.
func DownloadBill(req map[string]string, httpClient *http.Client) (data []byte, err error) {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	bodyBuf := bytes.NewBuffer(make([]byte, 0, 1024))
	if err = util.FormatMapToXML(bodyBuf, req); err != nil {
		return
	}

	httpResp, err := httpClient.Post("https://api.mch.weixin.qq.com/pay/downloadbill", "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
	}

	var result mch.Error
	if err = xml.Unmarshal(respBody, &result); err == nil {
		err = &result
		return
	}

	data = respBody
	err = nil
	return
}
Ejemplo n.º 5
0
// 下载对账单.
func (clt *Client) DownloadBill(req map[string]string) (data []byte, err error) {
	bodyBuf := textBufferPool.Get().(*bytes.Buffer)
	bodyBuf.Reset()
	defer textBufferPool.Put(bodyBuf)

	if err = util.FormatMapToXML(bodyBuf, req); err != nil {
		return
	}

	url := "https://api.mch.weixin.qq.com/pay/downloadbill"
	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
	}

	var result Error
	if err = xml.Unmarshal(respBody, &result); err == nil {
		err = &result
		return
	}

	data = respBody
	err = nil
	return
}
Ejemplo n.º 6
0
// 微信支付通用请求方法.
//  注意: 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
}