Logo

dev-resources.site

for different kinds of informations.

How to Integrate Telegram Payments in a Django and React Mini App

Published at
11/14/2024
Categories
python
telegram
payment
Author
leen2233
Categories
3 categories in total
python
open
telegram
open
payment
open
Author
8 person written this
leen2233
open
How to Integrate Telegram Payments in a Django and React Mini App

Introduction

Integrating payments directly within a Telegram Mini App can transform user experience by making in-app transactions straightforward and secure. Imagine users who can pay for products or services without ever leaving the app—they simply click, pay, and continue using your app seamlessly. With Telegram’s Stars payment system, this integration has become even easier for developers and more convenient for users.

In this guide, we’ll dive deep into the steps of adding Telegram payment functionality to a Mini App built with Django and React, covering everything from setting up your models to handling webhook updates from Telegram. Let’s jump in and create an app that offers a streamlined and modern payment experience!


Prerequisites for Payment Integration

Before diving into the code, make sure you have:

  1. A Django backend set up for managing API requests and business logic.
  2. A React frontend that will serve as the user interface within the Telegram Mini App.
  3. A Telegram bot, created via BotFather, with payment functionality enabled.

Once you have these components in place, you’ll be ready to start building the payment system!


Setting Up Models in Django

To manage transactions, we need a Payment model in Django. This model will track each user’s payments with fields for the user’s ID, payment amount, a unique order ID, and the payment status.

from django.db import models

