资讯动态

UniPush 2.0推送配置全指南:从厂商通道到客户端接入

发布时间:2026/10/14 6:19:27 来源:尧图企业网站定制
1. 动手之前先看懂 UniPush 的完整链路1.1 一个 App 的推送为什么是件麻烦事先说你早晚会撞上的问题App 一退到后台系统就把网络连接回收了你在服务端拼命发消息客户端却根本不知道该去收。iOS 更直接普通应用连常驻长连接都不允许想把消息送到用户眼前必须借助系统级通道。Android 虽然开放但国内各种定制系统把后台限制做得五花八门一个进程想常驻比上班摸鱼还难。UniPush 的思路是不再让 App 自己维持一条长连接而是把“消息要不要展示在系统通知栏”“消息什么时候触达”这些事交给系统级通道去处理。App 在线时走在线通道App 离线或被杀时走手机厂商的推送通道。这样用户看到的是系统通知而不是一个必须先打开 App 才能收到的“假通知”。这本配置指南我按“账号准备 → 厂商通道 → manifest 配置 → 客户端接入 → 服务端发送”五层来讲。你只要跟着每一层把参数填对整个链路就能通。1.2 UniPush 2.0 与旧版 1.0 的区别先避开过时教程网上搜“uni-app 推送”大概率会翻到plus.push开头的老代码那是 UniPush 1.0 时代的写法。1.0 把在线通道和厂商离线通道拆得很开发消息时还要区分“在线发透传”还是“离线发通知”接口又多又绕。我现在项目里一律用 UniPush 2.0它对外暴露的是uni.getPushClientId、uni.onPushMessage这一套。前端只需要拿一个cidClientID后端再拿cid去调推送接口剩下的在线、离线路由由服务端自动处理。这条升级线需要注意很多老教程里的plus.push代码在新版本里虽然能跑但控制台、消息记录、厂商回调都已经翻了新继续对着老文档配置你会越配越晕。再强调一个很容易混淆的点UniPush 2.0 里的token和 OAuth 登录的token完全是两码事。这里的 token 是服务端调推送接口时临时换来的访问令牌一般几分钟就会过期而登录 token 是业务系统的会话凭证。混用会导致后台怎么调都报 401。1.3 配置过程中绕不开的三组识别信息整个配置过程你会反复填三类“ID”先把它们焊死在脑子里排错时不用到处找。信息名称在哪里拿主要用途DCloud AppID开发者中心创建应用时自动生成uni-app 的 manifest.json 对应字段全局标识AppKey / AppSecretUniPush 推送控制台开通服务后生成服务端调用推送接口时用于签名鉴权ClientIDcidApp 客户端运行后由推送 SDK 生成服务端做定向推送时标识一台设备还有一个日常被当成“ID”的字段Android 应用包名applicationId。它在 HBuilderX 打包界面填写但必须和你去华为、小米等平台登记应用时用的包名完全一致。很多配置流程走到一半发现离线推送效果时好时坏问题就出在“打包时换过包名”这件事上。2. 开发者中心到推送服务开通先有通行证才能谈配置2.1 创建 DCloud 应用并完成实名认证一切配置的起点都在 DCloud 开发者中心。你先注册一个账号然后做实名认证这一步不是走形式推送通知属于消息触达能力平台需要明确责任主体实名不过关后续开通 uni-push 会直接卡住。认证通过后进入控制台创建应用。填应用名称、选择类型提交后会拿到一个__UNI__xxxxxxx格式的 DCloud AppID。这个 AppID 要原样填进项目的manifest.json - 基础配置 - Vue 应用 AppID里前端工程跟推送服务的绑定关系从这一格开始。我见过不少人不把 AppID 当回事随手复制别人项目的 ID 进去调试结果getPushClientId能返回但服务端一发就报设备不存在。原因很简单推送后台的系统里压根没有你这台设备。所以这一步宁可慢一点确认控制台和本地工程是同一个 ID。2.2 开通 uni-push 服务并区分套餐能力在开发者中心的“uni-push”或“消息推送”菜单里需要先手动开通服务。开通时会看到免费版和按量付费的选项我建议测试阶段直接开免费版等验证完到达率和业务场景后再决定要不要升付费。开通后系统会为这个 App 生成一组推送专属的AppKey、AppSecret。注意它跟 DCloud AppID 不是一个概念AppID 是应用在 DCloud 的身份AppKey/AppSecret 是服务端调用推送 API 的凭证。生产中 AppSecret 只能放后端绝不能写进前端代码或打包进应用否则任何人都能伪造你的推送。开通完成后记得把AppKey和AppSecret存到后端的配置中心或环境变量里。我习惯同时建一个专门存推送凭证的表每个环境一套避免测试环境把消息推到生产设备上。2.3 iOS 推送证书容易漏掉的必要项如果你要接 iOS 端DCloud 控制台的 uni-push 配置里还有一处独立设置上传 iOS 推送证书或 .p8 密钥。这个文件要去苹果开发者后台生成对应你的 Bundle ID开通 Push Notifications 能力后导出。有些教程把 iOS 证书放在“厂商通道”章节里讲容易误导人。iOS 没有像 Android 那样的多个厂商后台可选它就是 APNs 一个通道在 UniPush 控制台把证书填好即可。证书有两类开发证书.p12和发布证书.p12千万别传反。我踩过的坑是用开发证书打包 TestFlight 包结果 AppStore 版永远收不到通知因为发布环境的推送走的是另一份证书。上传后控制台一般会显示证书有效期。证书过期是一个非常“安静”的故障后台消息显示成功iPhone 就是不响。运维上最好提前一个月在日历里标记证书到期提醒。3. 厂商推送通道的申请与回填细节3.1 华为通道AppID、AppSecret 与证书指纹华为离线通道是安卓版推送效果好坏的分水岭。登录华为开发者平台创建一个移动应用开通推送服务之后能在应用信息里拿到AppID和AppSecret。同时还要配置 SHA-256 证书指纹这个指纹必须和你最终打包用的证书一致。我之前调试时图省事先在华为后台填了 debug 证书的指纹HBuilderX 里用发行证书打了一个 release 包结果在线推送一切正常一杀后台就彻底沉默了。查到最后发现是华为推送服务校验证书指纹失败直接拒绝了离线消息。把指纹改成正式证书后问题立刻消失。Android 打包证书指纹的生成方式不复杂但不同证书工具的输出格式不一样。无论用 keytool 还是第三方工具拿到指纹后先把冒号去掉再填华为后台通常要求不带分隔符的大写十六进制字符串。这一步错了基本不会有报错提示属于“谁都看不出问题但就是到不了”的典型类型。3.2 小米、OPPO、vivo 的差异处理国内用户量大的主流机型基本被几大厂商覆盖配置参数各不一样。我把常见厂商必需项整理成了一个对照表操作时对着看。厂商必填参数特殊要求华为AppID、AppSecretSHA-256 证书指纹包名严格匹配小米AppID、AppKey、AppSecret需要配置消息回执否则后台显示到达但没回执OPPOAppKey、AppSecret、MasterSecret通知渠道、角标权限另设vivoAppID、AppKey、AppSecret推送服务开关需单独打开魅族AppID、AppKey要求权限声明完整小米的回执是可以独立配置的在小米开放平台申请“消息回执”权限拿到回执 URL填到小米推送服务里。有了回执服务端才能从“推送到达”和“用户看到”两个维度区分真实效果。不做回执不会让消息消失但你没法判断用户到底点没点。OPPO 的角标权限要单独申请否则通知栏消息到了应用角标数字不会变。vivo 没有类似角标限制但推送服务开关默认可能是关闭状态忘了打开的话所有 vivo 离线消息都会被静默丢弃。3.3 为什么离线推送“突然失效”渠道与开关很多人配置完厂商通道测试当天一切正常过了两天发现离线消息收不到了第一反应是后台参数被改了。其实大概率是 Android 8.0 之后的通知渠道在做怪。Android 8.0 引入了 Notification ChannelApp 必须在推送消息里声明一个渠道 ID用户也可以在这些渠道上手动关闭通知。如果消息没带渠道 ID或者渠道 ID 在系统里不存在系统可能直接丢弃。UniPush 控制台或服务端推送参数里要指定一个渠道 ID 和对应的渠道名称、描述。渠道名称会直接显示在系统设置里建议写成用户容易理解的文案比如“订单通知”而不是技术味十足的“msg_channel”。另一个很容易被忽视的开关是用户权限用户在系统设置里手动关掉“通知权限”后任何通道都无法突破。排查这类问题时先让用户在设置里确认 App 通知开关确实开着再去查厂商后台。4. manifest 配置与打包环节最容易翻车的地方4.1 在 manifest.json 中开启 Push 模块和 uni-push 模块打开 HBuilderX 的项目进入manifest.json切到“App 模块配置”。这里要勾上Push如果你用的是 UniPush 2.0通常还会看到uni-push相关选项一起勾上。单勾一个Push往往不够跑起来怎么都监听不到消息原因就是 2.0 的初始化入口没被编译进去。还需要在“App 常用其他设置”里确认 Android 包名和 iOS Bundle ID。有些项目是复制模板改的这里还留着别人家的包名打包时能成功安装但厂商平台校验身份时会发现“请求包名不属于这个应用”。如果你只是用 HBuilderX 自带的“标准基座”运行调试那恭喜你会踩一个大坑。标准基座只包含基础模块默认是不带 Push 模块的所以你必须先制作自定义调试基座在制作基座时勾选推送模块再用这个基座运行。否则你在onLaunch里调getPushClientId回调永远是 fail。4.2 通知图标、横幅样式与角标配置推送配置里不只有参数还有视觉相关的资源。通知栏小图标要准备一个纯白透明背景的 PNG尺寸不要太大系统会自己压缩。很多同学传一张带圆角的彩色图上去通知栏里显示成一个怪异的方块用户看到第一眼就想卸 App。横幅样式和桌面角标Android 厂商各有一套。小米、OPPO 对横幅样式有单独的控制字段服务端发通知时没有指定样式类型部分机型会按系统默认样式展示。角标数字则往往需要厂商通道单独授权OPPO 平台要求上传角标权限申请说明审核通过后才会开放。iOS 方面没有小图标的概念APNs 展示的是 App 本身的图标。角落标也需要在 Xcode 或原生工程里开启对应能力uni-app 云打包时不能直接改原生工程需要额外配置或使用原生插件扩展。4.3 云打包与离线打包的配置差异HBuilderX 云打包是最省事的菜单选择“发行 - 原生 App-云打包”上传证书、填包名、生成安装包。整个过程里要注意“打包类型”别选错测试用“自定义调试基座”真正验证离线推送要用“正式打包”。用测试基座打包部分厂商 SDK 调不起离线通道因为应用签名和厂商后台登记的不一致。离线打包的话等于你自己维护一个原生工程。这种情况下除了 manifest 里要配置原生端的 AndroidManifest.xml 里还得手动声明厂商推送服务、接收器、权限。少了任何一项SDK 初始化时可能不报错但推送就是静默失败。我见过最隐蔽的一次事故原生工程里build.gradle引用了多个厂商 SDK其中两个依赖版本冲突导致初始化链路中断日志里全是一些无关的 warning。所以我的明确建议是个人项目或小团队直接用云打包把精力放在业务逻辑上只有当你确实需要自制原生插件或深度定制推送行为时再碰离线打包。5. 客户端接入从获取 ClientID 到前后台消息分派5.1 获取 ClientID时机和生命周期问题UniPush 2.0 的客户端接入逻辑很简单核心就是先拿到cid。把下面这段放到App.vue的onLaunch里// #ifdef APP-PLUS uni.getPushClientId({ success(res) { const cid res.cid console.log(推送 ClientID:, cid) // 上报到自己的服务端和用户账号绑定 uni.request({ url: https://api.example.com/user/bind-cid, method: POST, data: { cid } }) }, fail(err) { console.error(getPushClientId 失败, err.code, err.message) // 简单延时重试不要死循环 setTimeout(() this.getCid(), 3000) } }) // #endif调用时机越早越好最好放在onLaunch。因为cid是一台设备在推送系统里的“门牌号”服务端要定向推送必须先知道这个门牌号并把门牌号和用户账号做绑定。这里有个生命周期问题cid在应用覆盖安装、卸载重装后可能变化。也就是说不能把它当成永久设备 ID 硬编码必须每次都重新获取并上报。我做用户画像时遇到过一个情况同一个人换了台新手机服务端库里还留着旧手机的cid业务侧就往旧cid发消息结果自然没到达。处理办法是客户端上报时带上用户 ID服务端做唯一约束保证一个账号始终只对应最新的一批cid。5.2 监听在线透传与通知栏消息拿到cid后第二步是注册消息监听uni.onPushMessage((res) { console.log(onPushMessage:, JSON.stringify(res)) // 常见字段: type、payload、title、content })res.type在不同场景下取值不同App 在运行状态下收到操作系统通知栏展示出来通常能收到一次回调用户点击通知栏消息进入 App又会触发一次带 payload 的点击事件。把这两条事件理清楚很重要因为你的业务跳转就靠点击事件里的payload。还要提防重复处理。有的开发者把跳转逻辑直接写在监听回调里用户点一次通知回调执行两遍页面就被重复打开。稳妥做法是回调里先解析payload生成一个事件标记页面侧判断是否已经处理过再跳转。消息处理的核心原则是通知展示归系统业务响应归代码。系统负责把通知栏展示出来你的代码只负责用户点击之后该往哪个页面带什么参数。5.3 App 被杀死后点击通知栏的冷启动传参最复杂的场景是 App 进程被杀掉用户直接点通知栏消息把 App 拉起来。这种冷启动状态下onPushMessage的点击回调可能触发得很早首屏页面还没准备好跳转参数一赋值就被后续页面生命周期覆盖。我的做法是把参数先缓存到全局再让页面主动去取// App.vue onLaunch 里 uni.onPushMessage((res) { if (res.type click) { try { const payload typeof res.payload string ? JSON.parse(res.payload) : (res.payload || {}) uni.$vm.$globalData.pushPayload payload } catch (e) { uni.$vm.$globalData.pushPayload null } } }) // 首屏页的 onLoad const payload uni.$vm.$globalData.pushPayload if (payload payload.page) { uni.navigateTo({ url: payload.page }) }这种旁路缓存虽然土但非常可靠。后续如果你接了更复杂的路由体系可以把payload交给路由组件统一分发避免页面和推送逻辑互相纠缠。还有一个小技巧在处理点击跳转时页面路径尽量用相对路径并且确认这个路径在pages.json里注册过。我接过一个需求后端配置的跳转地址是/pages/order/detail结果开发环境正常一测试就白屏最后发现是路径前多了个反斜杠导致页面没注册成功。6. 服务端推送接口调用与全链路排错6.1 推送 API 的签名与鉴权逻辑服务端调 UniPush 推送接口先要明白鉴权流程用AppKey、AppSecret加当前毫秒时间戳拼出一个签名串算法是 SHA256(AppKey timestamp AppSecret)。签名串和 timestamp 一起发过去换 token后面真正的推送请求带上这个 token。Node.js 里算签名是这样const crypto require(crypto) function buildSign(appkey, appsecret) { const timestamp Date.now() // 注意必须是毫秒 const raw ${appkey}${timestamp}${appsecret} const sign crypto .createHash(sha256) .update(raw) .digest(hex) return { sign, timestamp } }常见的 401 错误九成出在时间戳单位或签名拼接顺序上。Date.now()得到的是毫秒别用什么秒级时间戳签名算法会直接验证失败。另外AppSecret因为密钥长度不同拼接时要注意不要带空格和换行。6.2 一个可直接跑通的 Node.js 发送示例换到 token 后我会用一个封装函数把单推请求发出去。下面这段是简化但能跑的版本const url https://推送接口域名/v2/{appId}/push/single/cid const body { request_id: crypto.randomUUID(), audience: { cid: [目标设备的cid] }, push_message: { notification: { title: 订单已发货, body: 点击查看物流信息, click_type: startapp }, transmission: { transmission_type: 1, transmission_content: JSON.stringify({ page: /pages/order/detail, orderId: 20240001 }) } } } fetch(url, { method: POST, headers: { Content-Type: application/json, token: accessToken }, body: JSON.stringify(body) })注意request_id每次推送必须唯一。用 UUID 或数据库自增主键都行但绝对不要在重试时复用同一个 ID否则服务端可能判定成重复请求。push_message里notification是系统通知栏展示的内容transmission是透传给客户端的自定义数据。很多人在开发阶段犯的一个错是把完整后端逻辑写在云函数或定时任务里本地没有现成推送环境时没法联调。我习惯先在本地写好一个独立脚本用真实测试设备的cid跑一遍确认返回成功再迁到线上服务。6.3 从推送记录看问题出在前端、厂商还是后端推送失败时先不要怀疑人生按这张表逐项排查。现象最可能的原因在线收不到透传manifest 没勾 Push 模块或用标准基座调试导致接口未注册离线收不到通知厂商后台参数不匹配、包名不一致、证书指纹错误点击通知栏没跳转payload解析异常或冷启动时序导致参数丢失接口返回 401签名串顺序错、timestamp 用了秒、AppSecret 带多余字符接口返回 404cid不属于当前 AppID或设备已卸载但服务端还在发UniPush 控制台的消息列表是最直接的证据来源。服务端返回的成功只代表“推送请求已接受”不代表设备已经收到控制台里的“任务ID”“到达数”“点击数”才是真实结果。某开发者曾经给我看过一个案例后台显示“发送成功”但到达数是 0。最后发现是因为他用了另一台测试机的cid发起单推那台手机根本没安装这个正式包。6.4 频率限制、静默通知与定时推送的注意点厂商通道对推送频率有隐形约束。短时间内给同一台设备发大量通知部分厂商会判定为骚扰直接降级或封禁推送能力。运营活动里“轰炸式”群发最容易踩这条线。我的建议是严格控制单用户日消息条数重要消息走通知栏普通消息走透传不要一上来就把通知权限用尽。静默通知也是一个需要谨慎的功能。静默通知指的是不发任何展示内容只把数据悄悄送给 App很多 App 用它做后台预热。厂商系统对静默通知同样有限流用得太猛通道可能会被系统冻结导致后续所有正常通知都“失声”。我在项目里只用静默通知做紧急配置文件同步量级非常低。定时推送如果由前端写定时器处理App 一死就全断。正确姿势是服务端用任务队列在指定时间调推送接口。如果只需要固定场景的定时推送UniPush 控制台也提供定时任务入口不写代码也能配。最后分享一套验收顺序整个流程走完之后我强烈建议按“在线透传 → 离线通知 → 点击跳转 → 服务端联调”四步做验收。第一次先跑通在线透传确认cid能拿到、监听能触发然后装一个正式包杀进程测离线通知再核对点击事件里的payload跳转最后才把服务端接进来用真实业务消息做全链路验证。这个顺序看起来多了一步实际上能帮你省掉大量“查不出原因”的时间。每一层功能单独测过出了问题你一眼就能定位是哪一层的锅。配置这事看着繁琐但基本原则就一条让每一层都拿着正确的参数去跟下一层对话。参数对齐了UniPush 的配置在你手里自然就是“有手就行”。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