|
|
package getuiV2
|
|
|
|
|
|
import (
|
|
|
"crypto/sha256"
|
|
|
"fmt"
|
|
|
"github.com/astaxie/beego/httplib"
|
|
|
"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
|
|
|
"openapi/pkg/infrastructure/push"
|
|
|
"openapi/pkg/infrastructure/utils"
|
|
|
"strings"
|
|
|
"sync"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
host = "https://restapi.getui.com"
|
|
|
pushSingle = "push/single/cid"
|
|
|
saveListBody = "push/list/message"
|
|
|
pushList = "push/list/cid"
|
|
|
authSign = "auth"
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
authtoken = ""
|
|
|
expire time.Time
|
|
|
authMux sync.RWMutex
|
|
|
expireSpan = time.Second * 600 //token 10分钟过期
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
error_not_auth = "not_auth"
|
|
|
)
|
|
|
|
|
|
//GetuiNotification 个推消息推送
|
|
|
type GetuiNotification struct {
|
|
|
Options *push.Options
|
|
|
Request *httplib.BeegoHTTPRequest
|
|
|
retry int
|
|
|
}
|
|
|
|
|
|
func (notify *GetuiNotification) Init(options ...push.Option) error {
|
|
|
notify.Options = &push.Options{}
|
|
|
for _, o := range options {
|
|
|
o(notify.Options)
|
|
|
}
|
|
|
notify.retry = 3
|
|
|
return nil
|
|
|
}
|
|
|
func (notify *GetuiNotification) Send(option map[string]interface{}) (rsp map[string]interface{}, err error) {
|
|
|
retry := 1
|
|
|
for {
|
|
|
switch notify.Options.PushType {
|
|
|
case push.PushToSingle:
|
|
|
rsp, err = notify.pushToSingle(option)
|
|
|
case push.PushToList:
|
|
|
rsp, err = notify.pushToList(option)
|
|
|
default:
|
|
|
rsp, err = notify.pushToSingle(option)
|
|
|
}
|
|
|
if err == nil {
|
|
|
break
|
|
|
}
|
|
|
//重试
|
|
|
if err != nil && retry > notify.retry {
|
|
|
return
|
|
|
}
|
|
|
log.Error(fmt.Sprintf("【个推】 重试:%v 失败:%v", retry, err))
|
|
|
retry++
|
|
|
if retry > notify.retry {
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//pushToSingle 单推
|
|
|
func (notify *GetuiNotification) pushToSingle(option map[string]interface{}) (rsp map[string]interface{}, err error) {
|
|
|
var token string
|
|
|
rsp = make(map[string]interface{})
|
|
|
if token, err = notify.GetAuthToken(); err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var (
|
|
|
result *MessageBase
|
|
|
url = notify.Url(notify.Options.AppId, pushSingle)
|
|
|
m = notify.Message(pushSingle)
|
|
|
)
|
|
|
notify.Request = httplib.Post(url)
|
|
|
notify.Request.Header("token", token)
|
|
|
notify.Request.JSONBody(m)
|
|
|
if err = notify.Request.ToJSON(&result); err != nil {
|
|
|
return
|
|
|
}
|
|
|
rsp = result.Data
|
|
|
notify.print(url, m, result, result)
|
|
|
if err = handleResult(url, result); err != nil {
|
|
|
return
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//pushToList 群推
|
|
|
//步骤1.获取token
|
|
|
//步骤2.save_list_body保存消息共同体
|
|
|
//步骤3.push_list
|
|
|
func (notify *GetuiNotification) pushToList(option map[string]interface{}) (rsp map[string]interface{}, err error) {
|
|
|
var (
|
|
|
token string
|
|
|
taskId string
|
|
|
)
|
|
|
rsp = make(map[string]interface{})
|
|
|
if token, err = notify.GetAuthToken(); err != nil {
|
|
|
return
|
|
|
}
|
|
|
if taskId, err = notify.saveListBody(token, option); err != nil {
|
|
|
return
|
|
|
}
|
|
|
var (
|
|
|
result *MessageBase
|
|
|
url = notify.Url(notify.Options.AppId, pushList)
|
|
|
m = NewMapData()
|
|
|
)
|
|
|
m.AddFiled("audience.cid", notify.Options.ClientIds)
|
|
|
m.AddFiled("taskid", taskId)
|
|
|
m.AddFiled("is_async", true) //是否异步发送
|
|
|
notify.Request = httplib.Post(url)
|
|
|
notify.Request.Header("token", token)
|
|
|
notify.Request.JSONBody(m.Data)
|
|
|
if err = notify.Request.ToJSON(&result); err != nil {
|
|
|
return
|
|
|
}
|
|
|
rsp = result.Data
|
|
|
notify.print(url, m, result, result)
|
|
|
if err = handleResult(url, result); err != nil {
|
|
|
return
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//saveListBody 保存消息共同体
|
|
|
func (notify *GetuiNotification) saveListBody(token string, option map[string]interface{}) (taskId string, err error) {
|
|
|
var (
|
|
|
result *MessageBase
|
|
|
url = notify.Url(notify.Options.AppId, saveListBody)
|
|
|
m = notify.Message(saveListBody)
|
|
|
)
|
|
|
notify.Request = httplib.Post(url)
|
|
|
notify.Request.Header("token", token)
|
|
|
notify.Request.JSONBody(m)
|
|
|
delete(m, "audience")
|
|
|
if err = notify.Request.ToJSON(&result); err != nil {
|
|
|
return
|
|
|
}
|
|
|
notify.print(url, m, result, result)
|
|
|
if err = handleResult(url, result); err != nil {
|
|
|
return
|
|
|
}
|
|
|
if id, ok := result.Data["taskid"]; ok {
|
|
|
taskId = id.(string)
|
|
|
return
|
|
|
}
|
|
|
return "", fmt.Errorf("error task id")
|
|
|
}
|
|
|
|
|
|
//Message 组装消息体
|
|
|
func (notify *GetuiNotification) Message(method string) map[string]interface{} {
|
|
|
msg := NewPushMessage(notify.Options)
|
|
|
return msg
|
|
|
}
|
|
|
|
|
|
//Url 组装请求地址
|
|
|
func (notify *GetuiNotification) Url(param string, method string) string {
|
|
|
return fmt.Sprintf("%v/v2/%v/%v", host, param, method)
|
|
|
}
|
|
|
|
|
|
//GetAuthToken 获取token
|
|
|
func (notify *GetuiNotification) GetAuthToken() (token string, err error) {
|
|
|
if authtoken != "" && expire.Unix() > time.Now().Unix() {
|
|
|
token = authtoken
|
|
|
return
|
|
|
}
|
|
|
|
|
|
authMux.Lock()
|
|
|
defer authMux.Unlock()
|
|
|
url := notify.Url(notify.Options.AppId, authSign)
|
|
|
notify.Request = httplib.Post(strings.TrimSpace(url))
|
|
|
req := &AuthSignRequest{
|
|
|
Timestamp: fmt.Sprintf("%v", time.Now().Unix()*1000), //"1589797286000",//
|
|
|
AppKey: notify.Options.AppKey,
|
|
|
}
|
|
|
req.Sign = sign(req.AppKey, req.Timestamp, notify.Options.AppMasterSecret)
|
|
|
if _, err = notify.Request.JSONBody(req); err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var rsp *AuthSignResponse
|
|
|
err = notify.Request.ToJSON(&rsp)
|
|
|
notify.print(url, req, rsp, rsp.MessageBase)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
if err = handleResult(url, rsp.MessageBase); err != nil {
|
|
|
return
|
|
|
}
|
|
|
authtoken = rsp.Data["token"].(string)
|
|
|
token = rsp.Data["token"].(string)
|
|
|
expire = time.Now().Add(rsp.GetExpireTime(expireSpan))
|
|
|
log.Info(fmt.Sprintf("【个推】token:%v expire:%v", token, expire))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//打印日志 debug_module=true print debug log
|
|
|
func (notify *GetuiNotification) print(url string, v interface{}, rsp interface{}, result *MessageBase) {
|
|
|
if !notify.Options.DebugModule {
|
|
|
return
|
|
|
}
|
|
|
log.Error(fmt.Sprintf("【个推】 url:%v \n request:%v \n response:%v 结果:%v", url, utils.JsonAssertString(v), utils.JsonAssertString(rsp), result.Msg))
|
|
|
}
|
|
|
|
|
|
//处理结果
|
|
|
func handleResult(url string, result *MessageBase) (err error) {
|
|
|
if result.Code == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
switch result.Code {
|
|
|
case 0:
|
|
|
break
|
|
|
default:
|
|
|
setToken("")
|
|
|
break
|
|
|
}
|
|
|
err = fmt.Errorf("error:%v %v", result.Code, result.Msg)
|
|
|
return err
|
|
|
}
|
|
|
func sign(appKey, timestamp, masterSecret string) string {
|
|
|
sha := sha256.New()
|
|
|
sha.Write([]byte(appKey + timestamp + masterSecret))
|
|
|
return fmt.Sprintf("%x", sha.Sum(nil))
|
|
|
}
|
|
|
|
|
|
func setToken(token string) {
|
|
|
//authMux.Lock()
|
|
|
//defer authMux.Unlock()
|
|
|
authtoken = token
|
|
|
} |
...
|
...
|
|