class Payment(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    order_id = models.CharField(max_length=100, unique=True)
    status = models.CharField(max_length=10, default="pending")
    created_at = models.DateTimeField(auto_now_add=True)
Enter fullscreen mode Exit fullscreen mode

The Payment model serves as a record for each transaction, allowing us to track when a user initiates payment and whether it’s completed successfully.


Creating the Payment Invoice View in Django

The create_invoice function is a key part of this integration. This function will generate an invoice and send a request to Telegram’s API, which will then return a link that the user can click to complete their payment.

def create_invoice(user, amount) -> dict:
    order_id = user.tg_id  # Unique order ID

    # Save payment in the database
    payment = Payment.objects.create(
        user=user,
        amount=amount,
        order_id=order_id
    )

    # Set payload with payment details
    payload = f"{order_id}&&&{payment.id}"
    data = {
        "title": "Purchase",
        "description": "Exclusive Access",
        "payload": payload,
        "currency": "XTR",
        "prices": [{"label": "Telegram Stars", "amount": int(amount * 100)}]
    }

    headers = {'Content-Type': 'application/json'}
    url = f"https://api.telegram.org/bot{settings.BOT_TOKEN}/createInvoiceLink"
    response = requests.post(url, json=data, headers=headers)

    if response.ok and response.json().get('ok'):
        return {"url": response.json()['result']}
    raise Exception("Invoice creation failed.")
Enter fullscreen mode Exit fullscreen mode

Here’s what each piece does:

  • Order ID: Unique identifier for the order based on the user’s Telegram ID.
  • Payload: Information about the order, including the ID and amount.
  • API Request: Sends a request to Telegram’s API, generating a unique payment link.

If everything goes well, we get an invoice URL that we’ll later send to the frontend.


Configuring API Request Headers and Endpoint for Telegram

To interact with Telegram’s API, set the necessary headers and construct the appropriate endpoint URL. This ensures that Telegram recognizes our request, and it returns the required payment link.


Returning Invoice URL from Django to React Frontend

Now, let’s create a view in Django that will interact with React when the user initiates a payment. This view generates the invoice link and sends it back to the frontend.

@api_view(["POST"])
def buy_subscription(request):
    user = request.user
    amount = request.data.get("amount")
    if not amount:
        return Response({"detail": "Invalid amount."}, status=400)

    try:
        url = create_invoice(user, amount)
        return Response(url)
    except Exception as e:
        return Response({"error": str(e)}, status=500)
Enter fullscreen mode Exit fullscreen mode

This view does a few things:

  • Retrieves the payment amount from the request.
  • Calls create_invoice to generate the payment link.
  • Sends the link back to React, which the user will use to complete the transaction.

Setting Up Payment Functionality in React

With the backend in place, let’s move to the frontend. Using axios, we’ll set up a function in React to send a payment initiation request to Django and retrieve the invoice URL.


Creating the payByTelegramStar Function in React

This function will make a request to our Django API endpoint to create an invoice. It will also handle what happens when the user clicks to pay.

const payByTelegramStar = () => {
    const telegram = window.Telegram.WebApp;
    const token = localStorage.getItem("token");
    setIsLoading(true);

    axios.post(
        "/pay/by/telegram-star",
        { amount: 100 },
        { headers: { Authorization: `Token ${token}` } }
    )
    .then(response => {
        telegram.openInvoice(response.data.url, (status) => {
            if (status === "cancelled" || status === "failed") {
                telegram.showAlert("Payment was cancelled or failed.");
            } else {
                pollSubscriptionStatus(token);
            }
            setIsLoading(false);
        });
    })
    .catch(() => {
        telegram.showAlert("Failed to initiate payment.");
        setIsLoading(false);
    });
};
Enter fullscreen mode Exit fullscreen mode

In this function:

  • We initialize Telegram’s WebApp API.
  • We send a request to our Django endpoint, passing in the payment amount and the user’s token.
  • When the request is successful, we use telegram.openInvoice to open the payment link, and a callback checks whether the payment was successful or canceled.

Opening the Invoice in the Telegram Mini App

The telegram.openInvoice method will open the invoice link within the Mini App, allowing the user to complete payment directly. We handle different responses with a callback, including success, failure, and cancellation, giving the user real-time feedback on their payment attempt.


Webhook Configuration in Django for Telegram Updates

After payment, Telegram sends updates to a designated webhook. This webhook, configured in Django, will listen for updates on the status of each transaction. We’ll use this webhook to confirm payments and update the database.


Handling pre_checkout_query to Confirm Payment

When a payment is initiated, Telegram sends a pre_checkout_query. This needs to be confirmed with Telegram to let it know that our system is ready to handle the transaction.

@csrf_exempt
@api_view(['POST'])
@permission_classes([AllowAny])
def telegram_webhook(request):
    update = request.data

    if 'pre_checkout_query' in update:
        id = update['pre_checkout_query']['id']
        url = f"https://api.telegram.org/bot{settings.BOT_TOKEN}/answerPreCheckoutQuery"
        requests.post(url, data={"pre_checkout_query_id": id, "ok": True})
    return Response({"status": "success"})
Enter fullscreen mode Exit fullscreen mode

In this function:

  • We check for the pre_checkout_query key in the webhook update.
  • If it exists, we extract the query ID and confirm the transaction with Telegram.

Processing successful_payment Webhook Update

When a payment is successfully completed, Telegram sends a successful_payment update to our webhook. We can then mark the corresponding Payment record as “paid” in our database. Let's edit our function

@csrf_exempt
@api_view(['POST'])
@permission_classes([AllowAny])
def telegram_webhook(request):
    update = request.data

    if 'pre_checkout_query' in update:
        id = update['pre_checkout_query']['id']
        url = f"https://api.telegram.org/bot{settings.BOT_TOKEN}/answerPreCheckoutQuery"
        requests.post(url, data={"pre_checkout_query_id": id, "ok": True})
    return Response({"status": "success"})

    # Successfull payment
    elif 'successful_payment' in update.get("message", {}):   
        order_id = update.get("message", {}).get("successful_payment", {}).get("invoice_payload")  # Get invoice payload 
        # Update your payment record based on order ID    
        try:  
            user_tg_id = order_id.split("&&&")[0]  
            payment_id = int(order_id.split("&&&")[1])  

            payment = Payment.objects.get(order_id=user_tg_id, id=payment_id)  
            if payment.status == "paid":  
                print(f'[payment already marked as paid]')  
                return Response({"status": "fail"})  
            else:  
                payment.status = "paid" # mark as paid
                payment.save()  
                ### Other operations here when payment is successful
        except Exception as e:  
            print("[error, data not valid]", str(e))  
            return Response({"status": "fail"})

Enter fullscreen mode Exit fullscreen mode

Setting the Webhook in Telegram

To receive payment updates, we must register the webhook URL with Telegram using the following format:

https://api.telegram.org/bot{YOUR_TELEGRAM_BOT_TOKEN}/setWebhook?url=https://example.com/webhooks/telegram
Enter fullscreen mode Exit fullscreen mode

This URL registers our webhook, and Telegram will start sending transaction updates to our app.


Polling the Subscription Status in React

To confirm payment on the frontend, we can create a polling function in React that periodically checks the payment status by sending a request to our backend.

const pollSubscriptionStatus = (token) => {
    const intervalId = setInterval(() => {
        axios.get("/payment/check", { headers: { Authorization: `Token ${token}` } })
            .then(response => {
                if (response.data.success) {
                    clearInterval(intervalId);
                }
            })
            .catch(error => console.error(error));
    }, 3000);
};
Enter fullscreen mode Exit fullscreen mode

This polling function will check the backend every 3 seconds to see if the payment has been marked as successful, providing a smooth user experience by confirming the transaction without the user having to refresh.


Conclusion

Integrating Telegram payments within a Django and React Mini App opens the door for a smooth, convenient transaction process that keeps users engaged within the app. From creating an invoice to handling real-time payment updates with webhooks and polling, each step contributes to a streamlined and secure payment flow.

By following this guide, you’ll have all the tools you need to build a Telegram payment integration that works seamlessly for users. Give it a try and see how much easier in-app payments can be!

Sources:
payment Article's
30 articles in total
Favicon
Digital Payment Market: Significant Growth to $236.3 Billion by 2030 with 14.5% CAGR
Favicon
Introduction to 3D Secure: Enhancing Online Payment Security
Favicon
Comprehensive Merchant Services & Payment Processing Solutions
Favicon
Setting Up Paystack for Subscription-Based Billing in NestJS
Favicon
Automated Monitoring and Message Notification System for Payment Channels
Favicon
🚀 Go-QRIS: Revolutionizing QRIS Transactions with Dynamic QR Codes 💳
Favicon
Why subscription payment gateways are essential for gyms and wellness centers?
Favicon
Fintech Secrets: Paying Bills (I)
Favicon
Implementing Afterpay in a Next.js E-commerce Application: A Complete Guide
Favicon
How To Integrate Direct Card Payment on Your Website Using Flutterwave
Favicon
Unravelling the Vision of FSS BLAZE from a Tech Lens
Favicon
Holiday Payment Testing Checklist: Maximize Sales and Deliver a Fantastic User Experience
Favicon
Streamline Your Payment Process with Payment Links
Favicon
How to Integrate Telegram Payments in a Django and React Mini App
Favicon
Integrating Stripe Payment Intent in NestJS with Webhook Handling
Favicon
Leveraging Data Science to Unlock Down Payment Solutions for First-Time Homebuyers
Favicon
The Future of Payments Technology is in the Cloud
Favicon
The Future of Payments Is Here: QR Codes, Agents, and Instant Transactions
Favicon
Transaction Verification in Fintech Applications: A Step-By-Step Guide
Favicon
Payment Gateway and Shipping Integrator
Favicon
How to Integrate a Payment Gateway in an E-commerce Application
Favicon
How to Safeguard Your Business with a Reliable Crypto Payment Gateway?
Favicon
Top 10 Payment Processors for Next.js Applications [2024]
Favicon
Create a Payment Form on WordPress with Flutterwave
Favicon
Visa Passkeys: Payment Service that is Secure & Convenient
Favicon
A Developer’s Guide to Verifying Customer Financial Data in Nigeria
Favicon
Payment Passkeys @ Mastercard: Revolution for Payment Security
Favicon
How AI Automates Payment Reconciliation for Businesses
Favicon
An A-to-Z Guide to BVN Verification: What to Know and How to Integrate
Favicon
What Makes PayPal a Trusted Payment System?

Featured ones: