登录
  • 人们都希望被别人需要 却往往事与愿违
  • 如果政府不能解决问题, 那它本身就成为问题!@里根 (美国前总统)

初探Stripe与Telegram Bot Payments API

编程 Benny小土豆 211次浏览 4519字 1个评论
文章目录[显示]

前言

4个月了,朕又出现了!刁民没能害得了武功高强的朕

Stripe是一个用于全球收钱的在线服务,支持很多种货币,哪怕你人在美国,收人民币也行,Stripe会自动帮你转成账户对应的货币。Stripe支持的支付方式包括银行卡,Apple Pay,Google Pay甚至是国内非常流行的支付宝和微信。

当你有了Stripe账户之后,无代码的情况下可以弄一个收款链接或者二维码,用户通过他们的本地支付方式就可以给你塞钱了。比如说下图这里,用户就可以用支付宝来给我打钱。

初探Stripe与Telegram Bot Payments API

集成Stripe

无代码的方式显然是不够的。很多情况下我们出售服务,或者说是软件授权,都需要自动化进行的。此时我们就可以利用Stripe的API了。想要利用这个API,主要就是两步:

  1. 创建PaymentIntent,主要就是定义了支持什么支付方式,想要收多少钱,想要什么币种
  2. 用户付款之后处理回调,比如说给用户发KEY啦之类的

我们以做一个用户任意捐款的页面为例(当然这个可以用Stripe的无代码,只是以此来作为例子),页面大概是这样子的

初探Stripe与Telegram Bot Payments API

创建PaymentIntent

很丑有没有。用户输入一个金额,提交表单之后,后端需要请求创建Payment Indent,大概是这样的:

 

import stripe

stripe.api_key =xxx

@app.route('/checkout', methods=['POST'])
def checkout():
    method = request.form['method']
    # unit is 分
    amount = int(float(request.form['amount']) * 100)
    # create payment intent
    logging.info("method: %s, amount: %s", method, amount)
    intent = stripe.PaymentIntent.create(payment_method_types=[method], amount=amount, currency="cny")
    secret = intent.client_secret
    return render_template('checkout.html', pk=pk, secret=secret, method=method)

有几点需要注意的:

  1. method是付款方式,具体会受到国家地区和货币的限制
  2. amount是收多少钱,也就是用户在输入框里输入的,需要注意是会变成最小货币单位。对于人民币来说,最小的货币单位是分,也就是说收人民币12.34元,这个amount应该是1234;对于日元这种最小单位就是元的货币(零位十进制货币),收500日元那么就写500即可。
  3. pk是Stripe的API的public key,其实是可以公开的。写在前端的代码里是没问题的
  4. client_secret 对于每一个付款请求都是唯一的

发起请求

前端可以这么写,很简单,总之就是要让用户进入付款页面

const stripe = Stripe(pk);
error = stripe.confirmAlipayPayment(clientSecret, {
    // Return URL where the customer should be redirected after the authorization
    return_url: `${window.location.origin}/callback`,
});

测试模式下,用户会进入这样的页面

初探Stripe与Telegram Bot Payments API

真实模式下是这样的

初探Stripe与Telegram Bot Payments API

处理回调

用户付款,成功或者失败之后,会返回return url,我们通过URL就可以知道付款是否成功,当然通过API或者webhook也是可以的。

初探Stripe与Telegram Bot Payments API

此时在Stripe的网页上就应该可以看到付款成功了

初探Stripe与Telegram Bot Payments API

基本上简单来说就是这样的😂微信也差不多,只不过微信模式下stripe.js 会直接嵌入一个微信的二维码,然后需要用webhook或者API去验证用户是否已经付款,不能依赖callback url啦。完整代码可以看最后gist

Stripe 费率

在上面的那个Stripe的页面,能发现Stripe抽了不少钱,具体费率每个国家、每种支付方式都不一样。比如如果是加拿大,用支付宝支付,那么费率是2.9% + C$0.30,如果需要货币转换,有些国家也还要收钱的。具体信息可以看这里 https://stripe.com/zh-cn-ca/pricing/local-payment-methods,把ca(加拿大)替换成你的国家代码就有啦。

Telegram Bot Payment

Telegram很早之前也给bot提供了骗钱的功能,支持的收款服务商包括Stripe之类的。想要用Payment API,先要去和Bot Father申请,选择 Bot Settings-Payments,然后选择对应的付款提供商,比如Stripe,之后会被重定向到对应的bot,然后选择测试还是生产模式,做一下oauth就可以拿到一个token了

初探Stripe与Telegram Bot Payments API

测试付款的时候可以用stripe的测试模式,有很多卡号可以模拟各种情况,成功失败都有,比如4242 4242 4242 4242就是可以用的测试卡,完整列表可以看这里

一些Bot API wrapper,比如pytelegrambotapi已经有了很简单易懂的例子。这里我用的pyrogram(1.x)来做例子说明怎么生成、验证付款。

