Telegram 支付机器人开发小记
· 阅读需 7 分钟

随着 Telegram 迈向区块链&小程序时代,Telegram 内部已经与 TON 钱包做了集成,并为了应对 Apple 和 Google 关于数字产品销售的政策监管需要上线了 Telegram Stars 作为支付方式。依托 Telegram 生态的数亿用户,存在着大量机遇,并为区块链走向 Mass Adoption 铺设了一条新的高速公路。本文基于 grammY 框架,分享支付机器人开发过程中的心得,助你成功。
支付机器人
初始化
在使用测试环境进行机器人开发时,创建 Bot 实例,需要将environment指定为test,否则将会产生401 Unauthorized错误。
另外如 果当前的网络环境需要使用科学上网才能访问 Telegram,还需要配置baseFetchConfig.agent为你的代理地址。
Bot Init
new Bot(process.env.BOT_TOKEN!, {
client: {
baseFetchConfig: {
agent: isDevEnv ? new HttpsProxyAgent('http://127.0.0.1:7890') : null
},
environment: isDevEnv ? 'test' : 'prod'
}
})
Stars 支付流程
Pay With Stars
// 1. 调用 `sendInvoice` 发送发票,currency 参数指定为`XTR`
ctx.api.sendInvoice(ctx.chat!.id, 'Title', 'Description', `payload`, 'XTR', [{ label: 'Label', amount: 1 }])
// 2. 检查发票,等待字段 `pre_checkout_query` 的更新
bot.on('pre_checkout_query', (ctx) => {
// 3. 通过 `answerPreCheckoutQuery` 批准或取消订单
ctx.answerPreCheckoutQuery(true)
// ctx.answerPreCheckoutQuery(false, {
// error_message: 'An unexpected error occurred. Please try again later.'
// })
})
// 4. 等待字段 `successful_payment` 的更新
bot.on(':successful_payment', ctx => {
// 5. 支付成功回调,存储成功支付的 `telegram_payment_charge_id`(未来可能需要用它来发起退款)
console.log(ctx.message?.successful_payment.telegram_payment_charge_id)
// 6. 向用户交付其所购买的商品和服务,业务逻辑...
ctx.reply('payment-success').catch(console.error)
})
TON 支付流程
- 生成指定钱包的支付链接
function generatePaymentLink(
toWallet: string,
amount: number | string | bigint,
comment: string,
app: "tonhub" | "tonkeeper"
) {
if (app === "tonhub") {
return `https://tonhub.com/transfer/${toWallet}?amount=${toNano(
amount
)}&text=${comment}`;
}
return `https://app.tonkeeper.com/transfer/${toWallet}?amount=${toNano(
amount
)}&text=${comment}`;
}
- 将生成的链接以菜单形式返回给用户,并提供
check_transaction事件用于检查交易
const tonhubPaymentLink = generatePaymentLink(process.env.OWNER_WALLET!, amount, comment, 'tonhub')
const tonkeeperPaymentLink = generatePaymentLink(process.env.OWNER_WALLET!, amount, comment, 'tonkeeper')
const menu = new InlineKeyboard()
.url("Click to pay in TonHub", tonhubPaymentLink)
.row()
.url("Click to pay in TonKeeper", tonkeeperPaymentLink)
.row()
.text(`I sent ${amount} TON`, "check_transaction");
await ctx.reply(
`Tips`,
{ reply_markup: menu, parse_mode: "HTML" }
);
