base.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package base
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "github.com/yaotian/gowechat/server/context"
  9. )
  10. //MchBase base mch
  11. type MchBase struct {
  12. *context.Context
  13. }
  14. //PostXML postXML
  15. func (c *MchBase) PostXML(url string, req map[string]string, needSSL bool) (resp map[string]string, err error) {
  16. bodyBuf := textBufferPool.Get().(*bytes.Buffer)
  17. bodyBuf.Reset()
  18. defer textBufferPool.Put(bodyBuf)
  19. if err = FormatMapToXML(bodyBuf, req); err != nil {
  20. return
  21. }
  22. //需要ssl,就需要ssl client
  23. client := c.HTTPClient
  24. if needSSL {
  25. client = c.SHTTPClient
  26. }
  27. httpResp, err := client.Post(url, "text/xml; charset=utf-8", bodyBuf)
  28. if err != nil {
  29. return resp, err
  30. }
  31. defer httpResp.Body.Close()
  32. if httpResp.StatusCode != http.StatusOK {
  33. err = fmt.Errorf("http.Status: %s", httpResp.Status)
  34. return
  35. }
  36. respBody, err := ioutil.ReadAll(httpResp.Body)
  37. if err != nil {
  38. return resp, err
  39. }
  40. if resp, err = ParseXMLToMap(bytes.NewReader(respBody)); err != nil {
  41. return
  42. }
  43. // 判断协议状态
  44. ReturnCode, ok := resp["return_code"]
  45. if !ok {
  46. err = errors.New("no return_code parameter")
  47. return
  48. }
  49. if ReturnCode != ReturnCodeSuccess {
  50. err = &Error{
  51. ReturnCode: ReturnCode,
  52. ReturnMsg: resp["return_msg"],
  53. }
  54. return
  55. }
  56. // 安全考虑, 做下验证
  57. mchId, ok := resp["mch_id"]
  58. if ok && mchId != c.MchID {
  59. err = fmt.Errorf("mch_id mismatch, have: %q, want: %q", mchId, c.MchID)
  60. return
  61. }
  62. //发送红包的情况,不需要验证这些,因为有的信息没有
  63. if !needSSL {
  64. appId, ok := resp["appid"]
  65. if ok && appId != c.AppID {
  66. err = fmt.Errorf("appid mismatch, have: %q, want: %q", appId, c.AppID)
  67. return
  68. }
  69. // 认证签名
  70. signature1, ok := resp["sign"]
  71. if !ok {
  72. err = errors.New("no sign parameter")
  73. return
  74. }
  75. signature2 := Sign(resp, c.MchAPIKey, nil)
  76. if signature1 != signature2 {
  77. err = fmt.Errorf("check signature failed, \r\ninput: %q, \r\nlocal: %q", signature1, signature2)
  78. return
  79. }
  80. }
  81. return
  82. }