pay.go 2.5 KB

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