liuxiaolong
2020-06-22 8a0cb38a396e18a9f220bd5144212baca18f49d1
push space left by uni-push
2个文件已添加
6个文件已修改
274 ■■■■■ 已修改文件
conf/app.conf 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controllers/car.go 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
extend/util/httpUtil.go 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
extend/util/util.go 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.go 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/carService_test.go 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/msgPush.go 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/msgPush_test.go 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
conf/app.conf
@@ -9,4 +9,11 @@
downdoc = true
latestVersion = 1.0.0
latestUrl =
juheweihaokey = 8c0efc4439080ef6c6aa2c29688c9550
juheweihaokey = 8c0efc4439080ef6c6aa2c29688c9550
pushAppId = WU8KzZBaTwADIjTwaMSzW5
pushAppKey = 9JLs4B1ZVkAVh93JXX3MP4
pushAppSecret = JuKr5y8IIC88WAWPicaSK3
pushMasterSecret = IbSAe83ZoZAczhKSA3Bwj9
pushPackageName = uni.UNI359F489
pushSignature = BA:AD:09:3A:82:82:9F:B4:32:A7:B2:8C:B4:CC:F0:E9:F3:7D:AE:58
pushBaseUrl = https://restapi.getui.com/v2/
controllers/car.go
@@ -4,14 +4,55 @@
    "car-service/extend/code"
    "car-service/models"
    "car-service/service"
    "fmt"
    "github.com/astaxie/beego"
    "net/http"
    "sort"
    "sync"
    "time"
)
type CarController struct {
    beego.Controller
}
//实时计算剩余车位数量,达到条件就推送
func ComputeSpaceLeftRealTime() {
    ticker := time.NewTicker(3 * time.Second)
    prePushLeft := 0
    for {
        select {
            case <-ticker.C:
                m := time.Now().Minute()
                i := m % 10
                left := 80
                if i == 0 {
                    left = 10
                }
                if m == 40 {
                    left = 5
                }
                if left <=10 && left != prePushLeft {
                    go service.Push("育英智慧停车", fmt.Sprintf("当前剩余车位:%d个", left))
                }
                updateSpaceLeft(left)
        default:
            time.Sleep(500 * time.Millisecond)
        }
    }
}
var cacheSpaceLeft int
var cLock sync.RWMutex
func updateSpaceLeft(num int) {
    cLock.Lock()
    defer cLock.Unlock()
    cacheSpaceLeft = num
}
func getSpaceLeft() int {
    cLock.Lock()
    defer cLock.Unlock()
    return cacheSpaceLeft
}
// @Title 统计剩余车位
@@ -22,15 +63,7 @@
func (c *CarController) Statistic() {
    //sv := service.NewCarService()
    //sta := sv.Statistic()
    m := time.Now().Minute()
    i := m % 10
    left := 80
    if i == 0 {
        left = 10
    }
    if m == 40 {
        left = 5
    }
    left := getSpaceLeft()
    sta := models.CarStatistic{
        Left: left,
    }
extend/util/httpUtil.go
@@ -15,6 +15,7 @@
    CONTENT_TYPE_FORM    = "application/x-www-form-urlencoded"
    CONTENT_TYPE_MULFORM = "multipart/form-data"
    CONTENT_TYPE_JSON    = "application/json"
    CONTENT_TYPE_UTF8_JSON = "application/json;charset=utf-8"
)
func DoPostRequest(url string, contentType string, body map[string]interface{}, params map[string]string, headers map[string]string) ([]byte, error) {
extend/util/util.go
@@ -5,16 +5,30 @@
    "crypto/md5"
    "crypto/sha256"
    "encoding/base64"
    "encoding/hex"
    "fmt"
    "math/rand"
    "strconv"
    "strings"
    "time"
    "unsafe"
)
func Sha256(message string) string {
    h := sha256.New()
    h.Write([]byte(message))
    res := h.Sum(nil)
    return hex.EncodeToString(res)
}
func ComputeHmacSha256Base64(message string, secret string) string {
    key := []byte(secret)
    h := hmac.New(sha256.New, key)
    h.Write([]byte(message))
    abs := h.Sum(nil)
    return base64.StdEncoding.EncodeToString(abs)
}
func Hik_ComputeSignatureBase64(appKey string, appSecret string, httpMethod string, accept string, contentType string, date string, url string) string {
    httpHeaders := httpMethod +"\n" + accept + "\n" + contentType + "\n"+ date +"\n"
@@ -43,4 +57,29 @@
func MD5Base64(s []byte) string {
    sum := md5.Sum(s)
    return base64.StdEncoding.EncodeToString(sum[:])
}
func GenValidateCode(width int) string {
    numeric := [10]byte{0,1,2,3,4,5,6,7,8,9}
    r := len(numeric)
    rand.Seed(time.Now().UnixNano())
    var sb strings.Builder
    for i := 0; i < width; i++ {
        fmt.Fprintf(&sb, "%d", numeric[ rand.Intn(r) ])
    }
    str := sb.String()
    if strings.HasPrefix(str, "0") {
        pI := RandInt(1,9)
        str = strconv.Itoa(pI) + str[1:]
    }
    return str
}
//生成区间随机数
func RandInt(min, max int) int {
    if min >= max || min ==0 ||max == 0 {
        return max
    }
    return rand.Intn(max-min) + min
}
main.go
@@ -12,5 +12,6 @@
        beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
    }
    controllers.Schedule()
    go controllers.ComputeSpaceLeftRealTime()
    beego.Run()
}
service/carService_test.go
@@ -1,11 +1,9 @@
package service
import (
    "fmt"
    "testing"
)
func TestCarService_Statistic(t *testing.T) {
    parkList := getHikParkList()
    fmt.Println("parkList:", parkList)
}
service/msgPush.go
New file
@@ -0,0 +1,156 @@
package service
import (
    "car-service/extend/util"
    "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)
            }
        }
    }()
}
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"`
}
func Push(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"
    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]string{
            "title": title,
            "body": msg,
            "click_type": "url",
            "url": "http://baidu.com",
        },
    }
    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("推送失败")
}
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
    appId := "WU8KzZBaTwADIjTwaMSzW5"
    appKey := "9JLs4B1ZVkAVh93JXX3MP4"
    masterSecret := "IbSAe83ZoZAczhKSA3Bwj9"
    baseUrl := "https://restapi.getui.com/v2/"+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失败")
}
service/msgPush_test.go
New file
@@ -0,0 +1,11 @@
package service
import (
    "fmt"
    "testing"
)
func TestRefreshToken(t *testing.T) {
    r, err := RefreshToken()
    fmt.Println(r, err)
}