阿里云推送服务

时间:2022-09-24 12:53:20

移动推送

  • 提供从云端到移动终端的优质推送服务,支持Android和iOS平台的通知/消息的推送功能.

推送内容及模式

  • 通知:会自动在手机端弹出通知栏,用户可以打开或者清除通知栏。iOS的通知走APNs(苹果官方推送通知服务),android 走移动推送自己的通道

  消息:不会自动在通知栏弹出,会在app中提示消息的接收。iOS和android的消息都走移动推送自己的通道

推送方式

  • 按设备号推送,在客户端调用getDeviceld获得设备号,再通过控制台/openapi接口推送

名词解释

  • AppKey:app在移动推送中的唯一标示。推送SDK初始化和调用openapi推送时需要,从推送控制台APP列表页的应用证书中获取。

  • AppSecret:app的秘钥。推送SDK初始化时需要,从推送控制台APP列表页的应用证书中获取。

  • accessKeyld和accessKeySecret:阿里云用户使用云产品的openapi接口验权时需要,从阿里云官网控制台获取https://ak-console.aliyun.com/#/accesskey

  • responseld:openapi推送请求返回ID(如需排查问题可告诉客户人员该ID)。

  • messageld:某一次推送的消息ID。从控制台通知记录/消息记录中可以找到消息ID。

  • deviceld:设备在推送的唯一标示。 32位,数字和小写字母组合,通过代码获取:Android:CloudPushService的getDeviceld方法,iOS:CloudPushSDK的getDeviceld方法。

  • deviceToken:iOS设备在苹果中心注册时返回的64位设备标识符(iOS设备同时会有deviceld和deviceToken,请不要混淆)。

  • account:给设备添加的账号,可以是任意您的业务需要的,一个设备只能添加一个account,account可以添加多个设备。

  • alias:给设备添加的别名,可以是任意您的业务需要的,一个设备可以最多添加128个alias,一个alias可以最多添加128个设备。

  • tag:给设备添加的标签,可以是任意您的业务需要的,一个appkey最多能绑定1万个tag,一个tag下绑定的设备没有限制。

限制说明

  • targetValue如果为集合,按别名或者设备推送,一次最多传递1000个(通过“,”分割),按账户推送,则最多传递100个;
  • 每个App最多创建1万个tag,tag名称要小于等于128个字符(中文算1个),一个Tag下可以绑定多个设备,设备个数没有限制;

开始配置

  • Android配置: 勾选Android,并填入PackageName,包名需要与您的代码中的applicationID保持一致。请务必确保您创建的不同应用具有不同的PackageName(就是创建应用的bundleld),阿里云移动推送Android SDK以PackageName作为路由依据,不同应用配置相同包名,可能导致消息错误发送,即与目标应用有相同包名的应用接收到推送消息。

查看Appkey&Secret

在产品列表,进入单个产品管理,在APP列表点击查看信息按钮即可查看该应用的Appkey和Secret。

设备绑定

API 说明
QueryAliases 查询别名
BindAlias 绑定别名
UnbindAlias 解绑别名
QueryTags 查询TAG
ListTags TAG列表
BindTag 绑定TAG
UnbindTag 解绑TAG
RemoveTag 删除TAG

 

 

公共请求参数

公共请求参数是指每个接口都需要使用到的请求参数。

名称 类型 是否必须 描述
Format String 返回值的类型,支持JSON与XML,默认为XML。
RegionId String 当前请设置为cn-hangzhou
Version String API版本号,为日期形式YYYY-MM-DD,请参见概览
AccessKeyId String 阿里云颁发给用户的访问服务所用的密钥ID。
Signature String 签名结果串,关于签名的计算方法,请参见 签名机制
SignatureMethod String 签名方式,目前支持HMAC-SHA1。
Timestamp String 请求的时间戳。日期格式按照ISO8601标准表示,并需要使用UTC时间,格式为YYYY-MM-DDThh:mm:ssZ,例如2016-02-25T12:00:00Z(为UTC时间2016年2月25日12点0分0秒)。
SignatureVersion String 签名算法版本,目前版本是1.0。
SignatureNonce String 唯一随机数,用于防止网络重放攻击,用户在不同请求间要使用不同的随机数值。

 

示例

https://cloudpush.aliyuncs.com/
?Format=XML
&RegionId=cn-hangzhou
&Version=2016-08-01
&AccessKeyId=testid
&Signature=Pc5WB8gokVn0xfeu%2FZV%2BiNM1dgI%3D
&SignatureMethod=HMAC-SHA1
&SignatureNonce=15215528852396
&SignatureVersion=1.0
&Timestamp=2016-02-25T12:00:00Z
&<接口相关参数>

公共返回参数

