This commit is contained in:
邹宗楠
2023-03-20 17:27:47 +08:00
parent e6d34242cd
commit edd680602b
4 changed files with 265 additions and 263 deletions

View File

@@ -20,14 +20,13 @@ type SendMsgRes struct {
} }
func (a *API) SendMsgByUinApp(parma map[string]interface{}) error { func (a *API) SendMsgByUinApp(parma map[string]interface{}) error {
if err := a.CheckTokenIsExpire(); err != nil { if _, err := a.CheckTokenIsExpire(); err != nil {
return err return err
} }
data, _ := json.Marshal(parma) data, _ := json.Marshal(parma)
fmt.Println(string(data)) fmt.Println(string(data))
result, err := a.AccessAPI(BaseUrl+a.appId, PushMsgByCid, http.MethodPost, parma) result, err := a.AccessAPI(BaseUrl+a.appId, PushMsgByCid, http.MethodPost, parma)
fmt.Println(err.Error())
if err != nil && !strings.Contains(err.Error(), "success") { if err != nil && !strings.Contains(err.Error(), "success") {
return err return err
} }

View File

@@ -122,10 +122,11 @@ func (a *API) GetUinAppToken() error {
// CheckTokenIsExpire 校验头肯是否过期 // CheckTokenIsExpire 校验头肯是否过期
// 注鉴权接口每分钟最大调用量为100次每天最大调用量为10万次建议开发者妥善管理token以免达到限制影响推送.感觉不做缓存也够用了! // 注鉴权接口每分钟最大调用量为100次每天最大调用量为10万次建议开发者妥善管理token以免达到限制影响推送.感觉不做缓存也够用了!
func (a *API) CheckTokenIsExpire() error { func (a *API) CheckTokenIsExpire() (string, error) {
// 没有token或者token过期了 // 没有token或者token过期了
if a.token == "" || a.expireTime == "" || utils.Str2Int64(a.expireTime) < (time.Now().UnixNano()/1e6) { if a.token == "" || a.expireTime == "" || utils.Str2Int64(a.expireTime) < (time.Now().UnixNano()/1e6) {
return a.GetUinAppToken() a.GetUinAppToken()
return a.token, nil
} }
return nil return a.token, nil
} }

View File

@@ -1,219 +1,220 @@
package unipushapi package unipushapi
import ( //
"crypto/sha256" //import (
"encoding/hex" // "crypto/sha256"
"encoding/json" // "encoding/hex"
"fmt" // "encoding/json"
"net/http" // "fmt"
"strings" // "net/http"
"sync" // "strings"
"time" // "sync"
// "time"
"git.rosy.net.cn/baseapi/platformapi" //
"git.rosy.net.cn/baseapi/utils" // "git.rosy.net.cn/baseapi/platformapi"
) // "git.rosy.net.cn/baseapi/utils"
//)
const ( //
prodURL = "https://restapi.getui.com/v2" //const (
// prodURL = "https://restapi.getui.com/v2"
authAction = "auth" //
SuccessOffLine = "successed_offline" // authAction = "auth"
SuccessONLine = "successed_online" // SuccessOffLine = "successed_offline"
) // SuccessONLine = "successed_online"
//)
type TokenInfo struct { //
ExpireTime string `json:"expire_time"` //type TokenInfo struct {
Token string `json:"token"` // ExpireTime string `json:"expire_time"`
} // Token string `json:"token"`
//}
type API struct { //
token string //type API struct {
appID string // token string
appKey string // appID string
appSecret string // appKey string
masterSecret string // appSecret string
// masterSecret string
client *http.Client //
config *platformapi.APIConfig // client *http.Client
locker sync.RWMutex // config *platformapi.APIConfig
} // locker sync.RWMutex
//}
func New(appID, appKey, appSecret, masterSecret string, config ...*platformapi.APIConfig) *API { //
curConfig := platformapi.DefAPIConfig //func New(appID, appKey, appSecret, masterSecret string, config ...*platformapi.APIConfig) *API {
if len(config) > 0 { // curConfig := platformapi.DefAPIConfig
curConfig = *config[0] // if len(config) > 0 {
} // curConfig = *config[0]
return &API{ // }
appID: appID, // return &API{
appKey: appKey, // appID: appID,
appSecret: appSecret, // appKey: appKey,
masterSecret: masterSecret, // appSecret: appSecret,
// masterSecret: masterSecret,
client: &http.Client{Timeout: curConfig.ClientTimeout}, //
config: &curConfig, // client: &http.Client{Timeout: curConfig.ClientTimeout},
} // config: &curConfig,
} // }
//}
func (a *API) signParam(appKey string, time int64, masterSecret string) (sig string) { //
//方法一: //func (a *API) signParam(appKey string, time int64, masterSecret string) (sig string) {
//创建一个基于SHA256算法的hash.Hash接口的对象 // //方法一:
hash := sha256.New() // //创建一个基于SHA256算法的hash.Hash接口的对象
//输入数据 // hash := sha256.New()
hash.Write([]byte(appKey + utils.Int64ToStr(time) + masterSecret)) // //输入数据
//计算哈希值 // hash.Write([]byte(appKey + utils.Int64ToStr(time) + masterSecret))
bytes := hash.Sum(nil) // //计算哈希值
//将字符串编码为16进制格式,返回字符串 // bytes := hash.Sum(nil)
hashCode := hex.EncodeToString(bytes) // //将字符串编码为16进制格式,返回字符串
//返回哈希值 // hashCode := hex.EncodeToString(bytes)
return hashCode // //返回哈希值
} // return hashCode
//}
func (a *API) AccessAPI(action string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) { //
params := make(map[string]interface{}) //func (a *API) AccessAPI(action string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
time := time.Now().UnixNano() / 1e6 // params := make(map[string]interface{})
params["timestamp"] = utils.Int64ToStr(time) // time := time.Now().UnixNano() / 1e6
params["appkey"] = a.appKey // params["timestamp"] = utils.Int64ToStr(time)
params["sign"] = a.signParam(a.appKey, time, a.masterSecret) // params["appkey"] = a.appKey
result, _ := json.MarshalIndent(params, "", " ") // params["sign"] = a.signParam(a.appKey, time, a.masterSecret)
fullURL := utils.GenerateGetURL(prodURL+"/"+a.appID, action, nil) // result, _ := json.MarshalIndent(params, "", " ")
err = platformapi.AccessPlatformAPIWithRetry(a.client, // fullURL := utils.GenerateGetURL(prodURL+"/"+a.appID, action, nil)
func() *http.Request { // err = platformapi.AccessPlatformAPIWithRetry(a.client,
request, _ := http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(result))) // func() *http.Request {
if action != authAction { // request, _ := http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(result)))
request.Header.Set("token", a.CBGetToken()) // if action != authAction {
} // request.Header.Set("token", a.CBGetToken())
request.Header.Set("Content-Type", "application/json;charset=utf-8") // }
return request // request.Header.Set("Content-Type", "application/json;charset=utf-8")
}, // return request
a.config, // },
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { // a.config,
if jsonResult1 == nil { // func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") // if jsonResult1 == nil {
} // return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
if err == nil { // }
if jsonResult1["msg"].(string) != "success" { // if err == nil {
errLevel = platformapi.ErrLevelGeneralFail // if jsonResult1["msg"].(string) != "success" {
err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"]))) // errLevel = platformapi.ErrLevelGeneralFail
} // err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"])))
retVal = jsonResult1["data"].(map[string]interface{}) // }
} // retVal = jsonResult1["data"].(map[string]interface{})
return errLevel, err // }
}) // return errLevel, err
return retVal, err // })
} // return retVal, err
//}
func (a *API) AccessAPI2(action string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) { //
result, _ := json.MarshalIndent(bizParams, "", " ") //func (a *API) AccessAPI2(action string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
fullURL := utils.GenerateGetURL(prodURL+"/"+a.appID, action, nil) // result, _ := json.MarshalIndent(bizParams, "", " ")
err = platformapi.AccessPlatformAPIWithRetry(a.client, // fullURL := utils.GenerateGetURL(prodURL+"/"+a.appID, action, nil)
func() *http.Request { // err = platformapi.AccessPlatformAPIWithRetry(a.client,
request, _ := http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(result))) // func() *http.Request {
request.Header.Set("token", a.CBGetToken()) // request, _ := http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(result)))
request.Header.Set("Content-Type", "application/json;charset=utf-8") // request.Header.Set("token", a.CBGetToken())
return request // request.Header.Set("Content-Type", "application/json;charset=utf-8")
}, // return request
a.config, // },
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { // a.config,
if jsonResult1 == nil { // func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") // if jsonResult1 == nil {
} // return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
if err == nil { // }
if jsonResult1["msg"].(string) != "success" { // if err == nil {
errLevel = platformapi.ErrLevelGeneralFail // if jsonResult1["msg"].(string) != "success" {
err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"]))) // errLevel = platformapi.ErrLevelGeneralFail
} // err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"])))
retVal = jsonResult1 // }
} // retVal = jsonResult1
return errLevel, err // }
}) // return errLevel, err
return retVal, err // })
} // return retVal, err
//}
func (a *API) CBSetToken(newToken string) bool { //
curToken := a.CBGetToken() //func (a *API) CBSetToken(newToken string) bool {
if curToken != newToken { // curToken := a.CBGetToken()
a.locker.Lock() // if curToken != newToken {
defer a.locker.Unlock() // a.locker.Lock()
a.token = newToken // defer a.locker.Unlock()
return true // a.token = newToken
} // return true
return false // }
} // return false
//}
func (a *API) CBGetToken() string { //
a.locker.RLock() //func (a *API) CBGetToken() string {
defer a.locker.RUnlock() // a.locker.RLock()
return a.token // defer a.locker.RUnlock()
} // return a.token
//}
func (a *API) CBRetrieveToken() (tokenInfo *TokenInfo, err error) { //
result, err := a.AccessAPI("auth", nil) //func (a *API) CBRetrieveToken() (tokenInfo *TokenInfo, err error) {
if err != nil { // result, err := a.AccessAPI("auth", nil)
return nil, err // if err != nil {
} // return nil, err
tokenInfo = &TokenInfo{ // }
Token: utils.Interface2String(result["token"]), // tokenInfo = &TokenInfo{
ExpireTime: utils.Interface2String(result["expire_time"]), // Token: utils.Interface2String(result["token"]),
} // ExpireTime: utils.Interface2String(result["expire_time"]),
a.CBSetToken(tokenInfo.Token) // }
return tokenInfo, nil // a.CBSetToken(tokenInfo.Token)
} // return tokenInfo, nil
//}
type PushMsg struct { //
Notificatio Notification `json:"notification"` //type PushMsg struct {
} // Notificatio Notification `json:"notification"`
//}
type Notification struct { //
Title string `json:"title"` //type Notification struct {
Body string `json:"body"` // Title string `json:"title"`
ClickType string `json:"click_type"` // Body string `json:"body"`
URL string `json:"url"` // ClickType string `json:"click_type"`
} // URL string `json:"url"`
//}
type Audience struct { //
CID []string `json:"cid"` //type Audience struct {
} // CID []string `json:"cid"`
//}
type Settings struct { //
TTL int `json:"ttl"` //type Settings struct {
} // TTL int `json:"ttl"`
//}
type Transmission struct { //
Transmission string `json:"transmission"` //type Transmission struct {
} // Transmission string `json:"transmission"`
//}
func (a *API) PushToSingle(cid string, transmission bool, notification *Notification) (status string, err error) { //
params := map[string]interface{}{ //func (a *API) PushToSingle(cid string, transmission bool, notification *Notification) (status string, err error) {
"request_id": utils.GetUUID(), // params := map[string]interface{}{
"audience": &Audience{ // "request_id": utils.GetUUID(),
[]string{cid}, // "audience": &Audience{
}, // []string{cid},
} // },
if !transmission { // }
params["push_message"] = &PushMsg{ // if !transmission {
Notificatio: Notification{ // params["push_message"] = &PushMsg{
Title: notification.Title, // Notificatio: Notification{
Body: notification.Body, // Title: notification.Title,
ClickType: "startapp", //打开应用首页 // Body: notification.Body,
}, // ClickType: "startapp", //打开应用首页
} // },
} else { // }
params["push_message"] = &Transmission{ // } else {
Transmission: notification.Body, // params["push_message"] = &Transmission{
} // Transmission: notification.Body,
} // }
result2, err := a.AccessAPI2("push/single/cid", params) // }
if err != nil { // result2, err := a.AccessAPI2("push/single/cid", params)
return "", err // if err != nil {
} else { // return "", err
for _, v := range result2["data"].(map[string]interface{}) { // } else {
for _, vv := range v.(map[string]interface{}) { // for _, v := range result2["data"].(map[string]interface{}) {
if vv.(string) != "" { // for _, vv := range v.(map[string]interface{}) {
status = vv.(string) // if vv.(string) != "" {
} // status = vv.(string)
} // }
} // }
} // }
return status, nil // }
} // return status, nil
//}

