send.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package dao
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/md5"
  6. "encoding/hex"
  7. "encoding/json"
  8. "fmt"
  9. "io"
  10. "net/http"
  11. "net/url"
  12. "sort"
  13. "strconv"
  14. "strings"
  15. "time"
  16. "go-common/app/admin/main/vip/model"
  17. "go-common/library/ecode"
  18. "go-common/library/log"
  19. "github.com/google/uuid"
  20. "github.com/pkg/errors"
  21. )
  22. const (
  23. _SendUserNotify = "/api/notify/send.user.notify.do"
  24. _payRefund = "/payplatform/refund/request"
  25. _minRead = 1024 * 64
  26. )
  27. // SendMultipMsg send multip msg
  28. func (d *Dao) SendMultipMsg(c context.Context, mids, content, title, mc, ip string, dataType int) (err error) {
  29. params := url.Values{}
  30. params.Set("mc", mc)
  31. params.Set("title", title)
  32. params.Set("context", content)
  33. params.Set("data_type", strconv.FormatInt(int64(dataType), 10))
  34. params.Set("mid_list", mids)
  35. if err = d.client.Post(c, d.c.Property.MsgURI+_SendUserNotify, "127.0.0.1", params, nil); err != nil {
  36. log.Error("SendMultipMsg error(%v)", err)
  37. return
  38. }
  39. return
  40. }
  41. //PayRefund .
  42. func (d *Dao) PayRefund(c context.Context, arg *model.PayOrder, refundAmount float64, refundID string) (err error) {
  43. params := make(map[string]string)
  44. params["customerId"] = strconv.FormatInt(d.c.PayConf.CustomerID, 10)
  45. params["notifyUrl"] = d.c.PayConf.RefundURL
  46. params["version"] = d.c.PayConf.Version
  47. params["signType"] = "MD5"
  48. params["timestamp"] = strconv.FormatInt(time.Now().UnixNano()/1e6, 10)
  49. params["traceId"] = uuid.New().String()
  50. params["refundDesc"] = "大会员退款"
  51. params["customerRefundId"] = refundID
  52. params["txId"] = arg.ThirdTradeNo
  53. params["totalAmount"] = strconv.Itoa(int(arg.Money * 100))
  54. params["refundAmount"] = strconv.Itoa(int(refundAmount * 100))
  55. sign := d.paySign(params, d.c.PayConf.Token)
  56. params["sign"] = sign
  57. resq := new(struct {
  58. Code int `json:"errno"`
  59. Msg string `json:"msg"`
  60. })
  61. if err = d.doPaySend(c, d.c.PayConf.BaseURL, _payRefund, "", nil, nil, params, resq); err != nil {
  62. err = errors.WithStack(err)
  63. return
  64. }
  65. if resq.Code != ecode.OK.Code() {
  66. err = ecode.Int(resq.Code)
  67. }
  68. return
  69. }
  70. func (d *Dao) paySign(params map[string]string, token string) (sign string) {
  71. tmp := d.sortParamsKey(params)
  72. var b bytes.Buffer
  73. b.WriteString(tmp)
  74. b.WriteString(fmt.Sprintf("&token=%s", token))
  75. log.Info("pay sign params:(%s) \n", b.String())
  76. mh := md5.Sum(b.Bytes())
  77. // query
  78. sign = hex.EncodeToString(mh[:])
  79. log.Info("pay sign (%v)", sign)
  80. return
  81. }
  82. func (d *Dao) sortParamsKey(v map[string]string) string {
  83. if v == nil {
  84. return ""
  85. }
  86. var buf bytes.Buffer
  87. keys := make([]string, 0, len(v))
  88. for k := range v {
  89. keys = append(keys, k)
  90. }
  91. sort.Strings(keys)
  92. for _, k := range keys {
  93. vs := v[k]
  94. prefix := k + "="
  95. if buf.Len() > 0 {
  96. buf.WriteByte('&')
  97. }
  98. buf.WriteString(prefix)
  99. buf.WriteString(vs)
  100. }
  101. return buf.String()
  102. }
  103. func (d *Dao) doPaySend(c context.Context, basePath, path, IP string, cookie []*http.Cookie, header map[string]string, params map[string]string, data interface{}) (err error) {
  104. var (
  105. req *http.Request
  106. client = new(http.Client)
  107. resp *http.Response
  108. bs []byte
  109. )
  110. url := basePath + path
  111. marshal, _ := json.Marshal(params)
  112. if req, err = http.NewRequest(http.MethodPost, url, strings.NewReader(string(marshal))); err != nil {
  113. err = errors.WithStack(err)
  114. return
  115. }
  116. req.Header.Add("Content-Type", "application/json")
  117. req.Header.Add("x-backend-bili-real-ip", IP)
  118. for _, v := range cookie {
  119. req.AddCookie(v)
  120. }
  121. for k, v := range header {
  122. req.Header.Add(k, v)
  123. }
  124. if resp, err = client.Do(req); err != nil {
  125. log.Error("call url:%v params:(%+v)", basePath+path, params)
  126. err = errors.WithStack(err)
  127. return
  128. }
  129. defer resp.Body.Close()
  130. if resp.StatusCode >= http.StatusBadRequest {
  131. err = errors.Errorf("incorrect http status:%d host:%s, url:%s", resp.StatusCode, req.URL.Host, req.URL.String())
  132. return
  133. }
  134. if bs, err = readAll(resp.Body, _minRead); err != nil {
  135. err = errors.Wrapf(err, "host:%s, url:%s", req.URL.Host, req.URL.String())
  136. return
  137. }
  138. if err = json.Unmarshal(bs, data); err != nil {
  139. err = errors.WithStack(err)
  140. return
  141. }
  142. log.Info("call url:%v params:%+v result:%+v", url, params, data)
  143. return
  144. }
  145. func readAll(r io.Reader, capacity int64) (b []byte, err error) {
  146. buf := bytes.NewBuffer(make([]byte, 0, capacity))
  147. // If the buffer overflows, we will get bytes.ErrTooLarge.
  148. // Return that as an error. Any other panic remains.
  149. defer func() {
  150. e := recover()
  151. if e == nil {
  152. return
  153. }
  154. if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
  155. err = panicErr
  156. } else {
  157. panic(e)
  158. }
  159. }()
  160. _, err = buf.ReadFrom(r)
  161. return buf.Bytes(), err
  162. }