Alibaba Cloud Push Notification Service Integration Guide
Push Notification Service
A cloud-to-device messaging solution that delivers notifications and messages to mobile endpoints, supporting both Android and iOS platforms through dedicated channels.
Notification vs Message Delivery
Notifications appear automatically in the device's status bar. Users can interact with or dismiss them. On iOS, notifications route through Apple's APNs infrastructure. Android notifications utilize the push service's proprietary channel.
Messages remain invisible in the notification drawer and require in-app handling to display. Both iOS and Android messages travel through the push service's internal channel.
Delivery Methods
Push targeting options include device-based delivery. Retrieve the device identifier on the client using the appropriate SDK method, then submit targets via console or OpenAPI endpoints.
Key Terminology
AppKey: A unique identifier assigned to each application within the push service. Required during SDK initialization and API calls. Obtain from the application credentials section in the console's app list.
AppSecret: The application's authentication key. Needed for SDK initialization. Fetch from the same credentials panel as AppKey.
AccessKeyId and AccessKeySecret: Credentials for authenticating OpenAPI calls. Acquire from the Alibaba Cloud console at https://ak-console.aliyun.com/#/accesskey.
ResponseId: A unique identifier returned by OpenAPI push requests. Useful when troubleshooting requires support assistance.
MessageId: An identifier for a specific push operation. Findable in notification or message delivery logs within the console.
DeviceId: A 32-character alphanumeric string serving as the device's push identifier. Fetch programmatically: Android uses CloudPushService.getDeviceId(), iOS uses CloudPushSDK.getDeviceId().
DeviceToken: A 64-character identifier issued by Apple's servers during device registration. iOS devices maintain both DeviceId and DeviceToken—these serve different purposes.
Account: A user-associated label assignable to devices. Each device accepts one account, while one account may reference multiple devices.
Alias: A custom label for targeting devices. Up to 128 aliases can bind to a single device, and up to 128 devices can share an alias.
Tag: Categorization labels for grouping devices. Each app supports up to 10,000 tags with no device limit per tag. Tag names must not exceed 128 characters.
Usage Constraints
Batch operations support a maximum of 1,000 targets when pushing by alias or device (comma-separated list). Account-based pushes accommodate 100 targets maximum. Tags are capped at 10,000 per application.
Initial Setup
Android Configuration
Enable Android support and provide the PackageName. This value must match your application's applicationId in the build configuration. Each application requires a unique package name, as the push SDK uses this identifier for routing. Misconfiguration may cause messages to reach unintended applications.
Retrieving AppKey and Secret
Navigate to the product list, select a specific product, access the app list, and click the credential viewing option to display AppKey and Secret values.
Device Association Operations
| Operation | Funcsion |
|---|---|
| QueryAliases | Retrieve alias bindings |
| BindAlias | Establish alias connection |
| UnbindAlias | Remove alias binding |
| QueryTags | Search tag assignments |
| ListTags | Enumerate available tags |
| BindTag | Create tag association |
| UnbindTag | Remove tag assignment |
| RemoveTag | Delete tag entirely |
Common Request Parameters
Every API call requires these parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| Format | String | No | Response format: JSON or XML (default: XML) |
| RegionId | String | Yes | Set to cn-hangzhou |
| Version | String | Yes | API version in YYYY-MM-DD format |
| AccessKeyId | String | Yes | User access key identifier |
| Signature | String | Yes | Computed request signature |
| SignatureMethod | String | Yes | HMAC-SHA1 |
| Timestamp | String | Yes | ISO 8601 UTC timestamp (YYYY-MM-DDThh:mm:ssZ) |
| SignatureVersion | String | Yes | Signature algorithm version (1.0) |
| SignatureNonce | String | Yes | Unique random value per request |
Request Example
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
&<operation-specific-parameters>
Response Structure
Every API response includes a RequestId for tracking purposes, regardless of success or failure.
{
"RequestId": "4C467B38-3910-447D-87BC-AC049166F216"
}
Endpoint Details
Service Endpoint: cloudpush.aliyuncs.com
Each request must specify an Action parameter (such as Push) along with common parameters and operation-specific parameters. All communication uses UTF-8 encoding.
Python Implementation
# -*- coding: utf-8 -*-
import os
import re
import configparser
from datetime import timedelta
from aliyunsdkpush.request.v20160801 import PushRequest
from aliyunsdkcore import client
from Config import ConfigPath
class PushNotificationClient:
MAX_TAG_OPERATIONS = 50
NOTIFICATION_TEMPLATES = {
"INIT": "Processing started for entity {0}",
"UPDATE": "Status changed for entity {0}",
"RETRY": "Operation restart for entity {0}"
}
def __init__(self, target_type, target_value):
self._target_type = target_type
self._target_value = target_value
config = configparser.ConfigParser()
config.read(ConfigPath)
self._ak_id = os.getenv('PUSH_ACCESS_KEY_ID',
config.get("push_config", "PUSH_ACCESS_KEY_ID"))
self._ak_secret = os.getenv('PUSH_ACCESS_KEY_SECRET',
config.get("push_config", "PUSH_ACCESS_KEY_SECRET"))
self._region = os.getenv('PUSH_REGION_ID',
config.get("push_config", "PUSH_REGION_ID"))
self._app_key = os.getenv('PUSH_APP_KEY',
config.get("push_config", "PUSH_APP_KEY"))
self._client = client.AcsClient(self._ak_id, self._ak_secret, self._region)
self._request = PushRequest.PushRequest()
self._request.set_AppKey(self._app_key)
async def send_notification(self, subject, content):
if not subject or not content:
return None
self._request.set_Target(self._target_type)
self._request.set_TargetValue(self._target_value)
self._request.set_DeviceType("ANDROID")
self._request.set_PushType("MESSAGE")
self._request.set_Title(subject)
self._request.set_Body(content)
schedule_time = datetime.utcnow() + timedelta(seconds=5)
expiration = datetime.utcnow() + timedelta(hours=24)
self._request.set_PushTime(schedule_time.strftime("%Y-%m-%dT%XZ"))
self._request.set_ExpireTime(expiration.strftime("%Y-%m-%dT%XZ"))
self._request.set_StoreOffline(True)
result = self._client.do_action(self._request)
result = result.decode('unicode_escape')
msg_id = re.findall("<MessageId>(.*)?</MessageId>", result)
return msg_id
Push Invocation Example
target_tags = {
"and": [
{ "tag": current_entity_code },
{ "or": list(map(lambda x: {"tag": x}, filtered_list)) }
]
}
print(target_tags)
push_client = PushNotificationClient("TAG", target_tags)
if job_type == JobTypes.INITIAL:
notification_title = "INIT"
notification_body = {
"type": 0,
"message": PushNotificationClient.NOTIFICATION_TEMPLATES["INIT"].format(current_entity_code)
}
elif job_type == JobTypes.SYNC:
notification_title = "UPDATE"
notification_body = {
"type": 0,
"message": PushNotificationClient.NOTIFICATION_TEMPLATES["UPDATE"].format(current_entity_code)
}
else:
continue
attempt = 1
success = False
while not success and attempt <= 3:
try:
await push_client.send_notification(notification_title, notification_body)
success = True
except Exception as error:
attempt += 1
if attempt > 3:
raise Exception("Failed to deliver notification after 3 attempts")