摘要:本文介绍一种基于 Android AccessibilityService 通知栏监听的个人收款回调方案,分析其技术原理、系统架构与实现细节,并提供完整的部署教程。该方案基于开源项目 v 免签重新开发,适用于个人开发者的收款场景学习与参考,监控端已兼容到Android 16。
MQPay - 个人收款系统 | 智能通知栏监控
https://mqpay.prod.plpl.host/
一、背景:个人收款的技术困境
在国内支付生态中,个人开发者若想接入支付功能,通常面临以下问题:
-
官方商户接口门槛高:微信支付、支付宝商户入驻需提供营业执照等资质,个人开发者难以申请。
-
第三方聚合支付成本高:手续费通常在 0.6%~2% 之间,且资金需经过第三方平台。
-
自建方案复杂:需要对接官方 SDK、处理证书、签名验证等,学习成本较高。
开源社区中,v 免签 项目提出了一种巧妙的替代方案:通过监听手机通知栏的收款推送消息,自动完成订单回调。本文将深入分析这一技术方案的原理与实现。
二、技术原理分析
2.1 核心思路
该方案的核心逻辑是:
用户扫码支付 → 微信/支付宝发送通知栏推送 → Android 监控端捕获通知
→ 解析金额与订单信息 → HTTP 回调至服务端 → 更新订单状态
整个流程不依赖官方支付 API,而是利用 Android 系统的通知栏推送机制作为信息传递通道。
2.2 关键技术:Android AccessibilityService
AccessibilityService 是 Android 系统提供的辅助功能服务,设计初衷是帮助视障用户操作手机。其核心能力包括:
-
监听系统 UI 事件(如窗口变化、通知栏更新)
-
读取界面节点信息(文本内容、控件属性)
-
模拟用户点击操作
在本方案中,主要利用其通知栏监听能力:
// AccessibilityService 核心代码示意
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
String packageName = sbn.getPackageName();
String tickerText = sbn.getNotification().tickerText.toString();
// 匹配微信/支付宝的通知
if ("com.tencent.mm".equals(packageName)) {
// 解析微信支付通知文本
parseWeChatNotification(tickerText);
} else if ("com.eg.android.AlipayGphone".equals(packageName)) {
// 解析支付宝通知文本
parseAlipayNotification(tickerText);
}
}
2.3 通知文本解析
微信和支付宝的收款通知通常包含以下信息:
| 通知来源 | 典型通知文本 |
|---|---|
| 微信支付 | 微信支付收款通知 + ¥128.00 刚刚 |
| 支付宝 | 支付宝到账通知 + ¥256.50 1分钟前 |
监控端通过正则表达式提取金额、时间等信息:
// 金额提取正则示例
Pattern pattern = Pattern.compile("([¥¥])(\\d+\\.?\\d*)");
Matcher matcher = pattern.matcher(notificationText);
if (matcher.find()) {
String amount = matcher.group(2); // 提取金额
}
三、系统架构设计
3.1 整体架构
┌─────────────────────────────────────────────────────────┐
│ 用户层 │
│ 用户扫码 → 微信/支付宝 APP │
└─────────────────────────┬───────────────────────────────┘
│
↓ 生成收款通知(系统通知栏推送)
┌─────────────────────────────────────────────────────────┐
│ 监控端层 │
│ ┌─────────────┐ AccessibilityService 监听通知栏 │
│ │ Android App │ 解析金额/时间/来源 │
│ │ (Java/Kotlin)│ HTTP POST 上报至服务端 │
│ └──────┬──────┘ │
└─────────┼───────────────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────┐
│ 服务端层 │
│ ┌─────────────┐ SpringBoot 2.1.1 + MySQL │
│ │ MQPay 服务端 │ 订单管理 / 回调处理 / 签名校验 │
│ │ (Java) │ RESTful API 供业务系统调用 │
│ └──────┬──────┘ │
└─────────┼───────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 业务系统层 │
│ 接收回调 → 更新订单状态 → 完成交易 │
└─────────────────────────────────────────────────────────┘
3.2 服务端技术栈
表格
| 组件 | 技术选型 | 说明 |
|---|---|---|
| 框架 | SpringBoot 2.1.1 | 轻量级 Web 框架 |
| 数据库 | MySQL | 零配置部署 |
| 安全 | MD5 签名校验 | 通讯密钥 + 参数排序签名 |
| 部署 | 可执行 WAR 包 | java -jar 直接运行 |
3.3 数据流时序图
用户 微信/支付宝 监控端APP MQPay服务端 业务系统
│ │ │ │ │
│──扫码支付────→│ │ │ │
│ │──通知栏推送─→│ │ │
│ │ │──解析通知─────→│ │
│ │ │ │──匹配订单────│
│ │ │ │ │
│ │ │ │──回调通知───→│
│ │ │ │ │──更新状态
│ │ │ │←──响应───────│
│ │ │←──上报结果─────│ │
│ │ │ │ │
四、部署教程
4.1 环境要求
-
服务端:JDK 1.8+,建议 Linux 服务器(需公网 IP)
-
监控端:Android 5.0+ 真机或模拟器(建议使用真机)
-
网络:服务端需可被监控端访问(建议部署在公网)
4.2 服务端部署
步骤 1:下载 WAR 包
从项目 releases 页面下载编译好的 v.war。
步骤 2:启动服务
# 默认端口 8080
java -jar v.war
# 自定义端口
java -jar v.war --server.port=9090
步骤 3:初始化配置
-
访问
http://localhost:8080 -
使用默认账号登录(账号:
admin,密钥:admin) -
进入系统设置,修改:
-
登录密码
-
通讯密钥(用于回调签名校验)
-
回调地址(业务系统接收支付通知的 URL)
-
4.3 监控端配置
步骤 1:安装 APK
在 Android 设备上安装监控端应用。
步骤 2:配置服务端
通过扫码或手动输入服务端地址完成配置。
步骤 3:开启辅助功能
设置 → 辅助功能 → 已安装的服务 → MQPay监控端 → 开启
步骤 4:通知权限设置
-
微信:设置 → 新消息通知 → 开启"通知显示消息详情"
-
支付宝:设置 → 通用 → 新消息通知 → 开启通知栏显示
-
系统:确保微信、支付宝、监控端均允许发送通知
4.4 后台保活配置(重要)
监控端被杀后台会导致收款通知丢失,需进行以下设置:
| 设置项 | 路径 |
|---|---|
| 内存白名单 | 手机管家/安全中心 → 白名单 → 添加监控端、微信、支付宝 |
| 自启动权限 | 设置 → 应用管理 → 自启动 → 允许 MQPay |
| 省电豁免 | 电池 → 省电优化 → MQPay 设为"不优化" |
| 后台锁定 | 多任务界面 → 下拉 MQPay 卡片加锁 |
五、API 接口文档
5.1 创建订单
POST /api/order/create
Content-Type: application/x-www-form-urlencoded
payId=ORDER_001&price=10.00¶m=user_123¬ifyUrl=http://example.com/callback
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
payId | String | 是 | 商户订单号,需唯一 |
price | String | 是 | 订单金额,单位元 |
param | String | 否 | 自定义参数,回调原样返回 |
notifyUrl | String | 否 | 异步回调地址 |
响应示例:
{
"code": 1,
"msg": "success",
"data": {
"orderId": "MQ20260503123456",
"payUrl": "weixin://wxpay/...",
"price": "10.00"
}
}
5.2 回调通知
支付成功后,服务端向 notifyUrl 发送 POST 请求:
POST http://example.com/callback
Content-Type: application/x-www-form-urlencoded
payId=ORDER_001¶m=user_123&price=10.00&reallyPrice=10.00&sign=xxx
签名校验算法:
// 1. 将参数按 key 升序排序
// 2. 拼接为 key1=value1&key2=value2... 格式
// 3. 末尾追加通讯密钥
// 4. MD5 加密,与 sign 比对
String source = "param=user_123&payId=ORDER_001&price=10.00&reallyPrice=10.00你的通讯密钥";
String sign = MD5(source).toLowerCase();
5.3 查询订单
POST /api/order/query
Content-Type: application/x-www-form-urlencoded
orderId=MQ20260503123456
六、技术难点与解决方案
6.1 通知栏文本解析的稳定性
问题:微信/支付宝可能在不同版本中更改通知文本格式。
方案:
-
使用模糊匹配正则,兼容多种格式
-
监控端支持配置自定义解析规则
-
提供通知历史记录功能,便于调试
6.2 金额匹配精度
问题:用户实际支付金额可能与订单金额不一致(如红包抵扣)。
方案:
-
服务端配置金额容差范围
-
支持精确匹配和模糊匹配两种模式
-
回调中包含
reallyPrice(实际到账金额)供业务系统判断
6.3 后台保活
问题:国产 ROM aggressively 杀后台。
方案:
-
提供完整的保活配置文档
-
建议用户使用备用机或模拟器长期挂机
七、适用场景与局限性
适用场景
-
个人开发者学习支付回调机制
-
小规模收款场景的技术验证
-
需要自建收款系统的教学演示
局限性
| 局限 | 说明 |
|---|---|
| 依赖通知栏 | 若通知被系统过滤或格式变更,可能解析失败 |
| 单点瓶颈 | 单台监控端处理能力有限,不适合高并发 |
| 设备依赖 | 需保持 Android 设备在线,存在单点故障风险 |
| 合规风险 | 个人收款码用于经营性收款可能违反平台规则 |
八、与原版 v 免签的对比
| 维度 | v 免签(原版) | MQPay(重构版) |
|---|---|---|
| 监控端兼容性 | 部分 Android 7.0+ 闪退 | 重构监控端,兼容性优化 |
| 后台保活 | 基础提示 | 完整配置指南与检测工具 |
| 部署文档 | 较简略 | 更详细的步骤说明 |
九、总结
本文介绍了一种基于 Android 通知栏监听的个人收款回调技术方案,分析了其技术原理、架构设计与实现细节。该方案巧妙地利用系统级辅助功能绕过官方 API 限制,为个人开发者提供了一种低成本的收款技术参考。
需要强调的是,该方案仅适用于技术学习和小规模场景验证,生产环境建议申请官方商户接口以确保合规与稳定。
参考链接:
-
项目官网:https://mqpay.prod.plpl.host/
https://mqpay.prod.plpl.host/ -
v 免签原版:https://github.com/szvone/Vmqphp
https://github.com/szvone/Vmqphp -
Android AccessibilityService 官方文档:https://developer.android.com/reference/android/accessibilityservice/AccessibilityService
https://developer.android.com/reference/android/accessibilityservice/AccessibilityService
本文仅供技术交流,请遵守相关法律法规。
438

被折叠的 条评论
为什么被折叠?



