Skip to content

Commit 77aeacb

Browse files
author
施凯伦
committed
init xiaomi push golang sdk
0 parents  commit 77aeacb

File tree

5 files changed

+436
-0
lines changed

5 files changed

+436
-0
lines changed

demo.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/yilee/xiaomi-push/xiaomipush"
7+
)
8+
9+
func main() {
10+
msg := xiaomipush.NewMessage("hi baby")
11+
client := xiaomipush.NewClient("xxxxxsad", "packagename")
12+
result, err := client.Push(msg, []string{"fake_reg_id_1", "fake_reg_id_2"})
13+
if err != nil {
14+
return
15+
}
16+
fmt.Printf("result:%#v\n", result)
17+
}

xiaomipush/client.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package xiaomipush
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"io/ioutil"
7+
"net/http"
8+
"net/url"
9+
"runtime"
10+
"strconv"
11+
"strings"
12+
)
13+
14+
type MiPush struct {
15+
packageName string
16+
host string
17+
appSecret string
18+
}
19+
20+
func NewClient(appSecret, packageName string) *MiPush {
21+
return &MiPush{
22+
packageName: packageName,
23+
host: ProductionHost,
24+
appSecret: appSecret,
25+
}
26+
}
27+
28+
func (m *MiPush) Push(msg *Message, regIDList []string) (*Result, error) {
29+
params := m.assemblePushParams(msg, regIDList)
30+
return m.doPost(m.host+RegURL, params)
31+
}
32+
33+
func (m *MiPush) Stats(start, end string) (*Result, error) {
34+
params := m.assembleStatsParams(start, end)
35+
return m.doGet(m.host+StatsURL, params)
36+
}
37+
38+
func (m *MiPush) Status(msgID string) (*Result, error) {
39+
params := m.assembleStatusParams(msgID)
40+
return m.doGet(m.host+MessageStatusURL, params)
41+
}
42+
43+
func (m *MiPush) assemblePushParams(msg *Message, regIDList []string) map[string]string {
44+
params := make(map[string]string)
45+
params["registration_id"] = strings.Join(regIDList, ",")
46+
params["restricted_package_name"] = m.packageName
47+
48+
if msg.timeToLive > 0 {
49+
params["time_to_live"] = strconv.FormatInt(msg.timeToLive, 10)
50+
}
51+
if len(msg.payload) > 0 {
52+
params["payload"] = msg.payload
53+
}
54+
if len(msg.title) > 0 {
55+
params["title"] = msg.title
56+
}
57+
if len(msg.description) > 0 {
58+
params["description"] = msg.description
59+
}
60+
params["notify_type"] = strconv.FormatInt(int64(msg.notifyType), 10)
61+
params["pass_through"] = strconv.FormatInt(int64(msg.passThrough), 10)
62+
if msg.notifyID > 0 {
63+
params["notify_id"] = strconv.FormatInt(msg.notifyID, 10)
64+
}
65+
if msg.timeToSend > 0 {
66+
params["time_to_send"] = strconv.FormatInt(msg.timeToSend, 10)
67+
}
68+
if msg.extra != nil && len(msg.extra) > 0 {
69+
for k, v := range msg.extra {
70+
params["extra."+k] = v
71+
}
72+
}
73+
return params
74+
}
75+
76+
func (m *MiPush) assembleStatsParams(start, end string) string {
77+
form := url.Values{}
78+
form.Add("start_date", start)
79+
form.Add("end_date", end)
80+
form.Add("restricted_package_name", m.packageName)
81+
return "?" + form.Encode()
82+
}
83+
84+
func (m *MiPush) assembleStatusParams(msgID string) string {
85+
form := url.Values{}
86+
form.Add("msg_id", msgID)
87+
return "?" + form.Encode()
88+
}
89+
90+
func (m *MiPush) handlePushResponse(response *http.Response) (*Result, error) {
91+
defer func() {
92+
_ = response.Body.Close()
93+
}()
94+
data, err := ioutil.ReadAll(response.Body)
95+
if err != nil {
96+
return nil, err
97+
}
98+
return getResultFromJSON(data)
99+
}
100+
101+
func (m *MiPush) doPost(url string, params map[string]string) (*Result, error) {
102+
var result *Result
103+
var req *http.Request
104+
var resp *http.Response
105+
var err error
106+
data, _ := json.Marshal(params)
107+
req, err = http.NewRequest("POST", url, bytes.NewBuffer(data))
108+
req.Header.Set("X-PUSH-OS", runtime.GOOS)
109+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
110+
req.Header.Set("Authorizatione", "key="+m.appSecret)
111+
112+
client := &http.Client{}
113+
resp, err = client.Do(req)
114+
if err != nil {
115+
return nil, err
116+
}
117+
defer func() { _ = resp.Body.Close() }()
118+
result, err = m.handlePushResponse(resp)
119+
if err != nil {
120+
return nil, err
121+
}
122+
return result, nil
123+
}
124+
125+
func (m *MiPush) doGet(url string, params string) (*Result, error) {
126+
var result *Result
127+
var req *http.Request
128+
var resp *http.Response
129+
var err error
130+
req, err = http.NewRequest("GET", url+params, nil)
131+
req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
132+
req.Header.Set("Authorizatione", "key="+m.appSecret)
133+
134+
client := &http.Client{}
135+
resp, err = client.Do(req)
136+
if err != nil {
137+
return nil, err
138+
}
139+
defer func() { _ = resp.Body.Close() }()
140+
result, err = m.handlePushResponse(resp)
141+
if err != nil {
142+
return nil, err
143+
}
144+
return result, nil
145+
}