View File

@@ -1,43 +1,44 @@
package unipushapi package unipushapi
import ( //
"testing" //import (
// "testing"
"git.rosy.net.cn/baseapi" //
"git.rosy.net.cn/baseapi/utils" // "git.rosy.net.cn/baseapi"
"go.uber.org/zap" // "git.rosy.net.cn/baseapi/utils"
) // "go.uber.org/zap"
//)
var ( //
api *API //var (
sugarLogger *zap.SugaredLogger // api *API
) // sugarLogger *zap.SugaredLogger
//)
func init() { //
logger, _ := zap.NewDevelopment() //func init() {
sugarLogger = logger.Sugar() // logger, _ := zap.NewDevelopment()
baseapi.Init(sugarLogger) // sugarLogger = logger.Sugar()
api = New("5lyyrvHODG6wC8Sdr3a9h", "iFrkUDmR2g5eqQpfh2kQ57", "WTn53qd6WAAdLMXfmXvzb7", "dGZcR0XGGg7H5Pd7FR3n47") // baseapi.Init(sugarLogger)
api.CBSetToken("cf74937695849a89bcb414e49f03702416b49024a49e7f62570280f99eb63b58") // api = New("5lyyrvHODG6wC8Sdr3a9h", "iFrkUDmR2g5eqQpfh2kQ57", "WTn53qd6WAAdLMXfmXvzb7", "dGZcR0XGGg7H5Pd7FR3n47")
// ef364b677911fa64d41a25d22d5e155065c4898046be65ddd627fa6c8cd87c2e // api.CBSetToken("cf74937695849a89bcb414e49f03702416b49024a49e7f62570280f99eb63b58")
} // // ef364b677911fa64d41a25d22d5e155065c4898046be65ddd627fa6c8cd87c2e
//}
func TestCBRetrieveToken(t *testing.T) { //
result, err := api.CBRetrieveToken() //func TestCBRetrieveToken(t *testing.T) {
if err != nil { // result, err := api.CBRetrieveToken()
t.Fatal(err.Error()) // if err != nil {
} // t.Fatal(err.Error())
t.Log(utils.Format4Output(result, false)) // }
} // t.Log(utils.Format4Output(result, false))
//}
func TestPushToSingle(t *testing.T) { //
result, err := api.PushToSingle("8aa96ba065a29a0135c5151819fb1666", false, &Notification{ //func TestPushToSingle(t *testing.T) {
Title: "测试", // result, err := api.PushToSingle("8aa96ba065a29a0135c5151819fb1666", false, &Notification{
Body: "测测测", // Title: "测试",
}) // Body: "测测测",
if err != nil { // })
t.Fatal(err.Error()) // if err != nil {
} // t.Fatal(err.Error())
t.Log(utils.Format4Output(result, false)) // }
// RASS_0911_1517001ff419d4699a0be17ac3f04a54 // t.Log(utils.Format4Output(result, false))
} // // RASS_0911_1517001ff419d4699a0be17ac3f04a54
//}