用户发送的每次接口调用请求,无论成功与否,系统都会返回一个唯一识别码RequestId给用户。

 

JSON示例

{
    "RequestId": "4C467B38-3910-447D-87BC-AC049166F216"
    /* 返回结果数据 */
}

  

请求结构

服务地址

移动推送API的服务接入地址为:cloudpush.aliyuncs.com

请求参数

每个请求都需要指定要执行的操作,即Action参数(例如Push),以及每个操作都需要包含的公共请求参数和指定操作所特有的请求参数。

字符编码

请求及返回结果都使用UTF-8字符集进行编码

python 实现推送 

# -*- coding: utf-8 -*-

# import properties
import os
import re
from aliyunsdkpush.request.v20160801 import PushRequest
from aliyunsdkcore import client
from datetime import *
import configparser
from Config import *
import time

class AliPushRequest:

    TAG_MAX_OPER_NUM = 50
    MESSAGES = {
        "I10000": "Arranging Result Initialized. (School: {0})",
        "I10001": "Arranging Result Changed. (School: {0})",
        "I20000": "Restart. (School: {0})"
    }

    def __init__(self, target, targetValue):
        self._target = target
        # 标签 
        # JSON格式
        # tags = {"or":[{"tag":"123456878"}, {"tag": "53488700341"} ]}
        self._targetValue = targetValue
        # 读取配置文件
        self._cf = configparser.ConfigParser()
        self._cf.read(ConfigPath)

        # 读取环境变量或定义常量
        self._access_key_id = os.getenv('PREQ_ACCESS_KEY_ID', self._cf.get("push_request","PREQ_ACCESS_KEY_ID"))
        self._access_key_secret = os.getenv('PREQ_ACCESS_KEY_SECRET', self._cf.get("push_request","PREQ_ACCESS_KEY_SECRET"))
        self._region_id = os.getenv('PREQ_REGION_ID', self._cf.get("push_request","PREQ_REGION_ID"))
        self._app_key = os.getenv('PREQ_APP_KEY', self._cf.get("push_request","PREQ_APP_KEY"))        

        self._clt = client.AcsClient(self._access_key_id, self._access_key_secret, self._region_id)
        self._request = PushRequest.PushRequest()
        self._request.set_AppKey(self._app_key)


    async def banpai_push_msg(self, title, message):
        # 检查参数不为空
        if title and message: 
            #推送目标: 按标签推送
            self._request.set_Target(self._target)
            #设置Tag Value
            self._request.set_TargetValue(self._targetValue)
            #设备类型 ANDROID
            self._request.set_DeviceType("ANDROID")
            #消息类型 MESSAGE
            self._request.set_PushType("MESSAGE")
            #消息的标题
            self._request.set_Title(title)
            #消息的内容
            self._request.set_Body(message)
            #30秒之后发送, 也可以设置成你指定固定时间
            pushDate = datetime.utcnow() + timedelta(seconds = +5)
            #24小时后消息失效, 不会再发送
            expireDate = datetime.utcnow() + timedelta(hours = +24)
            #转换成ISO8601T数据格式
            pushTime = pushDate.strftime("%Y-%m-%dT%XZ")
            expireTime = expireDate.strftime("%Y-%m-%dT%XZ")
            self._request.set_PushTime(pushTime)
            self._request.set_ExpireTime(expireTime)
            #设置过期时间,单位是小时
            # self._request.set_TimeOut(24)
            self._request.set_StoreOffline(True)
            res = self._clt.do_action(self._request)
            res = res.decode('unicode_escape')
            messageId = re.findall("<MessageId>(.*)?</MessageId>", res)
            return messageId
        else:
            return None

 

调用推送

tagsValue = {
    "and": [
        { "tag": self._Rucode },
        { "or": list(map(lambda x: {"tag": x}, arr)) }
    ]
}
print(tagsValue)
apr = AliPushRequest("TAG", tagsValue)
if self._jobType == CourseArranging.ConstJobTypeInit:
    push_title = "I10000"
    push_msg = {
        "type": 0, # 0 message 1 functional
        "message": AliPushRequest.MESSAGES["I10000"].format(self._Rucode)
    }
elif self._jobType == CourseArranging.ConstJobTypeSync:       
    push_title = "I10001"
    push_msg = {
        "type": 0, # 0 message 1 functional
        "message": AliPushRequest.MESSAGES["I10001"].format(self._Rucode)
    }
else:
    continue
cnt = 1
pushedFlag = False
while not pushedFlag and cnt <= 3:
    try:
        await apr.banpai_push_msg(push_title, push_msg)
        pushedFlag = True
    except Exception as ex:
        cnt += 1
    if cnt > 3:
        raise Exception("3 times push failed!")