bilibili-backup/app/admin/main/vip/dao/send.go

177 lines
4.5 KiB
Go
Raw Normal View History

2019-04-22 10:59:20 +08:00
package dao
import (
"bytes"
"context"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"go-common/library/log"
"github.com/google/uuid"
"github.com/pkg/errors"
)
const (
_SendUserNotify = "/api/notify/send.user.notify.do"
_payRefund = "/payplatform/refund/request"
_minRead = 1024 * 64
)
// SendMultipMsg send multip msg
func (d *Dao) SendMultipMsg(c context.Context, mids, content, title, mc, ip string, dataType int) (err error) {
params := url.Values{}
params.Set("mc", mc)
params.Set("title", title)
params.Set("context", content)
params.Set("data_type", strconv.FormatInt(int64(dataType), 10))
params.Set("mid_list", mids)
if err = d.client.Post(c, d.c.Property.MsgURI+_SendUserNotify, "127.0.0.1", params, nil); err != nil {
log.Error("SendMultipMsg error(%v)", err)
return
}
return
}
//PayRefund .
func (d *Dao) PayRefund(c context.Context, arg *model.PayOrder, refundAmount float64, refundID string) (err error) {
params := make(map[string]string)
params["customerId"] = strconv.FormatInt(d.c.PayConf.CustomerID, 10)
params["notifyUrl"] = d.c.PayConf.RefundURL
params["version"] = d.c.PayConf.Version
params["signType"] = "MD5"
params["timestamp"] = strconv.FormatInt(time.Now().UnixNano()/1e6, 10)
params["traceId"] = uuid.New().String()
params["refundDesc"] = "大会员退款"
params["customerRefundId"] = refundID
params["txId"] = arg.ThirdTradeNo
params["totalAmount"] = strconv.Itoa(int(arg.Money * 100))
params["refundAmount"] = strconv.Itoa(int(refundAmount * 100))
sign := d.paySign(params, d.c.PayConf.Token)
params["sign"] = sign
resq := new(struct {
Code int `json:"errno"`
Msg string `json:"msg"`
})
if err = d.doPaySend(c, d.c.PayConf.BaseURL, _payRefund, "", nil, nil, params, resq); err != nil {
err = errors.WithStack(err)
return
}
if resq.Code != ecode.OK.Code() {
err = ecode.Int(resq.Code)
}
return
}
func (d *Dao) paySign(params map[string]string, token string) (sign string) {
tmp := d.sortParamsKey(params)
var b bytes.Buffer
b.WriteString(tmp)
b.WriteString(fmt.Sprintf("&token=%s", token))
log.Info("pay sign params:(%s) \n", b.String())
mh := md5.Sum(b.Bytes())
// query
sign = hex.EncodeToString(mh[:])
log.Info("pay sign (%v)", sign)
return
}
func (d *Dao) sortParamsKey(v map[string]string) string {
if v == nil {
return ""
}
var buf bytes.Buffer
keys := make([]string, 0, len(v))
for k := range v {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
vs := v[k]
prefix := k + "="
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(prefix)
buf.WriteString(vs)
}
return buf.String()
}
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) {
var (
req *http.Request
client = new(http.Client)
resp *http.Response
bs []byte
)
url := basePath + path
marshal, _ := json.Marshal(params)
if req, err = http.NewRequest(http.MethodPost, url, strings.NewReader(string(marshal))); err != nil {
err = errors.WithStack(err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("x-backend-bili-real-ip", IP)
for _, v := range cookie {
req.AddCookie(v)
}
for k, v := range header {
req.Header.Add(k, v)
}
if resp, err = client.Do(req); err != nil {
log.Error("call url:%v params:(%+v)", basePath+path, params)
err = errors.WithStack(err)
return
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest {
err = errors.Errorf("incorrect http status:%d host:%s, url:%s", resp.StatusCode, req.URL.Host, req.URL.String())
return
}
if bs, err = readAll(resp.Body, _minRead); err != nil {
err = errors.Wrapf(err, "host:%s, url:%s", req.URL.Host, req.URL.String())
return
}
if err = json.Unmarshal(bs, data); err != nil {
err = errors.WithStack(err)
return
}
log.Info("call url:%v params:%+v result:%+v", url, params, data)
return
}
func readAll(r io.Reader, capacity int64) (b []byte, err error) {
buf := bytes.NewBuffer(make([]byte, 0, capacity))
// If the buffer overflows, we will get bytes.ErrTooLarge.
// Return that as an error. Any other panic remains.
defer func() {
e := recover()
if e == nil {
return
}
if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
err = panicErr
} else {
panic(e)
}
}()
_, err = buf.ReadFrom(r)
return buf.Bytes(), err
}