xiaomipush/constants.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package xiaomipush
2+
3+
const (
4+
ProductionHost = "https://api.xmpush.xiaomi.com"
5+
SandboxHost = "https://sandbox.xmpush.xiaomi.com" // iOS supported only
6+
)
7+
8+
const (
9+
RegURL = "/v3/message/regid" // 向某个regid或一组regid列表推送某条消息
10+
MessageAllURL = "/v3/message/all" // 向所有设备推送某条消息
11+
MultiMessagesURL = "/v2/multi_messages/regids" // 针对不同的regid推送不同的消息
12+
StatsURL = "/v1/stats/message/counters" // 统计push
13+
MessageStatusURL = "/v1/trace/message/status" // 获取指定ID的消息状态
14+
)
15+
16+
var (
17+
ErrorCodeMap = map[string]string{
18+
"-1": "未知错误",
19+
"0": "成功",
20+
"100": "参数不能为空",
21+
"10001": "系统错误",
22+
"10002": "服务暂停",
23+
"10003": "服务暂停",
24+
"10004": "服务暂停",
25+
"10005": "服务暂停",
26+
"10006": "服务暂停",
27+
"10007": "服务暂停",
28+
"10008": "服务暂停",
29+
"10009": "服务暂停",
30+
"10010": "服务暂停",
31+
"10011": "服务暂停",
32+
"10012": "服务暂停",
33+
"10013": "服务暂停",
34+
"10014": "服务暂停",
35+
"10016": "服务暂停",
36+
"10017": "服务暂停",
37+
"10018": "服务暂停",
38+
"10020": "服务暂停",
39+
"10021": "服务暂停",
40+
"10022": "服务暂停",
41+
"10023": "服务暂停",
42+
"10024": "服务暂停",
43+
"10025": "服务暂停",
44+
"10026": "服务暂停",
45+
"10027": "服务暂停",
46+
"10028": "服务暂停",
47+
"10029": "服务暂停",
48+
49+
"22000": "服务暂停",
50+
"22001": "服务暂停",
51+
"22002": "服务暂停",
52+
"22003": "服务暂停",
53+
"22004": "服务暂停",
54+
"22005": "服务暂停",
55+
"22006": "服务暂停",
56+
"22007": "服务暂停",
57+
"22008": "服务暂停",
58+
"22020": "服务暂停",
59+
"22021": "服务暂停",
60+
"22022": "服务暂停",
61+
"22100": "服务暂停",
62+
"22101": "服务暂停",
63+
"22102": "服务暂停",
64+
"22103": "服务暂停",
65+
}
66+
)
67+
68+
// for targeted push
69+
var (
70+
BrandsMap = map[string]string{
71+
"品牌": "MODEL",
72+
"小米": "xiaomi",
73+
"三星": "samsung",
74+
"华为": "huawei",
75+
"中兴": "zte",
76+
"中兴努比亚": "nubia",
77+
"酷派": "coolpad",
78+
"联想": "lenovo",
79+
"魅族": "meizu",
80+
"HTC": "htc",
81+
"OPPO": "oppo",
82+
"VIVO": "vivo",
83+
"摩托罗拉": "motorola",
84+
"索尼": "sony",
85+
"LG": "lg",
86+
"金立": "jinli",
87+
"天语": "tianyu",
88+
"诺基亚": "nokia",
89+
"美图秀秀": "meitu",
90+
"谷歌": "google",
91+
"TCL": "tcl",
92+
"锤子手机": "chuizi",
93+
"一加手机": "1+",
94+
"中国移动": "chinamobile",
95+
"昂达": "angda",
96+
"邦华": "banghua",
97+
"波导": "bird",
98+
"长虹": "changhong",
99+
"大可乐": "dakele",
100+
"朵唯": "doov",
101+
"海尔": "haier",
102+
"海信": "hisense",
103+
"康佳": "konka",
104+
"酷比魔方": "kubimofang",
105+
"米歌": "mige",
106+
"欧博信": "ouboxin",
107+
"欧新": "ouxin",
108+
"飞利浦": "philip",
109+
"维图": "voto",
110+
"小辣椒": "xiaolajiao",
111+
"夏新": "xiaxin",
112+
"亿通": "yitong",
113+
"语信": "yuxin",
114+
}
115+
116+
PriceMap = map[string]string{
117+
"0-999": "0-999",
118+
"1000-1999": "1000-1999",
119+
"2000-3999": "2000-3999",
120+
"4000+": "4000+",
121+
}
122+
)