生成invoice

需要使用raw_types

from pyrogram.raw import types as raw_types
raw_types.invoice.Invoice(currency="USD", prices=[raw_types.LabeledPrice(label="price", amount=amount)])

其中prices接受的参数是一个list,意味着这里可以有多项,比如说商品价格,税费,折扣,等等。amount同样遵循上面的最小货币单位原则,要收11.3美元,那么就要写1130

这里Invoice支持很多额外参数,比如email_requestedname_requestedsuggested_tip_amounts等等,自行发挥吧

生成InputMediaInvoice

raw_types.input_media_invoice.InputMediaInvoice(
    invoice=(
        raw_types.invoice.Invoice(currency="USD", prices=[raw_types.LabeledPrice(label="price", amount=amount)])),
    title=title,
    description=description,
    provider=PROVIDER_TOKEN,
    provider_data=raw_types.DataJSON(data=<strong>"{}"</strong>),
    payload=payload,
)

  • PROVIDER_TOKEN是在Bot Father中申请的那个token,不是bot token。
  • provider_data 是收款商需要要求的信息,比如印度Stripe强制要求姓名地址,那么就应该写在这里,否则Stripe会拒付。我这边没有要求,所以直接空json字符串就好
  • Payload是我们自定义的信息,内部使用,比如用于区分是什么的付款

如果要inline模式,那么就要用InputBotInlineMessageMediaInvoice

选择Forwarding Behavior

当invoice被转发了之后,我们可以选择有什么样的行为,一种是会可以继续付款,另外一种是通过deep linking跳转到机器人。由InputMediaInvoice的参数start_param控制的。直接忽略这个参数,意味着转发的消息也可以付款,并且付款后按钮不会变成receipt

初探Stripe与Telegram Bot Payments API

发送invoice

SendMedia就可以了

peer = raw_types.InputPeerUser(user_id=chat_id, access_hash=0)

app.send(
    functions.messages.SendMedia(
        peer=peer,
        media=inputinvoice,
        random_id=app.rnd_id(),
        message="pay for it!",
    )
)

Pre-Checkout

用户在付款之后,Telegram这边会给bot发一个pre_checkout_query的更新,要求bot做一个precheckout的检查,比如说检查是否还有货啦这种。Bot需要在10秒之内用answerPreCheckoutQuery应答,否则就会出错。

Pyrogram这边我没找到合适的事件监听,可能是版本太老了,所以只能这样了:

@app.on_raw_update()
def raw_update(client: "Client", update, users, chats):
    if update.QUALNAME == 'types.UpdateBotPrecheckoutQuery':
        client.send(
            functions.messages.SetBotPrecheckoutResults(
            query_id=update.query_id,
            success=True
            )
        )
  • success表示pre checkout状态,如果是false,需要提供一个error

checkout

Bot确认之后,Telegram就会请求Stripe完成付款请求。之后telegram会发一个successful_payment的service message,bot看到之后确认就可以了。

我们可以通过raw update的 types.MessageActionPaymentSentMe 来确认

打开你的Stripe,切换到测试模式,可以看到已经有“进账”啦,甚至还可以提现到银行卡😂

初探Stripe与Telegram Bot Payments API

值得思考的问题

既然Stripe能支持支付宝微信付款,并且可以提现到银行卡,那么相比较银行汇款,哪个更划算呢?

已知条件如下:

  1. 招商银行通信费150元/笔,手续费为汇款金额的0.1%,最低100最高1000,不考虑境外银行的收费
  2. Stripe手续费 2.9%,无提现、货币转换费
  3. 均不考虑不同平台银行的汇率差异

欢迎大家给我打钱!

参考这里或者直接Stripe吧!

初探Stripe与Telegram Bot Payments API

 

 

 

参考

https://core.telegram.org/bots/payments#step-by-step-process

https://stripe.com/docs/payments/alipay/accept-a-payment?locale=zh-CN

https://stripe.com/docs/payments/wechat-pay/accept-a-payment

https://stripe.com/zh-cn-ca/pricing/local-payment-methods

https://gist.github.com/BennyThink/d3a0de89d21ccb955636e0ffba0f9ea1

 


文章版权归原作者所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明原作者和本文原始地址:
https://dmesg.app/stripe-telegram.html
喜欢 (3)
分享:-)
Benny小土豆
关于作者:
If you have any further questions, feel free to contact me in English or Chinese.
发表我的评论(代码和日志请使用Pastebin或Gist)
取消评论

                     

去你妹的实名制!

  • 昵称 (必填)
  • 邮箱 (必填,不要邮件提醒可以随便写)
  • 网址 (选填)
(1)个小伙伴在吐槽
  1. 尊敬的独立博客作者您好,您的博客已经被收录在博客乌托邦,博客乌托邦是一个中文独立博客文章聚合搜索平台,如有疑问可前往https://utopiablog.cn 留言,祝您新春愉快!
    yearn192023-01-19 12:55 回复