来源:https://jonno.nz/posts/built-an-sms-gateway-with-a-20-dollar-android-phone/
作者:John Gregoriadis
整理时间:2026-04-15
标签:#SMS网关 #Android #Twilio替代 #开源 #Webhook #RESTAPI #物联网
| 方案 | 成本 |
|---|---|
| Twilio | ~$0.05-0.06/条 |
| 月均1000条 | ~$50/月 |
对于 MVP 来说,这是笔”智商税”。
20美元安卓机 + 开源App = 无限免费短信
核心思路:
- 用一台廉价安卓机作为 SMS 网关
- 通过 REST API 控制收发短信
- 短信费用 = 手机套餐费( prepaid 卡可为零)
┌─────────────┐ REST API ┌─────────────┐
│ 安卓手机 │ ◄───────────────► │ 你的后端 │
│ SMS Gateway│ HTTP/Webhook │ (Next.js) │
│ App │ │ │
└─────────────┘ └─────────────┘
▲ │
│ 短信收发 │
└─────────────────────────────────┘
真实移动网络
| 项目 | 信息 |
|---|---|
| 开源地址 | github.com/capcom6/android-sms-gateway |
| Play Store | me.capcom.smsgateway |
| 协议 | 开源免费 |
| 特点 | 说明 |
|---|---|
| 网络 | 必须同一 WiFi |
| 依赖 | 无第三方服务器 |
| 延迟 | 更低(直连) |
| 复杂度 | 需处理 AP 隔离 |
你的后端 ──HTTP──► 安卓手机:8080 ──► 发送短信
配置步骤:
1. 开启 Local Server
2. 设置端口(默认8080)、用户名(≥3字符)、密码(≥8字符)
3. 记录手机 IP 地址
发送示例:
curl -X POST http://192.168.1.50:8080/message \
-u "admin:yourpassword" \
-H "Content-Type: application/json" \
-d '{
"textMessage": { "text": "Hello!" },
"phoneNumbers": ["+15551234567"]
}'
| 特点 | 说明 |
|---|---|
| 网络 | 任意位置都可访问 |
| 依赖 | Firebase Cloud Messaging |
| 延迟 | 略高(经中转) |
| 可靠性 | FCM+SSE+轮询三重保障 |
中转架构:
你的后端 ──HTTPS──► api.sms-gate.app ◄──Firebase◄── 安卓手机
发送示例:
curl -X POST https://api.sms-gate.app/3rdparty/v1/messages \
-u "YOUR_USERNAME:YOUR_PASSWORD" \
-H "Content-Type: application/json" \
-d '{
"textMessage": { "text": "Hello from the cloud!" },
"phoneNumbers": ["+15551234567"]
}'
| 事件 | 说明 |
|---|---|
sms:received |
收到短信 |
sms:sent |
发送成功 |
sms:delivered |
送达确认 |
sms:failed |
发送失败 |
system:ping |
心跳检测 |
{
"id": "Ey6ECgOkVVFjz3CL48B8C",
"webhookId": "LreFUt-Z3sSq0JufY9uWB",
"event": "sms:received",
"payload": {
"message": "Hello!",
"sender": "+15551234567",
"recipient": "+15559876543",
"receivedAt": "2026-04-01T12:41:59.000+00:00"
}
}
Webhook 使用 HMAC-SHA256 签名验证:
import crypto from 'crypto';
function verifyWebhook(
signingKey: string,
payload: string,
timestamp: string,
signature: string
): boolean {
const expected = crypto
.createHmac('sha256', signingKey)
.update(payload + timestamp)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(signature, 'hex')
);
}
| 参数 | 值 |
|---|---|
| 超时 | 30秒 |
| 首次重试 | 10秒后 |
| 策略 | 指数退避 |
| 最大重试 | 14次(约2天) |
// src/lib/sms/provider.ts
export interface InboundSms {
from: string;
body: string;
receivedAt?: Date;
}
export interface SmsProvider {
send(to: string, body: string): Promise<string>;
parseWebhook(req: Request): Promise<InboundSms | null>;
webhookResponse(replyText?: string): Response;
}
export async function getSmsProvider(): Promise<SmsProvider> {
const provider = process.env.SMS_PROVIDER || "sms-gate";
switch (provider) {
case "sms-gate": {
const { SmsGateProvider } = await import("./sms-gate");
return new SmsGateProvider();
}
case "console": {
const { ConsoleProvider } = await import("./console");
return new ConsoleProvider();
}
default:
throw new Error(`Unknown SMS provider: ${provider}`);
}
}
// src/app/api/sms/webhook/route.ts
export async function POST(req: NextRequest) {
const provider = await getSmsProvider();
const sms = await provider.parseWebhook(req);
if (!sms) {
return new Response("Bad request", { status: 400 });
}
const { from, body } = sms;
console.log(`[SMS from ${from}]: ${body}`);
// 回复短信
await provider.send(from, "Got it — we're on it!");
return provider.webhookResponse();
}
| 配置项 | 建议 |
|---|---|
| 设备 | 专用廉价安卓机 |
| 供电 | 一直插着充电器 |
| 网络 | 稳定的 WiFi |
| 电池优化 | 必须关闭 |
| 自启动 | 开启 |
| SIM卡 | Prepaid 无限短信套餐 |
| 问题 | 解决方案 |
|---|---|
| AP隔离 | 关闭路由器”客户端隔离” |
| 后台被杀 | 关闭电池优化(dontkillmyapp.com) |
| 设备离线 | 注册 system:ping webhook 监控 |
| 方案 | 单条成本 | 月均1000条 |
|---|---|---|
| Twilio | ~$0.05 | ~$50 |
| 安卓SMS网关 | $0 | ~$8(套餐) |
节省:80%+
| 场景 | 说明 |
|---|---|
| MVP 阶段 | 节省 SMS 开销 |
| 通知系统 | 订单、验证码、提醒 |
| 双向通信 | 用户回复处理 |
| 物联网 | 设备短信控制 |
| 备用方案 | 主通道故障时降级 |
20美元安卓机 + SMS Gateway App = 零成本的无限短信网关,Webhook 实时接收 + REST API 发送,比 Twilio 节省80%成本。
本文由 AI 辅助整理,供技术学习参考。