service_api.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package qq
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "net/http"
  10. "reflect"
  11. "strings"
  12. "github.com/iGoogle-ink/gopay"
  13. )
  14. // 解析QQ支付异步通知的结果到BodyMap
  15. // req:*http.Request
  16. // 返回参数bm:Notify请求的参数
  17. // 返回参数err:错误信息
  18. func ParseNotifyResultToBodyMap(req *http.Request) (bm gopay.BodyMap, err error) {
  19. bs, err := ioutil.ReadAll(io.LimitReader(req.Body, int64(2<<20))) // default 2MB change the size you want;
  20. if err != nil {
  21. return nil, fmt.Errorf("ioutil.ReadAll:%w", err)
  22. }
  23. bm = make(gopay.BodyMap)
  24. if err = xml.Unmarshal(bs, &bm); err != nil {
  25. return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
  26. }
  27. return
  28. }
  29. // 解析QQ支付异步通知的参数
  30. // req:*http.Request
  31. // 返回参数notifyReq:Notify请求的参数
  32. // 返回参数err:错误信息
  33. func ParseNotifyResult(req *http.Request) (notifyReq *NotifyRequest, err error) {
  34. notifyReq = new(NotifyRequest)
  35. if err = xml.NewDecoder(req.Body).Decode(notifyReq); err != nil {
  36. return nil, fmt.Errorf("xml.NewDecoder.Decode:%w", err)
  37. }
  38. return
  39. }
  40. // QQ同步返回参数验签或异步通知参数验签
  41. // ApiKey:API秘钥值
  42. // signType:签名类型(调用API方法时填写的类型)
  43. // bean:微信同步返回的结构体 qqRsp 或 异步通知解析的结构体 notifyReq
  44. // 返回参数ok:是否验签通过
  45. // 返回参数err:错误信息
  46. func VerifySign(apiKey, signType string, bean interface{}) (ok bool, err error) {
  47. if apiKey == gopay.NULL || signType == gopay.NULL {
  48. return false, errors.New("apiKey or signType can not null")
  49. }
  50. if bean == nil {
  51. return false, errors.New("bean is nil")
  52. }
  53. kind := reflect.ValueOf(bean).Kind()
  54. if kind == reflect.Map {
  55. bm := bean.(gopay.BodyMap)
  56. bodySign := bm.Get("sign")
  57. bm.Remove("sign")
  58. return getReleaseSign(apiKey, signType, bm) == bodySign, nil
  59. }
  60. bs, err := json.Marshal(bean)
  61. if err != nil {
  62. return false, fmt.Errorf("json.Marshal(%s):%w", string(bs), err)
  63. }
  64. bm := make(gopay.BodyMap)
  65. if err = json.Unmarshal(bs, &bm); err != nil {
  66. return false, fmt.Errorf("json.Marshal(%s):%w", string(bs), err)
  67. }
  68. bodySign := bm.Get("sign")
  69. bm.Remove("sign")
  70. return getReleaseSign(apiKey, signType, bm) == bodySign, nil
  71. }
  72. type NotifyResponse struct {
  73. ReturnCode string `xml:"return_code"`
  74. ReturnMsg string `xml:"return_msg"`
  75. }
  76. // 返回数据给QQ
  77. func (w *NotifyResponse) ToXmlString() (xmlStr string) {
  78. var buffer strings.Builder
  79. buffer.WriteString("<xml><return_code>")
  80. buffer.WriteString(w.ReturnCode)
  81. buffer.WriteString("</return_code>")
  82. if w.ReturnMsg != gopay.NULL {
  83. buffer.WriteString("<return_msg>")
  84. buffer.WriteString(w.ReturnMsg)
  85. buffer.WriteString("</return_msg>")
  86. }
  87. buffer.WriteString("</xml>")
  88. xmlStr = buffer.String()
  89. return
  90. }