471 lines
13 KiB
Go
471 lines
13 KiB
Go
package dao
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
xtime "time"
|
|
|
|
"go-common/app/job/main/vip/model"
|
|
"go-common/library/ecode"
|
|
"go-common/library/log"
|
|
"go-common/library/time"
|
|
"go-common/library/xstr"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
_cleanCache = "/notify/cleanCache"
|
|
_payOrder = "/payplatform/pay/pay"
|
|
_message = "/api/notify/send.user.notify.do"
|
|
_addBcoin = "/api/coupon/regular/add"
|
|
_sendVipbuyTicket = "/mall-marketing/coupon_code/create"
|
|
_sendMedal = "/api/nameplate/get/v2"
|
|
_pushData = "/x/internal/push-strategy/task/add"
|
|
|
|
_retry = 3
|
|
_minRead = 1024 * 64
|
|
|
|
_alreadySend = -804
|
|
|
|
_alreadyGet = -663
|
|
|
|
_alreadySendVipbuy = 83110005
|
|
_ok = 1
|
|
|
|
//push
|
|
appID = 1
|
|
)
|
|
|
|
//PushData http push data
|
|
func (d *Dao) PushData(c context.Context, mids []int64, pushData *model.VipPushData, curtime string) (rel *model.VipPushResq, err error) {
|
|
var (
|
|
pushTime xtime.Time
|
|
expireTime xtime.Time
|
|
params = url.Values{}
|
|
)
|
|
rel = new(model.VipPushResq)
|
|
|
|
if pushTime, err = xtime.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%v %v", curtime, pushData.PushStartTime), xtime.Local); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
|
|
if expireTime, err = xtime.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%v %v", curtime, pushData.PushEndTime), xtime.Local); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
|
|
page := len(mids) / d.c.Property.SplitPush
|
|
if len(mids)%d.c.Property.SplitPush != 0 {
|
|
page++
|
|
}
|
|
for i := 0; i < page; i++ {
|
|
startID := i * d.c.Property.SplitPush
|
|
endID := (i + 1) * d.c.Property.SplitPush
|
|
if endID > len(mids) {
|
|
endID = len(mids)
|
|
}
|
|
tempMids := mids[startID:endID]
|
|
params.Set("app_id", fmt.Sprintf("%v", appID))
|
|
params.Set("business_id", fmt.Sprintf("%v", d.c.Property.BusinessID))
|
|
params.Set("alert_title", pushData.Title)
|
|
params.Set("alert_body", pushData.Content)
|
|
params.Set("mids", xstr.JoinInts(tempMids))
|
|
params.Set("link_type", fmt.Sprintf("%v", pushData.LinkType))
|
|
params.Set("link_value", pushData.LinkURL)
|
|
params.Set("builds", pushData.Platform)
|
|
params.Set("group", pushData.GroupName)
|
|
params.Set("uuid", uuid.New().String())
|
|
params.Set("push_time", fmt.Sprintf("%v", pushTime.Unix()))
|
|
params.Set("expire_time", fmt.Sprintf("%v", expireTime.Unix()))
|
|
|
|
header := make(map[string]string)
|
|
header["Authorization"] = fmt.Sprintf("token=%v", d.c.Property.PushToken)
|
|
header["Content-Type"] = "application/x-www-form-urlencoded"
|
|
|
|
for i := 0; i < _retry; i++ {
|
|
if err = d.doNomalSend(c, d.c.URLConf.APICoURL, _pushData, "127.0.0.1", header, params, rel); err != nil {
|
|
log.Error("send error(%v) url(%v)", err, d.c.URLConf.APICoURL+_pushData)
|
|
return
|
|
}
|
|
|
|
if rel.Code == int64(ecode.OK.Code()) {
|
|
log.Info("send url:%v params:%+v return:%+v error(%+v)", d.c.URLConf.APICoURL+_pushData, params, rel, err)
|
|
break
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
//SendMedal send medal
|
|
func (d *Dao) SendMedal(c context.Context, mid, medalID int64) (status int64) {
|
|
var (
|
|
err error
|
|
)
|
|
params := url.Values{}
|
|
params.Set("mid", fmt.Sprintf("%v", mid))
|
|
params.Set("nid", fmt.Sprintf("%v", medalID))
|
|
rel := new(struct {
|
|
Code int64 `json:"code"`
|
|
Data string `json:"data"`
|
|
})
|
|
defer func() {
|
|
if err == nil {
|
|
log.Info("send url:%+v params:%+v return:%+v", d.c.URLConf.AccountURL+_sendMedal, params, rel)
|
|
}
|
|
}()
|
|
for i := 0; i < _retry; i++ {
|
|
if err = d.client.Get(c, d.c.URLConf.AccountURL+_sendMedal, "127.0.0.1", params, rel); err != nil {
|
|
log.Error("send error(%v) url(%v)", err, d.c.URLConf.AccountURL+_sendMedal)
|
|
continue
|
|
}
|
|
if rel.Code == int64(ecode.OK.Code()) || rel.Code == _alreadyGet {
|
|
status = 1
|
|
if rel.Code == _alreadyGet {
|
|
status = 2
|
|
}
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
//SendVipBuyTicket send vipbuy ticket
|
|
func (d *Dao) SendVipBuyTicket(c context.Context, mid int64, couponID string) (status int64) {
|
|
var (
|
|
err error
|
|
)
|
|
header := make(map[string]string)
|
|
header["Content-Type"] = "application/json"
|
|
|
|
params := make(map[string]string)
|
|
params["mid"] = fmt.Sprintf("%v", mid)
|
|
params["couponId"] = fmt.Sprintf("%v", couponID)
|
|
|
|
for i := 0; i < _retry; i++ {
|
|
repl := new(struct {
|
|
Code int64 `json:"code"`
|
|
Message string `json:"message"`
|
|
})
|
|
|
|
if err = d.doSend(c, d.c.URLConf.MallURL, _sendVipbuyTicket, "127.0.0.1", header, params, repl); err != nil {
|
|
log.Error("send vip buy ticket(%+v) error(%+v)", params, err)
|
|
continue
|
|
}
|
|
if repl.Code == int64(ecode.OK.Code()) || repl.Code == _alreadySendVipbuy {
|
|
status = 1
|
|
if repl.Code == _alreadySendVipbuy {
|
|
status = 2
|
|
}
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
//SendCleanCache clean cache
|
|
func (d *Dao) SendCleanCache(c context.Context, hv *model.HandlerVip) (err error) {
|
|
params := url.Values{}
|
|
params.Set("mid", strconv.FormatInt(int64(hv.Mid), 10))
|
|
if err = d.client.Get(c, d.c.VipURI+_cleanCache, "127.0.0.1", params, nil); err != nil {
|
|
log.Error("SendCleanCache error(%v) url(%v)", err, d.c.VipURI+_cleanCache)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
//SendBcoin send bcoin http
|
|
func (d *Dao) SendBcoin(c context.Context, mids []int64, money int32, dueTime time.Time, ip string) (err error) {
|
|
if len(mids) <= 0 {
|
|
return
|
|
}
|
|
var midStrs []string
|
|
for _, v := range mids {
|
|
midStrs = append(midStrs, fmt.Sprintf("%v", v))
|
|
}
|
|
params := url.Values{}
|
|
params.Add("activity_id", fmt.Sprintf("%v", d.c.Property.ActivityID))
|
|
params.Add("mids", strings.Join(midStrs, ","))
|
|
params.Add("money", fmt.Sprintf("%v", money*100))
|
|
params.Add("due_time", dueTime.Time().Format("2006-01-02"))
|
|
|
|
res := new(struct {
|
|
Code int64 `json:"code"`
|
|
Message string `json:"message"`
|
|
TS int64 `json:"ts"`
|
|
Data struct {
|
|
CouponMoney int64 `json:"coupon_money"`
|
|
Status int8 `json:"status"`
|
|
} `json:"data"`
|
|
})
|
|
if err = d.client.Post(c, d.c.URLConf.PayCoURL+_addBcoin, ip, params, res); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
if res.Code == int64(_alreadySend) {
|
|
return
|
|
}
|
|
if int(res.Code) != ecode.OK.Code() {
|
|
err = fmt.Errorf("发放B币失败 message: %s mid: %s resp(%+v)", res.Message, strings.Join(midStrs, ","), res)
|
|
return
|
|
}
|
|
if res.Data.Status != _ok {
|
|
err = fmt.Errorf("发放B币失败 message: %s mid: %s resp(%+v)", res.Message, strings.Join(midStrs, ","), res)
|
|
return
|
|
}
|
|
log.Info("发放B币成功 mids %v resp(%+v)", mids, res)
|
|
return
|
|
}
|
|
|
|
//SendAppCleanCache notice app clean cache
|
|
func (d *Dao) SendAppCleanCache(c context.Context, hv *model.HandlerVip, app *model.VipAppInfo) (err error) {
|
|
params := url.Values{}
|
|
params.Set("modifiedAttr", "updateVip")
|
|
params.Set("mid", fmt.Sprintf("%v", hv.Mid))
|
|
params.Set("status", fmt.Sprintf("%v", hv.Type))
|
|
params.Set("buyMonths", fmt.Sprintf("%v", hv.Months))
|
|
params.Set("days", fmt.Sprintf("%v", hv.Days))
|
|
if err = d.client.Get(c, app.PurgeURL, "127.0.0.1", params, nil); err != nil {
|
|
log.Error("SendAppCleanCache error(%v) url(%v) params(%v)", err, app.PurgeURL, params)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
//SendMultipMsg send multip msg
|
|
func (d *Dao) SendMultipMsg(c context.Context, mids, content, title, mc 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)
|
|
defer func() {
|
|
log.Info("SendMultipMsg(%v) params(%+v) error(%+v)", d.c.URLConf.MsgURL+_message, params, err)
|
|
}()
|
|
if err = d.client.Post(c, d.c.URLConf.MsgURL+_message, "127.0.0.1", params, nil); err != nil {
|
|
log.Error("SendMultipMsg params(%+v) error(%v)", err, params)
|
|
return
|
|
}
|
|
log.Info("cur send mid(%+v)", mids)
|
|
return
|
|
}
|
|
|
|
// PayOrder pay order.
|
|
func (d *Dao) PayOrder(c context.Context, paramsMap map[string]interface{}) (err error) {
|
|
params := make(map[string]string)
|
|
for k, v := range paramsMap {
|
|
params[k] = fmt.Sprintf("%v", v)
|
|
}
|
|
|
|
header := make(map[string]string)
|
|
header["Content-Type"] = "application/json"
|
|
success := false
|
|
for i := 0; i < 3; i++ {
|
|
repl := new(struct {
|
|
ErrNo int64 `json:"errno"`
|
|
Msg string `json:"msg"`
|
|
Data interface{} `json:"data"`
|
|
})
|
|
if err = d.doPaySend(c, d.c.URLConf.PayURL, _payOrder, "127.0.0.1", header, params, repl); err != nil {
|
|
continue
|
|
}
|
|
if repl.ErrNo == 0 {
|
|
success = true
|
|
break
|
|
}
|
|
}
|
|
if !success {
|
|
err = fmt.Errorf("下单失败")
|
|
}
|
|
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()
|
|
}
|
|
|
|
//PaySign pay sign
|
|
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("sign params:%v ", b.String())
|
|
mh := md5.Sum(b.Bytes())
|
|
// query
|
|
var qb bytes.Buffer
|
|
qb.WriteString(tmp)
|
|
qb.WriteString("&sign=")
|
|
qb.WriteString(hex.EncodeToString(mh[:]))
|
|
sign = hex.EncodeToString(mh[:])
|
|
log.Info("sign params(%v) and sign(%v)", b.String(), sign)
|
|
return
|
|
}
|
|
|
|
func (d *Dao) doNomalSend(c context.Context, basePath, path, ip string, header map[string]string, params url.Values, data interface{}) (err error) {
|
|
var (
|
|
req *http.Request
|
|
client = new(http.Client)
|
|
resp *http.Response
|
|
bs []byte
|
|
marshal string
|
|
)
|
|
url := basePath + path
|
|
|
|
if req, err = d.client.NewRequest(http.MethodPost, url, ip, params); err != nil {
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
|
|
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, string(marshal))
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
defer func() {
|
|
log.Info("call url:%v params:(%v) result:(%+v) header:(%+v)", url, string(marshal), data, header)
|
|
}()
|
|
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
|
|
}
|
|
return
|
|
}
|
|
|
|
func (d *Dao) doSend(c context.Context, basePath, path, IP string, 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
|
|
}
|
|
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, string(marshal))
|
|
err = errors.WithStack(err)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
defer func() {
|
|
log.Info("call url:%v params:(%v) result:(%+v) header:(%+v)", url, string(marshal), data, header)
|
|
}()
|
|
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
|
|
}
|
|
return
|
|
}
|
|
|
|
func (d *Dao) doPaySend(c context.Context, basePath, path, IP string, header map[string]string, params map[string]string, data interface{}) (err error) {
|
|
sign := d.PaySign(params, d.c.PayConf.Token)
|
|
params["sign"] = sign
|
|
return d.doSend(c, basePath, path, IP, header, params, data)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
// SalaryCoupon salary coupon.
|
|
func (d *Dao) SalaryCoupon(c context.Context, mid int64, couponType int8, count int64, token string) (err error) {
|
|
params := url.Values{}
|
|
params.Set("mid", fmt.Sprintf("%d", mid))
|
|
params.Set("type", fmt.Sprintf("%d", couponType))
|
|
params.Set("count", fmt.Sprintf("%d", count))
|
|
params.Set("batch_no", token)
|
|
var resp struct {
|
|
Code int64 `json:"code"`
|
|
}
|
|
if err = d.client.Post(c, d.c.Property.SalaryCouponURL, "", params, &resp); err != nil {
|
|
log.Error("message url(%s) error(%v)", d.c.Property.SalaryCouponURL+"?"+params.Encode(), err)
|
|
return
|
|
}
|
|
if resp.Code != 0 {
|
|
err = fmt.Errorf("POST SalaryCoupon url resp(%v)", resp)
|
|
return
|
|
}
|
|
return
|
|
}
|