Ejemplo n.º 1
0
func EncodeXMLResponseMessage(w io.Writer, msg map[string]string) (err error) {
	var buf bytes.Buffer
	if err = util.EncodeXMLFromMap(&buf, msg, "xml"); err != nil {
		return
	}
	log.Printf("[WECHAT_DEBUG] [MCH] [CALLBACK] http response body:\n%s\n", buf.Bytes())

	_, err = buf.WriteTo(w)
	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.EncodeXMLFromMap(reqBuf, req, "xml"); 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 = io.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 core.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(return_code == SUCCESS).
func (pxy *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.EncodeXMLFromMap(bodyBuf, req, "xml"); err != nil {
		return
	}

	httpResp, err := pxy.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.DecodeXMLToMap(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
	}

	// 安全考虑, 做下验证
	appId, ok := resp["appid"]
	if ok && appId != pxy.appId {
		err = fmt.Errorf("appid mismatch, have: %q, want: %q", appId, pxy.appId)
		return
	}
	mchId, ok := resp["mch_id"]
	if ok && mchId != pxy.mchId {
		err = fmt.Errorf("mch_id mismatch, have: %q, want: %q", mchId, pxy.mchId)
		return
	}

	// 认证签名
	signature1, ok := resp["sign"]
	if !ok {
		err = errors.New("no sign parameter")
		return
	}
	signature2 := Sign(resp, pxy.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
// PostXML 是微信支付通用请求方法.
//  err == nil 表示协议状态为 SUCCESS(return_code==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.EncodeXMLFromMap(bodyBuf, req, "xml"); err != nil {
		return
	}
	api.DebugPrintPostXMLRequest(url, bodyBuf.Bytes())

	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 = api.DecodeXMLHttpResponse(httpResp.Body); err != nil {
		return
	}

	// 判断协议状态
	returnCode, ok := resp["return_code"]
	if !ok {
		err = ErrNotFoundReturnCode
		return
	}
	if returnCode != ReturnCodeSuccess {
		err = &Error{
			ReturnCode: returnCode,
			ReturnMsg:  resp["return_msg"],
		}
		return
	}

	// 安全考虑, 做下验证 appid 和 mch_id
	appId, ok := resp["appid"]
	if ok && appId != clt.appId {
		err = fmt.Errorf("appid mismatch, have: %s, want: %s", appId, clt.appId)
		return
	}
	mchId, ok := resp["mch_id"]
	if ok && mchId != clt.mchId {
		err = fmt.Errorf("mch_id mismatch, have: %s, want: %s", mchId, clt.mchId)
		return
	}

	// 验证签名
	signature1, ok := resp["sign"]
	if !ok {
		err = ErrNotFoundSign
		return
	}
	signature2 := Sign(resp, clt.apiKey, nil)
	if signature1 != signature2 {
		err = fmt.Errorf("sign mismatch,\nhave: %s,\nwant: %s", signature1, signature2)
		return
	}
	return
}
Ejemplo n.º 5
0
func EncodeXMLResponseMessage(w io.Writer, msg map[string]string) (err error) {
	return util.EncodeXMLFromMap(w, msg, "xml")
}
Ejemplo n.º 6
0
// Response 回复消息给微信服务器
func (ctx *Context) Response(msg map[string]string) (err error) {
	return util.EncodeXMLFromMap(ctx.ResponseWriter, msg, "xml")
}