@@ -442,7 +442,11 @@ github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVc | |||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= | |||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= | |||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= | |||
github.com/xialeistudio/go-jpush v0.0.0-20240131095927-52180d0dcd2f h1:tZplxcu/gOk26hCDf4LBTZSB8bbdr1vUEC2Y32YFqE4= | |||
github.com/xialeistudio/go-jpush v0.0.0-20240131095927-52180d0dcd2f/go.mod h1:Yy3A3otA58L9C0kuUOgPFsKQ6/b+HUfX+aPoBA6ibFg= | |||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= | |||
github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369 h1:g95WlXTqXFLM36fhvDKcZWHTUnBb2KCEn4tuSizk/d8= | |||
github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369/go.mod h1:Nv7wKD2/bCdKUFNKcJRa99a+1+aSLlCRJFriFYdjz/I= | |||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||
@@ -0,0 +1,63 @@ | |||
package jPush | |||
import ( | |||
jpush "code.fnuoos.com/EggPlanet/egg_system_rules.git/jPush/sdk" | |||
"fmt" | |||
) | |||
// 极光推送 最大1000个用户 | |||
func PushMoreUser(key, secret, title, content string, alias []string, extras map[string]interface{}) (map[string]interface{}, error) { | |||
var client = jpush.NewClient(key, secret) | |||
audience := &jpush.PushAudience{ | |||
Alias: alias, | |||
} | |||
req := getMsg(title, content, audience, extras) | |||
result, err := client.Push(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return result, nil | |||
} | |||
// 广播推送 一天10次 | |||
func PushAllUser(key, secret, title, content string, extras map[string]interface{}) (map[string]interface{}, error) { | |||
var client = jpush.NewClient(key, secret) | |||
audience := "all" | |||
req := getMsg(title, content, audience, extras) | |||
result, err := client.Push(req) | |||
if err != nil { | |||
fmt.Println(err) | |||
return nil, err | |||
} | |||
fmt.Println(result) | |||
return result, nil | |||
} | |||
func getMsg(title, content string, audience interface{}, extras map[string]interface{}) *jpush.PushRequest { | |||
req := &jpush.PushRequest{ | |||
Platform: "all", | |||
Audience: audience, | |||
Notification: &jpush.PushNotification{ | |||
Alert: content, | |||
Android: &jpush.NotificationAndroid{ | |||
Alert: content, | |||
Title: title, | |||
}, | |||
Hmos: &jpush.NotificationHmos{ | |||
Alert: content, | |||
Title: title, | |||
}, | |||
IOS: &jpush.NotificationIOS{ | |||
Alert: content, | |||
}, | |||
}, | |||
Message: &jpush.PushMessage{ | |||
MsgContent: content, | |||
Extras: extras, | |||
}, | |||
Options: &jpush.PushOptions{ | |||
TimeToLive: 3 * 86400, | |||
ApnsProduction: false, | |||
}, | |||
} | |||
return req | |||
} |
@@ -0,0 +1,20 @@ | |||
# JPush GO SDK | |||
极光推送golang sdk。 | |||
官方的go sdk就新建了项目,没有文件,故开发本SDK。 | |||
使用教程直接参照单元测试代码即可。 | |||
## 功能列表 | |||
+ Push API v3 | |||
+ Report API v3 | |||
+ Device API v3 | |||
+ Schedule API v3 | |||
## 单元测试 | |||
1. 添加**APP_KEY**和**MASTER_SECRET**以及**REGISTRATION_ID**到环境变量 | |||
2. go test | |||
## 如何使用 | |||
参照单元测试即可 | |||
## 注意 | |||
**VIP类**接口和**Admin API v1**由于暂时没有权限,没有做实现。有需要的可以提交PR。 |
@@ -0,0 +1,20 @@ | |||
# JPush GO SDK | |||
[中文文档](README-CN.md) | |||
JPush GO SDK is the official Golang SDK for JPush, a push notification service. Since the official Go SDK only provides a project without any files, this SDK was developed to fill in the gap. Please refer to the unit test code for usage instructions. | |||
## Feature List | |||
+ Push API v3 | |||
+ Report API v3 | |||
+ Device API v3 | |||
+ Schedule API v3 | |||
## Unit Testing | |||
1. Add APP_KEY, MASTER_SECRET, and REGISTRATION_ID to the environment variables. | |||
2. Run `go test .` | |||
## How to Use | |||
Please refer to the unit test code for usage instructions. | |||
## Note | |||
The VIP class interfaces and Admin API v1 are not implemented due to lack of permission. If needed, you can submit a pull request. |
@@ -0,0 +1,60 @@ | |||
package jpush | |||
import ( | |||
"encoding/base64" | |||
"fmt" | |||
"io" | |||
"io/ioutil" | |||
"net/http" | |||
"runtime" | |||
) | |||
type Client struct { | |||
AppKey string | |||
MasterSecret string | |||
pushUrl string | |||
reportUrl string | |||
deviceUrl string | |||
} | |||
func NewClient(appKey, masterSecret string) *Client { | |||
client := &Client{AppKey: appKey, MasterSecret: masterSecret} | |||
client.pushUrl = "https://api.jpush.cn" | |||
client.reportUrl = "https://report.jpush.cn" | |||
client.deviceUrl = "https://device.jpush.cn" | |||
return client | |||
} | |||
func (c *Client) getAuthorization(isGroup bool) string { | |||
str := c.AppKey + ":" + c.MasterSecret | |||
if isGroup { | |||
str = "group-" + str | |||
} | |||
buf := []byte(str) | |||
return fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString(buf)) | |||
} | |||
func (c *Client) getUserAgent() string { | |||
return fmt.Sprintf("(%s) go/%s", runtime.GOOS, runtime.Version()) | |||
} | |||
func (c *Client) request(method, link string, body io.Reader, isGroup bool) (*Response, error) { | |||
req, err := http.NewRequest(method, link, body) | |||
if err != nil { | |||
return nil, err | |||
} | |||
req.Header.Set("Authorization", c.getAuthorization(isGroup)) | |||
req.Header.Set("User-Agent", c.getUserAgent()) | |||
req.Header.Set("Content-Type", "application/json") | |||
client := &http.Client{} | |||
resp, err := client.Do(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
defer resp.Body.Close() | |||
buf, err := ioutil.ReadAll(resp.Body) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return &Response{data: buf}, nil | |||
} |
@@ -0,0 +1,108 @@ | |||
package jpush | |||
import ( | |||
"bytes" | |||
"encoding/json" | |||
"strings" | |||
) | |||
func (c *Client) DeviceView(registrationId string) (map[string]interface{}, error) { | |||
link := c.deviceUrl + "/v3/devices/" + registrationId | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) DeviceRequest(registrationId string, req *DeviceSettingRequest) ([]byte, error) { | |||
link := c.deviceUrl + "/v3/devices/" + registrationId | |||
buf, err := json.Marshal(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Bytes(), nil | |||
} | |||
func (c *Client) DeviceEmptyTagsRequest(registrationId string, req *DeviceSettingEmptyTagsRequest) ([]byte, error) { | |||
link := c.deviceUrl + "/v3/devices/" + registrationId | |||
buf, err := json.Marshal(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Bytes(), nil | |||
} | |||
func (c *Client) DeviceGetWithAlias(alias string, platforms []string) (map[string]interface{}, error) { | |||
link := c.deviceUrl + "/v3/aliases/" + alias | |||
if len(platforms) > 0 { | |||
link += "?platform=" + strings.Join(platforms, ",") | |||
} | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) DeviceDeleteAlias(alias string) ([]byte, error) { | |||
link := c.deviceUrl + "/v3/aliases/" + alias | |||
resp, err := c.request("DELETE", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Bytes(), nil | |||
} | |||
func (c *Client) DeviceGetTags() (map[string]interface{}, error) { | |||
link := c.deviceUrl + "/v3/tags/" | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) DeviceCheckDeviceWithTag(tag, registrationId string) (map[string]interface{}, error) { | |||
link := c.deviceUrl + "/v3/tags/" + tag + "/registration_ids/" + registrationId | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) DeviceBindTags(tag string, req *DeviceBindTagsRequest) ([]byte, error) { | |||
link := c.deviceUrl + "/v3/tags/" + tag | |||
params := make(map[string]interface{}) | |||
params["registration_ids"] = req | |||
buf, err := json.Marshal(params) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Bytes(), nil | |||
} | |||
func (c *Client) DeviceDeleteTag(tag string, platforms []string) ([]byte, error) { | |||
link := c.deviceUrl + "/v3/tags/" + tag | |||
if len(platforms) > 0 { | |||
link += "?platform=" + strings.Join(platforms, ",") | |||
} | |||
resp, err := c.request("DELETE", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Bytes(), nil | |||
} |
@@ -0,0 +1,61 @@ | |||
package jpush | |||
import ( | |||
"bytes" | |||
"encoding/json" | |||
"strconv" | |||
) | |||
func (c *Client) Push(push *PushRequest) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/push" | |||
buf, err := json.Marshal(push) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) GetCidPool(count int, cidType string) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/push/cid?" | |||
if count > 0 { | |||
link += "count=" + strconv.Itoa(count) | |||
} | |||
if cidType != "" { | |||
link += "type=" + cidType | |||
} | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) GroupPush(push *PushRequest) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/grouppush" | |||
buf, err := json.Marshal(push) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), true) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) Validate(req *PushRequest) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/push/validate" | |||
buf, err := json.Marshal(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} |
@@ -0,0 +1,33 @@ | |||
package jpush | |||
import ( | |||
"bytes" | |||
"encoding/json" | |||
"errors" | |||
"strings" | |||
) | |||
func (c *Client) ReportReceived(msgIds []string) ([]interface{}, error) { | |||
if len(msgIds) == 0 { | |||
return nil, errors.New("msgIds不能为空") | |||
} | |||
link := c.reportUrl + "/v3/received?msg_ids=" + strings.Join(msgIds, ",") | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Array() | |||
} | |||
func (c *Client) ReportStatusMessage(req *ReportStatusRequest) (map[string]interface{}, error) { | |||
link := c.reportUrl + "/v3/status/message" | |||
buf, err := json.Marshal(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} |
@@ -0,0 +1,63 @@ | |||
package jpush | |||
import ( | |||
"bytes" | |||
"encoding/json" | |||
"strconv" | |||
) | |||
func (c *Client) ScheduleCreateTask(req *ScheduleRequest) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/schedules" | |||
buf, err := json.Marshal(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("POST", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) ScheduleGetList(page int) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/schedules" | |||
if page > 0 { | |||
link += "?page=" + strconv.Itoa(page) | |||
} | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) ScheduleView(id string) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/schedules/" + id | |||
resp, err := c.request("GET", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) ScheduleUpdate(id string, req *ScheduleRequest) (map[string]interface{}, error) { | |||
link := c.pushUrl + "/v3/schedules/" + id | |||
buf, err := json.Marshal(req) | |||
if err != nil { | |||
return nil, err | |||
} | |||
resp, err := c.request("PUT", link, bytes.NewReader(buf), false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Map() | |||
} | |||
func (c *Client) ScheduleDelete(id string) ([]byte, error) { | |||
link := c.pushUrl + "/v3/schedules/" + id | |||
resp, err := c.request("DELETE", link, nil, false) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return resp.Bytes(), nil | |||
} |
@@ -0,0 +1,20 @@ | |||
package jpush | |||
type DeviceSettingRequest struct { | |||
Tags *DeviceSettingRequestTags `json:"tags"` | |||
Alias string `json:"alias"` | |||
Mobile string `json:"mobile"` | |||
} | |||
type DeviceSettingEmptyTagsRequest struct { | |||
Tags string `json:"tags"` | |||
Alias string `json:"alias"` | |||
Mobile string `json:"mobile"` | |||
} | |||
type DeviceSettingRequestTags struct { | |||
Add []string `json:"add,omitempty"` | |||
Remove []string `json:"remove,omitempty"` | |||
} | |||
type DeviceBindTagsRequest struct { | |||
Add []string `json:"add,omitempty"` | |||
Remove []string `json:"remove,omitempty"` | |||
} |
@@ -0,0 +1,114 @@ | |||
package jpush | |||
import "encoding/json" | |||
type Platform string | |||
const ( | |||
PlatformAndroid Platform = "android" | |||
PlatformIOS Platform = "ios" | |||
PlatformWinPhone Platform = "winphone" | |||
) | |||
type PushAudience struct { | |||
Tag []string `json:"tag,omitempty"` | |||
TagAnd []string `json:"tag_and,omitempty"` | |||
TagNot []string `json:"tag_not,omitempty"` | |||
Alias []string `json:"alias,omitempty"` | |||
RegistrationId []string `json:"registration_id,omitempty"` | |||
Segment []string `json:"segment,omitempty"` | |||
ABTest []string `json:"abtest,omitempty"` | |||
} | |||
type PushNotification struct { | |||
Alert string `json:"alert,omitempty"` | |||
Android *NotificationAndroid `json:"android,omitempty"` | |||
Hmos *NotificationHmos `json:"hmos,omitempty"` | |||
IOS *NotificationIOS `json:"ios,omitempty"` | |||
WinPhone *NotificationWinPhone `json:"winphone,omitempty"` | |||
} | |||
type NotificationAndroid struct { | |||
Alert string `json:"alert"` | |||
Title string `json:"title,omitempty"` | |||
BuilderId int `json:"builder_id,int,omitempty"` | |||
Priority int `json:"priority,omitempty"` | |||
Category string `json:"category,omitempty"` | |||
Style int `json:"style,int,omitempty"` | |||
AlertType int `json:"alert_type,int,omitempty"` | |||
BigText string `json:"big_text,omitempty"` | |||
Inbox map[string]interface{} `json:"inbox,omitempty"` | |||
BigPicPath string `json:"big_pic_path,omitempty"` | |||
Extras map[string]interface{} `json:"extras,omitempty"` | |||
} | |||
type NotificationHmos struct { | |||
Alert string `json:"alert"` | |||
Title string `json:"title"` | |||
} | |||
type NotificationIOS struct { | |||
Alert interface{} `json:"alert"` | |||
Sound string `json:"sound,omitempty"` | |||
Badge int `json:"badge,int,omitempty"` | |||
ContentAvailable bool `json:"content-available,omitempty"` | |||
MutableContent bool `json:"mutable-content,omitempty"` | |||
Category string `json:"category,omitempty"` | |||
Extras map[string]interface{} `json:"extras,omitempty"` | |||
} | |||
type NotificationWinPhone struct { | |||
Alert string `json:"alert"` | |||
Title string `json:"title,omitempty"` | |||
OpenPage string `json:"_open_page,omitempty"` | |||
Extras map[string]interface{} `json:"extras,omitempty"` | |||
} | |||
type PushMessage struct { | |||
MsgContent string `json:"msg_content"` | |||
Title string `json:"title,omitempty"` | |||
ContentType string `json:"content_type,omitempty"` | |||
Extras map[string]interface{} `json:"extras,omitempty"` | |||
} | |||
type SmsMessage struct { | |||
Content string `json:"content"` | |||
DelayTime int `json:"delay_time,int,omitempty"` | |||
} | |||
type PushOptions struct { | |||
SendNo int `json:"sendno,int,omitempty"` | |||
TimeToLive int `json:"time_to_live,int,omitempty"` | |||
OverrideMsgId int64 `json:"override_msg_id,int64,omitempty"` | |||
ApnsProduction bool `json:"apns_production"` | |||
ApnsCollapseId string `json:"apns_collapse_id,omitempty"` | |||
BigPushDuration int `json:"big_push_duration,int,omitempty"` | |||
} | |||
type PushRequest struct { | |||
Cid string `json:"cid,omitempty"` | |||
Platform Platform `json:"platform"` | |||
Audience interface{} `json:"audience,omitempty"` | |||
Notification *PushNotification `json:"notification,omitempty"` | |||
Message *PushMessage `json:"message,omitempty"` | |||
SmsMessage *SmsMessage `json:"sms_message,omitempty"` | |||
Options *PushOptions `json:"options,omitempty"` | |||
} | |||
type Response struct { | |||
data []byte | |||
} | |||
func (res *Response) Array() ([]interface{}, error) { | |||
list := make([]interface{}, 0) | |||
err := json.Unmarshal(res.data, &list) | |||
return list, err | |||
} | |||
func (res *Response) Map() (map[string]interface{}, error) { | |||
result := make(map[string]interface{}) | |||
err := json.Unmarshal(res.data, &result) | |||
return result, err | |||
} | |||
func (res *Response) Bytes() []byte { | |||
return res.data | |||
} |
@@ -0,0 +1,7 @@ | |||
package jpush | |||
type ReportStatusRequest struct { | |||
MsgId int `json:"msg_id,int"` | |||
RegistrationIds []string `json:"registration_ids"` | |||
Date string `json:"date,omitempty"` | |||
} |
@@ -0,0 +1,33 @@ | |||
package jpush | |||
const ( | |||
ScheduleTimeUnitDay = "day" | |||
ScheduleTimeUnitWeek = "week" | |||
ScheduleTimeUnitMonth = "month" | |||
) | |||
type ScheduleRequest struct { | |||
Cid string `json:"cid,omitempty"` | |||
Name string `json:"name"` | |||
Enabled bool `json:"enabled"` | |||
Push *PushRequest `json:"push"` | |||
Trigger *ScheduleTrigger `json:"trigger"` | |||
} | |||
type ScheduleTrigger struct { | |||
Single *ScheduleTriggerSingle `json:"single,omitempty"` | |||
Periodical *ScheduleTriggerPeriodical `json:"periodical,omitempty"` | |||
} | |||
type ScheduleTriggerSingle struct { | |||
Timer string `json:"time,omitempty"` | |||
} | |||
type ScheduleTriggerPeriodical struct { | |||
Start string `json:"start,omitempty"` | |||
End string `json:"end,omitempty"` | |||
Time string `json:"time,omitempty"` | |||
TimeUnit string `json:"time_unit,omitempty"` | |||
Frequency int `json:"frequency,int,omitempty"` | |||
Point interface{} `json:"point,omitempty"` | |||
} |