集成示例
返回结果示例:
附录A unicast消息发送示例
Android 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"unicast",
"production_mode":"false",
"device_tokens":"xx(Android为44位)",
"payload":{
"display_type":"notification",// 消息类型
"body":{
"title":"xx", // 通知标题
"text":"xx",
"after_open":"go_app"
},
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"channel_properties":{
"channel_activity":"xxx" // 系统弹窗
},
"description":"测试单播消息-Android"
}iOS 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"unicast",
"production_mode":"false",
"device_tokens":"xx(iOS为64位)",
"payload":{
"aps":{// 苹果必填字段
"alert":{// 可为JSON类型和字符串类型,当content-available=1时(静默推送),可选; 否则必填。
"title":"title",
"subtitle":"subtitle",
"body":"body"
}
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"description":"测试单播消息-iOS"
}返回结果示例:
// 返回成功
{
"ret":"SUCCESS",
"data":{
"msg_id":"uu07343141897754408310"
},
}
// 返回失败
{
"ret":"FAIL",
"data":{
"error_code":"xxx"//错误码
"error_msg":"xxx"//错误信息
}
}附录B listcast消息发送示例
Android 示例:
},{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"listcast",
"device_tokens":"device1,device2,…",// 不能超过500个,多个device_token用英文逗号分隔
"payload":{
"display_type":"notification",// 消息类型
"body":{
"title":"xx", // 通知标题
"text":"xx",
"after_open":"go_app"
},
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"channel_properties":{
"channel_activity":"xxx" // 系统弹窗
},
"description":"测试列播通知-Android"
}iOS 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"listcast",
"device_tokens":"device_token1,device_token2,...",// 不能超过500个,多个device_token用英文逗号分隔
"payload":{
"aps":{// 苹果必填字段
"alert":{// 可为JSON类型和字符串类型,当content-available=1时(静默推送),可选; 否则必填。
"title":"title",
"subtitle":"subtitle",
"body":"body"
}
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"description":"测试列播消息-iOS"
}返回结果示例:
// 返回成功
{
"ret":"SUCCESS",
"data":{
"msg_id":"uu07343141897754408310"
}
}
// 返回失败
{
"ret":"FAIL",
"data":{
"error_code":"xxx"//错误码
"error_msg":"xxx"//错误信息
}
}附录C broadcast消息发送示例
Android 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"broadcast",
"payload":{
"display_type":"notification",// 通知,notification
"body":{
"ticker":"测试提示文字",
"title":"测试标题",
"text":"测试文字描述",
"after_open":"go_app"
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"channel_properties":{
"channel_activity":"xxx" // 系统弹窗
},
"description":"测试广播通知-Android"
}iOS 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"broadcast",
"payload":{
"aps":{// 苹果必填字段
"alert":{// 可为JSON类型和字符串类型,当content-available=1时(静默推送),可选; 否则必填。
"title":"title",
"subtitle":"subtitle",
"body":"body"
}
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"description":"测试广播通知-iOS"
}返回结果示例:
// 返回成功
{
"ret":"SUCCESS",
"data":{
"msg_id":"uu07343141897754408310"
}
}
// 返回失败
{
"ret":"FAIL",
"data":{
"error_code":"xxx"//错误码
"error_msg":"xxx"//错误信息
}
}附录D groupcast消息发送示例
Android 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"groupcast",
"filter":{
"where":{
"and":[{"app_version":"1.0"}]// 发送给app_version为1.0的用户群
}
},
"payload":{
"display_type":"notification",// 通知,notification
"body":{
"ticker":"测试提示文字",
"title":"测试标题",
"text":"测试文字描述",
"after_open":"go_app"
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"channel_properties":{
"channel_activity":"xxx" // 系统弹窗
},
"description":"测试组播通知-Android"
}iOS 示例:
{
"appKey":"你的appkey",
"timestamp":"你的timestamp",
"type":"groupcast",
"filter":{
"where":{
"and":[{"app_version":"1.0"}]
}
},
"payload":{
"aps":{// 苹果必填字段
"alert":{// 可为JSON类型和字符串类型,当content-available=1时(静默推送),可选; 否则必填。
"title":"title",
"subtitle":"subtitle",
"body":"body"
}
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"description":"测试组播通知-iOS"
}说明:其中的filter条件表示向当前所有app_version是v1.0的应用客户端发送消息,其内容的使用语法示例请参考附录G。
返回结果示例:
// 返回成功
{
"ret":"SUCCESS",
"data":{
"msg_id":"uu07343141897754408310"
}
}
// 返回失败
{
"ret":"FAIL",
"data":{
"error_code":"xxx"//错误码
"error_msg":"xxx"//错误信息
}
}附录E customizedcast消息发送示例
通过alias发送消息示例:
Android示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"customizedcast",
"alias":"你的alias",//不能超过500个,多个alias以英文逗号风格
"alias_type":"alias对应的type(SDK调用addAlias(alias,alis_type)接口指定的alias_type)",
"payload":{
"display_type":"notification",// 通知,notification
"body":{
"ticker":"测试提示文字",
"title":"测试标题",
"text":"测试文字描述",
"after_open":"go_app"
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"channel_properties":{
"channel_activity":"xxx" // 系统弹窗
},
//厂商下发相关参数设置参考附录B
"description":"测试alias通知-Android"
}
iOS 示例:
{
"appKey":"你的appkey",
"timestamp":"你的timestamp",
"type":"customizedcast",
"alias":"你的alias",//不能超过500个,多个alias以英文逗号分隔。
"alias_type":"alias对应的type",
"payload":{
"aps":{// 苹果必填字段
"alert":{// 可为JSON类型和字符串类型,当content-available=1时(静默推送),可选; 否则必填。
"title":"title",
"subtitle":"subtitle",
"body":"body"
}
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"description":"测试alias通知-iOS"
}返回结果示例:
// 返回成功
{
"ret":"SUCCESS",
"data":{
"msg_id":"uu07343141897754408310"
}
}
// 返回失败
{
"ret":"FAIL",
"data":{
"error_code":"xxx"//错误码
"error_msg":"xxx"//错误信息
}
}通过file_id方式发送消息示例:
(1)先通过文件上传接口获取文件id:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"content":"alias1\nalias2\nalias3\n..."// 多个alias用回车符分隔,回车符需要显示出现。
}文件上传接口 返回结果:
{
"ret":"SUCCESS",
"data":{
"file_id":"PF212711418961495056"
}
}(2)再通过文件方式发送消息:
Android 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"customizedcast",
"alias_type":"alias对应的type",
"file_id":"PF212711418961495056",// 通过文件上传接口获得的file_id
"payload":{
"display_type":"notification",// 通知,notification
"body":{
"ticker":"测试提示文字",
"title":"测试标题",
"text":"测试文字描述",
"after_open":"go_app"
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"channel_properties":{
"channel_activity":"xxx" // 系统弹窗
},
//厂商下发相关参数设置参考附录B
"description":"测试alias文件通知-Android"
}iOS 示例:
{
"appKey":"你的appkey",
"timestamp":"你的timestamp",
"type":"customizedcast",
"alias_type":"alias对应的type(SDK添加的alias的时候,会带一个type)",
"file_id":"PF8961384936199949",
"payload":{
"aps":{// 苹果必填字段
"alert":{// 可为JSON类型和字符串类型,当content-available=1时(静默推送),可选; 否则必填。
"title":"title",
"subtitle":"subtitle",
"body":"body"
}
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"description":"测试alias文件通知-iOS"
}返回结果示例:
// 返回成功
{
"ret":"SUCCESS",
"data":{
"msg_id":"uu07343141897754408310"
}
}
// 返回失败
{
"ret":"FAIL",
"data":{
"error_code":"xxx"//错误码
"error_msg":"xxx"//错误信息
}
}附录F filecast消息发送示例
(1)先通过文件上传接口获取文件id:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"content":"device_token_1\ndevice_token_2\ndevice_token_3\n..." // 多个device_token用回车符分隔,回车符需要显示出现。
}文件上传接口 返回结果:
{
"ret":"SUCCESS",
"data":{
"file_id":"PF212711418961495056"
}
}(2)再通过文件方式发送消息:
Android 示例:
{
"appkey":"你的appkey",
"timestamp":"你的timestamp",
"type":"filecast",
"file_id":"PF8961384936199949",// 通过文件上传接口获得的file_id
"payload":{
"display_type":"notification",// 通知,notification
"body":{
"ticker":"测试提示文字",
"title":"测试标题",
"text":"测试文字描述",
"after_open":"go_app"
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"channel_properties":{
"channel_activity":"xxx" // 系统弹窗
},
"description":"测试filecast文件通知-Android"
}iOS 示例:
{
"appKey":"你的appkey",
"timestamp":"你的timestamp",
"type":"filecast",
"file_id":"PF8961384936199949",
"payload":{
"aps":{// 苹果必填字段
"alert":{// 可为JSON类型和字符串类型,当content-available=1时(静默推送),可选; 否则必填。
"title":"title",
"subtitle":"subtitle",
"body":"body"
}
}
},
"policy":{
"expire_time":"2023-07-20 12:00:00"
},
"description":"测试filecast文件通知-iOS"
}返回结果示例:
// 返回成功
{
"ret":"SUCCESS",
"data":{
"msg_id":"uu07343141897754408310"
}
}
// 返回失败
{
"ret":"FAIL",
"data":{
"error_code":"xxx"//错误码
"error_msg":"xxx"//错误信息
}
}附录G 过滤条件示例
目前开放的筛选字段有:
“app_version”(应用版本)
“channel”(渠道)
“province”(省)
“tag”(用户标签)
“country”(国家和地区) //“country”和”province”的类型定义请参照 文档示例
“language”(语言)
“launch_from”(一段时间内活跃)
“not_launch_from”(一段时间内不活跃)
“install_in”(设备注册时间在最近)
“install_before”(设备注册时间在之前)
“push_switch”(通知开关状态)
注:push_switch(通知开关)有三个状态
{"push_switch":"true"}//设备通知开关是打开状态
{"push_switch":"false"}//设备通知开关是关闭状态
{"push_switch":"null"}//设备通知开关是未知状态我们的筛选条件非常灵活,支持逻辑上的and(与), or(或), not(非)操作, 以及这些操作的组合。具体请参照下面的示例。
and条件示例
已注册的(registered_user)并且版本(app_version)是1.0的用户群,在2020-09-30之后活跃过,设备注册时间在2020-09-01至2020-09-22之间,设备通知开关是打开状态的人群。
"where":
{
"and":
[
{"tag":"registered_user"},//开发者自定义tag
{"app_version":"1.0"},// app-version
{"launch_from":"2020-09-30"},// X天活跃/不活跃
{"install_in":"2020-09-01"},//设备注册时间在9月1号(含)之后
{"install_before":"2020-09-22"},//设备注册时间在9月22号(不含)之前
{"push_switch":"true"}//设备通知开关是打开状态
]
}or条件示例
自定义标签为“美剧”的用户或者自定义标签为“文艺”的用户
"where":{
"and":[
{
"or":[
{"tag":"美剧"},
{"tag":"文艺"}]
}
]
}not条件示例
未注册的(registered_user)的用户群
"where":
{
"and":
[
{
"not":
{
"tag":"registered_user"
}
}
]
}and, or, not组合条件示例
发送给分渠道非360或者“版本号为1.2”并且“2014-11-15之后不活跃”的用户
"where":
{
"and":
[
{
"or":
[
{
"not":
{
"channel":"360"
}
},
{
"app_version":"1.2"
}
]
},
{
"not_launch_from":"2014-11-15"
}
]
}大于等于(>=)及小于等于(<=)组合条件示例
如果要选择推送给版本>=某版本或者<=某版本的设备,以筛选>=1.0的设备为例,可采用以下两种方法实现:
方法一:自己筛选出符合要求的各个版本。(官方建议方案)格式为:
{"and":[{"or":[{"app_version":">=1.0"}]}]}方法二:自己筛选出符合要求的各个版本。格式为:
{"and":[{"or":[{"app_version":"1.0"},{"app_version":"2.0"},{"app_version":"3.0"},{"app_version":"4.0"}]}]}附录H 接口调用错误码
API通过HTTP Status Code来说明请求是否成功, 200表示成功, 400表示失败。
附录I 关于签名
为了确保用户发送的请求不被更改,我们设计了签名算法。该算法基本可以保证请求是合法者发送且参数没有被修改,但无法保证不被偷窥。 签名生成规则:
提取请求方法method(POST,全大写);
提取请求url信息,包括Host字段的域名(或ip:端口)和URI的path部分。注意不包括path的querystring。比如http://msg.umeng.com/api/send 或者 http://msg.umeng.com/api/status;
提取请求的post-body;
拼接请求方法、url、post-body及应用的app_master_secret;
将上一步形成的字符串计算MD5值,形成一个32位的十六进制(字母小写)字符串,即为本次请求sign(签名)的值;Sign=MD5(${http_method}${url}${post-body}${app_master_secret})
python生成签名示例
import hashlib
def md5(s):
m = hashlib.md5(s)
return m.hexdigest()
appkey ='你的appkey'
app_master_secret ='你的app_master_secret'
timestamp ='你的timestamp'
method ='POST'
url ='http://msg.umeng.com/api/send'
params = {
'appkey': appkey,
'timestamp': timestamp,
'device_tokens': device_token,
'type':'unicast',
'payload':{
'body':{
'ticker': 'Hello World',
'title': '你好',
'text': '来自友盟推送',
'after_open': 'go_app'
},
'display_type':'notification'
}
}
post_body = json.dumps(params)
print post_body
sign = md5('%s%s%s%s' % (method, url, post_body, app_master_secret))附录J HTTP常见Status Code及其含义
错误码 | 错误信息提示 | Http Status Code |
1000 | 请求参数没有appkey或为空值 | 400 |
1001 | 请求参数没有payload或为非法json | 400 |
1002 | 请求参数payload中, 没有body或为非法json | 400 |
1003 | payload.display_type为message时, 请求参数payload.body中, 没有custom字段 | 400 |
1004 | 请求参数payload中, 没有display_type或为空值 | 400 |
1005 | 请求参数payload.body中, img格式有误, 需以http或https开始 | 400 |
1007 | payload.body.after_open为go_url时, 请求参数payload.body中, url格式有误, 需以http或https开始 | 400 |
1008 | payload.display_type为notification时, 请求参数payload.body中, 没有ticker参数 | 400 |
1009 | payload.display_type为notification时, 请求参数payload.body中, 没有title参数 | 400 |
1010 | payload.display_type为notification时, 请求参数payload.body中, 没有text参数 | 400 |
1014 | task_id对应任务没有找到 | 400 |
1015 | type为unicast或listcast时, 请求参数没有device_tokens或为空值 | 400 |
1016 | 请求参数没有type或为空值 | 400 |
1019 | 请求参数payload中, display_type值非法 | 400 |
1020 | 应用组中尚未添加应用 | 400 |
1022 | payload.body.after_open为go_url时, 请求参数payload.body中, 没有url参数或为空 | 400 |
1024 | payload.body.after_open为go_activity时, 请求参数payload.body中, 没有activity或为空值 | 400 |
1025 | 请求参数payload中builder_id必须是整数 | |
1026 | 请求参数payload中, extra为非法json | 400 |
1027 | 请请求参数payload中, policy为非法json | 400 |
1028 | task_id对应任务无法撤销 | 400 |
2000 | 该应用已被禁用 | 400 |
2002 | 请求参数policy中, start_time必须大于当前时间 | 400 |
2003 | 请求参数policy中, expire_time必须大于start_time和当前时间 | 400 |
2004 | IP白名单尚未添加, 请到网站后台添加您的服务器IP或关闭IP白名单功能 | 400 |
2006 | Validation token不一致(PS: 此校验方法已废弃, 请采用sign进行校验) | 400 |
2007 | 未对请求进行签名 | 400 |
2008 | json解析错误 | 400 |
2009 | type为customizedcast时, 请求参数没有alias、file_id或皆为空值 | 400 |
2010 | alias_type和alias找不到匹配的device_token | 400 |
2015 | device_tokens个数已超过500 | 400 |
2016 | type为groupcast时, 请求参数没有filter或为非法json | 400 |
2017 | 添加tag失败 | 400 |
2018 | type为filecast时, 请求参数没有file_id或为空值 | 400 |
2019 | type为filecast时, file_id对应的文件不存在 | 400 |
2021 | appkey不存在 | 400 |
2022 | payload长度过长 | 400 |
2023 | 文件上传失败, 请稍后重试 | 400 |
2025 | 请求参数没有aps或为非法json | 400 |
2027 | 签名不正确 | 400 |
2028 | 时间戳已过期 | 400 |
2029 | 请求参数没有content或为空值 | 400 |
2031 | filter格式不正确 | 400 |
2032 | 未上传生产证书, 请到Web后台上传 | 400 |
2033 | 未上传开发证书, 请到Web后台上传 | 400 |
2034 | 证书已过期 | 400 |
2035 | 定时任务发送时, 证书已过期 | 400 |
2036 | 时间戳格式错误 | 400 |
2039 | 请求参数policy中, 时间格式必须是yyyy-MM-dd HH:mm:ss | 400 |
2040 | 请求参数policy中, expire_time不能超过发送时间+7天 | 400 |
2046 | 请求参数policy中, start_time不能超过当前时间+7天 | 400 |
2047 | type为customizedcast时, 请求参数没有alias_type或为空值 | 400 |
2048 | type值须为unicast、listcast、filecast、broadcast、groupcast、groupcast中的一种 | 400 |
2049 | type为customizedcast时, 请求参数alias、file_id只可二选一 | 400 |
2050 | 发送频率超出应用限额 | 400 |
2051 | 发送QPS超过限制 | 429 |
2052 | 请求参数没有timestamp或为空值 | 400 |
2053 | 请求参数没有task_id或为空值 | 400 |
2054 | IP不在白名单中, 请到网站后台添加您的服务器IP或关闭IP白名单功能 | 400 |
2060 | tag参数错误 | 400 |
2061 | tag数量太多 | 400 |
2062 | tag超长 | 400 |
2063 | 编码不支持 | 400 |
2064 | device_tokens不存在 | 400 |
2066 | device_tokens长度非法 | 400 |
5001 | 证书解析bundle id失败, 请重新上传 | 400 |
5002 | 请求参数payload中p、d为友盟保留字段 | 400 |
5007 | certificate_revoked错误 | 400 |
5008 | certificate_unkown错误 | 400 |
5009 | handshake_failure错误 | 400 |
5010 | 配置使用Token Auth, 但未上传p8证书 | 400 |
6001 | 该app未开通服务端tag接口 | 400 |
6002 | 内部错误(iOS证书) | 400 |
6003 | 内部错误(数据库) | 400 |
6006 | 系统繁忙,请稍后重试 | 400 |
6010 | 该app未开通服务端alias接口 | 400 |
7001 | 发送内容包含敏感词 | 400 |
8001 | 需要指定图片类型,大图或右侧图标 | 400 |
8002 | 图片地址太长 | 400 |
8003 | 图片地址需要是http或https格式 | 400 |
8004 | 图片地址URL解析错误 | 400 |
8005 | 图片大小超出厂商限制 | 400 |
8006 | 请确认图片格式,支持PNG/JPG/JPEG | 400 |
8007 | 图片下载失败请确认图片地址是否公网可用 | 400 |
8008 | 图片解析失败,请求检查图片base64编码是否正确 | 400 |
8009 | 图片上传厂商失败 | 400 |
8010 | 应用下图片数量超过限制,请删除无效数据或联系客服处理 | 400 |
8011 | 应用下持久化图片数量超过限制,请删除无效数据或联系客服处理 | 400 |
8012 | 图片接口请求频次过高 | 400 |
8013 | 图片接口超过每天请求额度限制 | 400 |
8014 | 图片地址和图片内容不能同时为空 | 400 |
8015 | 当前应用未配置厂商通道 | 400 |
8016 | 过期时间设置不准确, 请设置为yyyy-MM-dd HH:mm:ss格式, 有效时间段为当前时间至未来3年 | 400 |
8017 | 所有厂商上传失败 | 400 |
8018 | 指定地址不存在或已删除 | 400 |
温馨提示
为了保证使用友盟推送的开发者都能获得良好的用户体验,我们坚决杜绝滥用推送服务的事件发生。一经发现,友盟推送将有权对滥用服务的appkey实施封禁发送权限的处理。
技术支持
如果还有问题,请您点击右下角“在线客服”咨询(在线时间:工作日10:00~18:00),或在右上角点击“我的产品”——“我的反馈”中提交问题,我们会尽快回复您。
服务端代码调用示例
调用示例仅供集成阶段联调测试使用,不推荐应用在生产环境。