
许多 VPN 服务通过 Telegram 销售:用户本来就在聊天里,购买也应该在那里完成。本指南介绍如何在您的服务器上运行一个现成的机器人:用户选择套餐,用 TRC20、ERC20 或 BEP20 网络的 USDT 或其他币种付款,机器人在您的 Marzban、3x-ui 或 Remnawave 面板中创建或续期用户,并把订阅链接发到同一个聊天。无需自建钱包或区块链节点,资金直接进入您的 SnapEX Pay 商户余额。
销售流程
用户 → /start → 点击套餐
机器人 → SnapEX Pay:账单 → "Pay" 按钮
用户 → 在 SnapEX Pay 页面付款
SnapEX Pay → 签名 Webhook → 机器人
机器人 → 通过 API 查询账单 → paid?
机器人 → 面板:创建或续期用户
机器人 → 用户:订阅链接
/start以按钮形式显示您的套餐。每次点击都会创建一张 SnapEX Pay 账单,机器人回复一个 Pay(支付)按钮。- 用户在支付页面选择币种并付款。账单支付完成后,SnapEX Pay 向机器人发送签名 Webhook。
- 机器人校验签名,通过 SnapEX Pay API 查询账单,只有状态为
paid且账单属于机器人自己创建的订单时,才开通用户。
面板用户名为 tg<telegram_id>,因此每个 Telegram 账户正好对应一个 VPN 用户。
准备条件
- 从 @BotFather 获取的机器人令牌。
- Marzban、3x-ui(MHSanaei)或 Remnawave(2.x 或 3.x)面板的管理员权限。没有面板时,机器人只能收款(
PANEL_TYPE=none),访问权限由您自己发放。 - 装有 Docker Compose(或 Python 3.12)的服务器。
- 用于 Webhook 的公网 HTTPS 地址:SnapEX Pay 只向
https://地址发送 Webhook。 - SnapEX Pay 商户账户:在 pay.snapex.pro 注册。
机器人使用长轮询(long polling),所以 Telegram 不需要您的服务器开放端口——只需要 HTTPS 后面的 Webhook 端口可以访问。
第 1 步:下载机器人
下载压缩包 snapexpay-telegram-vpn-bot-1.1.0.zip(MIT 许可,免费),并创建配置文件:
curl -fsSLO https://pay.snapex.pro/downloads/telegram-vpn-bot/snapexpay-telegram-vpn-bot-1.1.0.zip
unzip snapexpay-telegram-vpn-bot-1.1.0.zip
cd snapexpay-telegram-vpn-bot-1.1.0
cp .env.example .env
所有配置都在 .env 中。把机器人令牌填入 TELEGRAM_BOT_TOKEN,店铺名称填入 SHOP_NAME——它会显示在 /start 消息和账单描述中。
第 2 步:获取 API 密钥
在 SnapEX Pay 商户后台打开 Developers 页面,生成 API 密钥。密钥只显示一次,请立即复制到 SNAPEX_API_KEY。后台生成的密钥自动拥有 Merchant API 的全部权限,包括机器人需要的 invoices.read 和 invoices.write。重新生成密钥会立即作废旧密钥,因此请同时更新 .env。
另外两个支付设置:
SNAPEX_FEE_ON:merchant(默认),用户正好支付套餐价格,手续费从您的收款中扣除;customer,手续费加在价格之上。详见:加密货币账单的手续费由谁支付。SNAPEX_EXPIRES_MINUTES:账单可支付的时长,默认 60 分钟(1 到 1440)。
第 3 步:设置套餐
套餐写在 PLANS 的一行中:id:days:price_usd:traffic_bytes,用逗号分隔。流量 0 字节表示不限流量。
PLANS=week:7:2.00:0,month:30:5.00:0,quarter:90:12.00:107374182400
这里 quarter 是 90 天、100 GiB 流量。id 会显示在按钮上("month — $5.00 / 30d"),所以请保持简短:拉丁字母、数字、_ 和 -。价格以 USD 计;账单最低金额为 0.50 USD。
每个订单都保存一份套餐副本,因此之后修改价格不会影响已支付的订单。
第 4 步:连接面板
设置 PANEL_TYPE 和面板的访问信息。
Marzban:PANEL_TYPE=marzban:
MARZBAN_URL、MARZBAN_USERNAME、MARZBAN_PASSWORD:面板地址和管理员登录信息(或在MARZBAN_TOKEN中填写现成的管理员令牌)。MARZBAN_SUB_URL:仅当 Marzban 返回相对链接/sub/<token>(XRAY_SUBSCRIPTION_URL_PREFIX为空)时需要:链接的公网基础地址。
3x-ui:PANEL_TYPE=3xui:
XUI_URL:面板地址,如果设置了 Web 基础路径,需包含该路径(https://xui.example.com:2053/secretpath)。XUI_USERNAME、XUI_PASSWORD:该账户必须关闭双因素认证。XUI_INBOUND_ID:新客户端加入的入站(vless、vmess、trojan 或 shadowsocks)。XUI_SUB_URL:订阅基础地址,例如https://xui.example.com:2096/sub。不填时机器人只发送subId。
Remnawave:PANEL_TYPE=remnawave:
REMNAWAVE_URL和REMNAWAVE_TOKEN:面板地址和 API Tokens 中的 API 令牌。REMNAWAVE_SQUAD_UUIDS:新用户所属的内部 squad,用逗号分隔。没有 squad 的新用户没有可用服务器。
第 5 步:在 HTTPS 后启动机器人
docker compose up -d --build
docker compose logs -f bot
机器人监听 8080 端口:/webhook 供 SnapEX Pay 使用,/health 用于健康检查。请把它放在带 TLS 的反向代理后面,例如 Caddy:
pay-bot.example.com {
reverse_proxy 127.0.0.1:8080
}
代理必须原样转发请求体——签名是基于原始请求体计算的。
第 6 步:配置 Webhook
在商户后台 Developers 页面填写 Webhook 地址 https://pay-bot.example.com/webhook 并保存。签名密钥 whsec_… 只在第一次保存后显示一次——请把它复制到 SNAPEX_WEBHOOK_SECRET 并重启机器人:docker compose up -d。
商户后台每个账户只有一个 Webhook 地址,所有事件都发送到这里。机器人只处理账单事件,其他事件仅确认接收。
机器人如何校验通知:
Webhook-Signature请求头:用您的密钥对{Webhook-Timestamp}.{原始请求体}计算 HMAC-SHA256;未签名或被篡改的请求返回401;Webhook-Timestamp与服务器时间相差不超过 5 分钟——请保持 NTP 开启;- 账单本身:用您的密钥通过 SnapEX Pay API 重新查询,只有状态为
paid时才开通用户。
如果此时面板或 SnapEX Pay API 不可用,机器人返回 502,SnapEX Pay 会重新投递(最多 5 次)。重复和并发的投递只会让一张账单开通一次。关于签名和重试的更多内容:加密货币支付 Webhook。
第 7 步:不用真实资金测试购买
- 设置
SNAPEX_ENVIRONMENT=test并重启:docker compose up -d。 - 用您自己的 Telegram 账户向机器人发送
/start并点击一个套餐。 - 点击 Pay。SnapEX Pay 页面会显示 Test 标记。任选币种和网络:页面显示测试地址,大约 10 秒后支付自动确认,无需转账。
- 机器人应发送 "Payment received"(已收到付款)和订阅链接,面板中应出现用户
tg<your telegram id>。如果没有,请查看docker compose logs -f bot以及 Developers 页面上的投递日志。 - 设置
SNAPEX_ENVIRONMENT=live并重启。
机器人处于 test 时,通过它购买的任何套餐都会在没有真实资金的情况下开通,所以请尽快完成测试。详见:如何不用真实资金测试加密货币支付。
用户看到什么
/start:您的店铺名称、一行关于使用 USDT(TRC20 / ERC20 / BEP20)或其他币种付款的说明,以及套餐按钮。- 点击后:套餐、天数、价格和账单编号,以及 "Pay $5.00 with crypto"(用加密货币支付 $5.00)按钮。
- SnapEX Pay 页面,可选择币种:TRC20、ERC20、BEP20 网络的 USDT,以及 SnapEX Pay 针对该账单金额提供的其他币种(共 50 多种)。
- 付款后:同一个聊天中收到 "Payment received"(已收到付款)和订阅链接。
PANEL_TYPE=none时,消息会说明管理员稍后发送访问权限。
机器人自身的消息为英文;只有店铺名称和套餐名称由您决定。
老用户用同一个 Telegram 账户付款时,其用户从当前到期时间起续期(如果已过期,则从现在起算);带流量限制的套餐会重新计算流量额度。详见:用加密货币支付 VPN 订阅续费。
如果用户支付的金额少于账单总额,用户不会被开通:机器人只为 paid 状态的账单开通访问权限。已收到的金额进入您的 SnapEX Pay 余额,差额由您与用户协商处理。少付的处理方式:用户付款不足怎么办。
常见问题排查
- 点击套餐后提示 "Payment is unavailable right now"(暂时无法支付)。 机器人无法创建账单:请检查
SNAPEX_API_KEY(密钥错误或已作废)和日志。 - Webhook 返回 401 "bad webhook signature"(Webhook 签名错误)。
SNAPEX_WEBHOOK_SECRET不匹配,或代理修改了请求体。也请检查服务器时间是否同步。 - 用户已付款但什么也没收到。 在日志中查找
provision failed。SnapEX Pay 会持续重新投递;面板恢复后,下一次投递会开通用户,您也可以在商户后台的日志中重新发送投递。 - Marzban 发送的链接没有主机名。 在 Marzban 中设置
XRAY_SUBSCRIPTION_URL_PREFIX,或在机器人中设置MARZBAN_SUB_URL。 - 3x-ui:提示 "login failed"(登录失败)。 检查
XUI_URL(含 Web 基础路径)和登录信息,并关闭该账户的双因素认证。 - Remnawave:用户已创建,但订阅为空。 在
REMNAWAVE_SQUAD_UUIDS中填写包含您节点的 squad。 - 运行了多个机器人副本。 每个
DATA_DIR只运行一个实例:防重复保护只在单个进程及其 SQLite 文件内有效。
费用
每笔支付 1%,无开户费,无月费。机器人免费。
机器人页面:Telegram VPN 机器人。想改用面板自带的商店销售?请看 Xboard 和 V2Board 接入加密货币支付。VPN 服务概览:VPN 加密货币支付。注册:pay.snapex.pro。