package service import ( "car-service/extend/util" "car-service/models" "encoding/json" "errors" "fmt" "github.com/astaxie/beego" "sync" "time" ) var latestToken *TokenResult var lock sync.RWMutex func getCacheToken() string { lock.Lock() defer lock.Unlock() if latestToken != nil { return latestToken.Token } return "" } func updateToken(newT *TokenResult) { lock.Lock() defer lock.Unlock() latestToken = newT } func init() { newToken, err := RefreshToken() if err == nil { updateToken(newToken) } ticker := time.NewTicker(time.Hour * 20) go func() { for { select { case <-ticker.C: if t,err := RefreshToken();err == nil { updateToken(t) } default: time.Sleep(time.Second * 5) } } }() } //批量解绑别名 func UnbindAlias(cid string) (bool, error) { var uc models.UserClient ucList := uc.GetByCid(cid) if ucList ==nil { return true,errors.New("ucList is nil") } var aliasArr []string for _,als := range ucList { aliasArr = append(aliasArr, als.PhoneNum) } appId := beego.AppConfig.String("pushAppId") baseUrl := beego.AppConfig.String("pushBaseUrl") + appId retryTimes := 0 ReTry: token := getCacheToken() if token == "" { return false, errors.New("token is nil") } url := baseUrl + "/user/alias" header := map[string]string { "token": token, } caArr := make([]map[string]string, 0) for _,as := range aliasArr { caArr = append(caArr, map[string]string{ "cid": cid, "alias": as, }) } reqBody := map[string]interface{}{ "data_list": caArr, } b,err := util.DoDeleteRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, header) if err !=nil { fmt.Println("DoDelete err:", err) return false, err } var result PushResult err = json.Unmarshal(b, &result) if err != nil { fmt.Println("unmarshal err:", err) return false, err } if result.Code == 0 { //解绑成功 return true, nil } else if result.Code == 10001 { //token过期 if retryTimes <=3 { newToken, err := RefreshToken() if err == nil { updateToken(newToken) retryTimes++ goto ReTry } } } return false, errors.New(result.Msg) } //一个别名最多允许绑定10个cid func BindAlias(cid, alias string) (bool, error) { appId := beego.AppConfig.String("pushAppId") baseUrl := beego.AppConfig.String("pushBaseUrl") + appId retryTimes := 0 ReTry: token := getCacheToken() if token == "" { return false, errors.New("token is nil") } url := baseUrl+"/user/alias" caArr := make([]map[string]string, 0) caArr = append(caArr, map[string]string{ "cid": cid, "alias": alias, }) reqBody := map[string]interface{} { "data_list":caArr, } header := map[string]string { "token": token, } b, err := util.DoPostRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, nil, header) if err !=nil { fmt.Println("DoPost err:", err) return false, err } var result PushResult err = json.Unmarshal(b, &result) if err != nil { fmt.Println("unmarshal err:", err) return false, err } if result.Code == 0 { //绑定成功 return true, nil } else if result.Code == 10001 { //token过期 if retryTimes <=3 { newToken, err := RefreshToken() if err == nil { updateToken(newToken) retryTimes++ goto ReTry } } } return false, errors.New(result.Msg) } type PushResult struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } type TokenResult struct { ExpireTime string `json:"expire_time"` Token string `json:"token"` } type CreatePushMsgResult struct { TaskId string `json:"taskid"` } func createPushMsg(title string, msg string) (bool,string, error) { appId := beego.AppConfig.String("pushAppId") baseUrl := beego.AppConfig.String("pushBaseUrl") + appId retryTimes := 0 ReTry: token := getCacheToken() if token == "" { return false, "", errors.New("token is nil") } url := baseUrl+"/push/list/message" intent := "intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;component=uni.UNIEDF0B5C/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title="+title+";S.content="+msg+";S.payload=test;end" reqBody := map[string]interface{} { "request_id": time.Now().Format("20060102150405") + util.GenValidateCode(6), "settings":map[string]int { "ttl": 8 * 3600 * 1000, }, "push_message": map[string]map[string]string { "notification": { "title": title, "body": msg, "click_type": "intent", "intent": intent, }, }, "push_channel": map[string]map[string]map[string]map[string]string { "android": { "ups": { "notification": { "title": title, "body": msg, "click_type": "intent", "intent": intent, }, }, }, }, } header := map[string]string { "token": token, } b, err := util.DoPostRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, nil, header) if err !=nil { fmt.Println("DoPost err:", err) return false, "",err } var result PushResult err = json.Unmarshal(b, &result) if err != nil { fmt.Println("unmarshal err:", err) return false, "",err } if result.Code == 0 { rb,uErr := json.Marshal(result.Data) if uErr == nil { var tResult CreatePushMsgResult if uErr =json.Unmarshal(rb, &tResult); uErr ==nil { return true, tResult.TaskId, nil } else { return false, "", uErr } } else { return false, "", uErr } } else if result.Code == 10001 { //token过期 if retryTimes <=3 { newToken, err := RefreshToken() if err == nil { updateToken(newToken) retryTimes++ goto ReTry } } } return false, "", errors.New(result.Msg) } //对已注册的用户进行消息推送。调用此接口前需调用创建消息接口设置消息内容 func PushByAlias(title string, msg string) (bool, error) { var aliasArr []string pushUserM := make(map[string]string) var userE models.User allUsers, _ := userE.GetAllUsers() if allUsers != nil { for _,u := range allUsers { pushUserM[u.Id] = u.PhoneNum } } if len(pushUserM) == 0 { return true,errors.New("len(pushUserM) == 0") } carPersonM := make(map[string]string) //以车牌号为key,value是hik的personId csv := NewCarService() carPersons := csv.GetVehicleListByPerson("") if carPersons != nil { for _, cp := range carPersons { carPersonM[cp.PlateNo] = cp.PersonId } } delPersonIdM := make(map[string]string) spaceNos := csv.FindSpaceNo("") for _,sn := range spaceNos { if sn.State == 1 && sn.PlateNo != "" { //已经把车停到停车场的车主,不再推送消息 if pId,ok := carPersonM[sn.PlateNo];ok { delPersonIdM[pId] = pId delete(carPersonM, sn.PlateNo) } } } var uc models.UserClient for _,personId := range carPersonM { if phoneNum,ok := pushUserM[personId]; ok { //此人已注册到系统,并且车不在停车库内 if _,in := delPersonIdM[personId];!in { if uc.Exist(phoneNum) { aliasArr = append(aliasArr, phoneNum) } } } } lenAS := len(aliasArr) if lenAS == 0 { return true, errors.New("aliasArr is empty") } cResult, taskId, ce := createPushMsg(title, msg) fmt.Println("createPushMsg taskId:", taskId, "cResult:",cResult, "err:", ce) if !cResult { return false, errors.New("创建推送前置消息失败") } //alias 单次推送长度上限是200 pushTime := 1 if lenAS > 200 { pushTime = lenAS / 200 if lenAS % 200 >0 { pushTime++ } } isSuccess := false for i:=0;i0 { flag, e := doPush(taskId, curAliasArr) if e != nil { fmt.Println("doPush err:", e) } if flag { isSuccess = true } } } if isSuccess { return true, nil } return false, errors.New("推送失败") } func doPush(taskId string, aliasArr []string) (bool,error) { appId := beego.AppConfig.String("pushAppId") baseUrl := beego.AppConfig.String("pushBaseUrl") + appId retryTimes := 0 ReTry: token := getCacheToken() if token == "" { return false, errors.New("token is nil") } url := baseUrl+"/push/list/alias" reqBody := map[string]interface{} { "audience":map[string]interface{}{ "alias": aliasArr, }, "taskid": taskId, "is_async": false, } header := map[string]string { "token": token, } b, err := util.DoPostRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, nil, header) if err !=nil { fmt.Println("DoPost err:", err) return false, err } var result PushResult err = json.Unmarshal(b, &result) if err != nil { fmt.Println("unmarshal err:", err) return false, err } if result.Code == 0 { return true, nil } else if result.Code == 10001 { //token过期 if retryTimes <=3 { newToken, err := RefreshToken() if err == nil { updateToken(newToken) retryTimes++ goto ReTry } } } else { fmt.Println("推送结果:", result) } return false, errors.New("推送失败") } func NightPush(title string, msg string) (bool, error) { var aliasArr []string pushUserM := make(map[string]string) var userE models.User allUsers, _ := userE.GetAllUsers() if allUsers != nil { for _,u := range allUsers { pushUserM[u.Id] = u.PhoneNum } } if len(pushUserM) == 0 { return true,nil } carPersonM := make(map[string]string) csv := NewCarService() carPersons := csv.GetVehicleListByPerson("") if carPersons != nil { for _, cp := range carPersons { carPersonM[cp.PlateNo] = cp.PersonId } } spaceNos := csv.FindSpaceNo("") var uc models.UserClient for _,sn := range spaceNos { if sn.State == 1 && sn.PlateNo != "" { //已经把车停到停车场的车主,不再推送消息 if personId,ok := carPersonM[sn.PlateNo];ok { if phoneNum,ok := pushUserM[personId]; ok { //此人已注册到系统,并且车不在停车库内 if uc.Exist(phoneNum) { aliasArr = append(aliasArr, phoneNum) } } } } } if len(aliasArr) == 0 { fmt.Println("没有推送目标,aliasArr is empty") return true, nil } cResult, taskId, ce := createPushMsg(title, msg) if !cResult { fmt.Println("createPushMsg taskId:", taskId, "err:", ce) return false, errors.New("创建推送前置消息失败") } return doPush(taskId, aliasArr) } func PushAll(title string, msg string) (bool,error) { appId := beego.AppConfig.String("pushAppId") baseUrl := beego.AppConfig.String("pushBaseUrl") + appId retryTimes := 0 ReTry: token := getCacheToken() if token == "" { return false, errors.New("token is nil") } url := baseUrl+"/push/all" intent := "intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;component=uni.UNIEDF0B5C/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title="+title+";S.content="+msg+";S.payload=test;end" reqBody := map[string]interface{} { "request_id": time.Now().Format("20060102150405") + util.GenValidateCode(6), "settings":map[string]int { "ttl": 8 * 3600 * 1000, }, "audience": "all", "push_message": map[string]map[string]string { "notification": { "title": title, "body": msg, "click_type": "intent", "intent": intent, }, }, "push_channel": map[string]map[string]map[string]map[string]string { "android": { "ups": { "notification": { "title": title, "body": msg, "click_type": "intent", "intent": intent, }, }, }, }, } header := map[string]string { "token": token, } b, err := util.DoPostRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, nil, header) if err !=nil { fmt.Println("DoPost err:", err) return false, err } var result PushResult err = json.Unmarshal(b, &result) if err != nil { fmt.Println("unmarshal err:", err) return false, err } if result.Code == 0 { return true, nil } else if result.Code == 10001 { //token过期 if retryTimes <=3 { newToken, err := RefreshToken() if err == nil { updateToken(newToken) retryTimes++ goto ReTry } } } else { fmt.Println("推送结果:", result) } return false, errors.New("推送失败") } func RefreshToken() (*TokenResult,error) { appId := beego.AppConfig.String("pushAppId") appKey := beego.AppConfig.String("pushAppKey") masterSecret := beego.AppConfig.String("pushMasterSecret") baseUrl := beego.AppConfig.String("pushBaseUrl") + appId url := baseUrl +"/auth" timestamp := fmt.Sprintf("%v", time.Now().UnixNano() / 1e6) sign := util.Sha256(appKey + timestamp + masterSecret) reqBody := map[string]interface{} { "sign": sign, "timestamp": timestamp, "appkey": appKey, } b, err := util.DoPostRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, nil, nil) if err !=nil { fmt.Println("DoPost err:", err) return nil, err } var result PushResult err = json.Unmarshal(b, &result) if err != nil { fmt.Println("unmarshal err:", err) return nil, err } if result.Code == 0 { db, err := json.Marshal(result.Data) if err != nil { fmt.Println("marshal err:", err) return nil, err } var t TokenResult err = json.Unmarshal(db, &t) if err != nil { fmt.Println("unmarshal err:", err) return nil, err } return &t, nil } return nil, errors.New("获取unipush平台token失败") }