xiaomipush/message.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package xiaomipush
2+
3+
import "time"
4+
5+
type Message struct {
6+
uniqueID string
7+
collapseKey string
8+
payload string
9+
title string
10+
description string
11+
passThrough int32
12+
notifyType int32
13+
notifyID int64
14+
timeToLive int64
15+
timeToSend int64
16+
extra map[string]string
17+
}
18+
19+
const (
20+
MaxTimeToSend = time.Hour * 24 * 7
21+
MaxTimeToLive = time.Hour * 24 * 7 * 2
22+
)
23+
24+
type TargetType int32
25+
26+
const (
27+
TargetTypeRegID TargetType = 1
28+
TargetTypeReAlias TargetType = 2
29+
TargetTypeAccount TargetType = 3
30+
)
31+
32+
func NewMessage(payload string) *Message {
33+
return &Message{
34+
uniqueID: "",
35+
payload: payload,
36+
title: "", // TBD
37+
description: "", // TBD
38+
passThrough: 1,
39+
notifyType: -1, // default notify type
40+
extra: make(map[string]string),
41+
}
42+
}
43+
44+
func (m *Message) SetUniqueID(uniqueID string) *Message {
45+
m.uniqueID = uniqueID
46+
return m
47+
}
48+
49+
func (m *Message) SetTimeToSend(tts int64) *Message {
50+
if time.Since(time.Unix(0, tts*int64(time.Millisecond))) > MaxTimeToSend {
51+
m.timeToSend = time.Now().Add(MaxTimeToSend).UnixNano() / 1e6
52+
} else {
53+
m.timeToSend = tts
54+
}
55+
return m
56+
}
57+
58+
func (m *Message) SetTimeToLive(ttl int64) *Message {
59+
if time.Since(time.Unix(0, ttl*int64(time.Millisecond))) > MaxTimeToLive {
60+
m.timeToLive = time.Now().Add(MaxTimeToLive).UnixNano() / 1e6
61+
} else {
62+
m.timeToLive = ttl
63+
}
64+
return m
65+
}
66+
67+
func (m *Message) EnableFlowControl() *Message {
68+
m.extra["flow_control"] = "1"
69+
return m
70+
}
71+
72+
func (m *Message) DisableFlowControl() *Message {
73+
delete(m.extra, "flow_control")
74+
return m
75+
}
76+
77+
// 小米推送服务器每隔1s将已送达或已点击的消息ID和对应设备的regid或alias通过调用第三方http接口传给开发者。
78+
func (m *Message) SetCallback(callbackURL string) *Message {
79+
m.extra["callback"] = callbackURL
80+
m.extra["callback.param"] = m.uniqueID
81+
m.extra["callback.type"] = "3" // 1:送达回执, 2:点击回执, 3:送达和点击回执
82+
return m
83+
}
84+
85+
// TargetedMessage封装了MiPush推送服务系统中的消息Message对象,和该Message对象所要发送到的目标。
86+
type TargetedMessage struct {
87+
message *Message
88+
targetType TargetType
89+
target string
90+
}
91+
92+
func NewTargetedMessage(m *Message, target string, targetType TargetType) *TargetedMessage {
93+
return &TargetedMessage{
94+
message: m,
95+
targetType: targetType,
96+
target: target,
97+
}
98+
}
99+
100+
func (tm *TargetedMessage) SetTargetType(targetType TargetType) *TargetedMessage {
101+
tm.targetType = targetType
102+
return tm
103+
}
104+
105+
func (tm *TargetedMessage) SetTarget(target string) *TargetedMessage {
106+
tm.target = target
107+
return tm
108+
}

0 commit comments

Comments
 (0)