123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- 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
- }
|