Skip to main content

How to Integrate Stripe Checkout with Python-Generated PDF Invoices?


Stripe payment page

In the previous tutorial, we created a sales invoice using Python and ReportLab. The invoice included details such as customer information, line items, totals, and formatting. In this tutorial, we will enhance the invoice by adding a Stripe payment button directly inside the PDF. This functionality means that when a customer opens the invoice, they can click the "Pay Now" button, which redirects them to a Stripe checkout page to complete the payment.

Prerequisite:

This tutorial is part of the Automated Sales Invoice Series.

📚 View the Complete Automated Sales Invoice Series

⬅ Previous Part                                                                                                                     ➡ Next Part

Preliminary
Before I begin, please activate the virtual environment and install the required dependencies.

python -m venv venv
venv\Scripts\activate 
pip install reportlab
Then, we need to set up the file and folder structure, as below:

File and folder structure

Since this tutorial continues from the last tutorial, Part 2, all the files and folders remain the same, except I need to slightly amend 'pdf.py' and create a new file, 'payment.py' to add a button on the sales invoice, as shown in the diagram above.


Step 1: Log in to the Stripe platform and create a product
Go to the Stripe site and log in with my Google account. When I am at the dashboard page, from the left-side menu bar, I will click "Product Catalogue," and then a window will slide from the right. Next, I will click the purple button from the top right corner, "+ create product." 

Stripe platform

On the "Add a product" window, I input the product name and description, upload a simple image, select the payment type, preferred currency, and amount, and finally click the "Add product" button at the bottom. The details are shown in the diagram below.

Stripe product page


Step 2: Generate and copy a product link
I will create a product link once I've created the product. In the top right corner, there is a "+" button, and I click it, and a drop-down shows a list of options. I will click the "Payment Link." Then select the product category I created in step 1 above; a preview will appear in the right window. If I am satisfied with the layout, I can go ahead and click the "Create link" in the top right corner. Finally, I simply click the copy button when it has shown the payment link that I need.

Click "Create link" in the top-right
Create product link




Step 3: Create a button in the Sales Invoice PDF
Once I own the link, I will create the code below in the payment.py file. I need to create a red button at the centre bottom of the sales invoice with a clickable link. The copied URL link from the Stripe site will now be pasted into my code, and when the button is clicked, it will redirect me to the Stripe payment site. The following is my code in payment.py with a detailed explanation.
# Import module from the ReportLab
from reportlab.lib.units import inch
from reportlab.lib.colors import red

def stripe_payment(c):
    # Stripe Checkout payment link from step 2 above
    # This is the URL that customers will be redirected to when they click the button
    stripe_url = "https://buy.stripe.com/test_28EeVdecq3ME7n92OvgMw05"
    
    # ---------------------------------------------------------
    # Button Position and Size
    # ---------------------------------------------------------
    
    # the x, y coordination, width and height
    x = 2.8 * inch
    y = 0.5 * inch
    width = 2 * inch
    height = 0.5 * inch
    
    # ---------------------------------------------------------
    # Draw Button Background
    # ---------------------------------------------------------
    
    # Define the rectangle area of the button
    rect = (x, y, x + width, y + height)
    
    # Set the fill colour of the button
    c.setFillColor(red)
    
    # ---------------------------------------------------------
    # Add Button Text
    # ---------------------------------------------------------
    
    # Set the font style and size
    c.setFont("Roboto-Bold", 14)

    # Adjust text position slightly to centre it visually
    offset_x = -69   # negative = left
    offset_y = -76    # negative = down

    # Calculate text position based on button centre
    text_x = x + width/2 + offset_x
    text_y = y + height/2 + offset_y
    
    # Button label
    text = "Pay Now"
    
    # Draw the text centred at the calculated position
    c.drawCentredString(text_x, text_y, text)

    # ---------------------------------------------------------
    # Add Clickable Stripe Link
    # ---------------------------------------------------------
    
    # When the user clicks the rectangle area, it opens the Stripe payment page
    c.linkURL(
        stripe_url,
        rect,
        relative=0,
        thickness=2,
        color=red
    )
    
    # Return the updated canvas object
    return c
When it prompts a security warning, just click to allow the process to proceed.

Click the payment button

I made a button in payment.py, but it must be imported in pdf.py to work. Following is my code in pdf.py.
# import from the payment.py
from payment import stripe_payment 

# Set the output PDF file path
my_path = 'sales_invoice/my_invoice.pdf'

# Create a new PDF canvas object
c = canvas.Canvas(my_path, pagesize=letter)

# Stripe payment button at the bottom
c = stripe_payment(c)
When I run the app, it will generate a my_invoice.pdf file in the sales invoice folder. Then, I click PDF to open the file.


Step 4: Test the payment link

(A) Before payment

After I click the 'Pay Now' button, it will direct me to the Stripe payment link (the link in Step 2), as shown in the diagram below.

Payment page

Before I proceed, I need to fill out my email address and then complete the payment details.

The card number for testing purposes is as follows:
   (i) Visa - 4242424242424242, or
   (ii) Master - 5555555555554444

I used a Visa card for this tutorial; the card's expiration date is in the future, and the three-digit CVC is a random number, followed by my cardholder name and country, as diagrammed above.

(B) After payment

Once I have filled out the card details and clicked the subscribe button, the diagram below displays the payment status; the tick mark indicates the payment was successful. 

Thank you page

To confirm the payment was actually received, I need to return to the Stripe platform again. When I click the left sidebar menu on transactions to view the full list of transactions, I notice the successful payment details are shown in the table below.

Transaction view

Final wrap-up.
In this tutorial series, we created a sales invoice generator using Python and ReportLab and enhanced it by adding a clickable payment button directly inside the PDF. By combining a visual button with a payment link, customers can easily click “Pay Now” and complete their payment online. The link can point to any payment platform, such as Stripe, PayPal, or Razorpay, making the invoice flexible for different payment providers. This makes the invoice more interactive and convenient, turning the Python invoice system into a practical tool for generating invoices with built-in payment capabilities.

Published: Mar 2026
Last Updated: Mar 2026
---------------------------------------------------------------------------------------------------------------------------------------------------

🎁 Get Your FREE Flask Cheat Sheet

Join 500+ Python learners and receive this printable Flask Cheat Sheet instantly. Plus, get new Flask tutorials delivered to your inbox.

✓ Practical coding tutorials
✓ Automation tips for SMEs
✓ New project ideas and templates

-----------------------------------------------------------------------------------------------------------------------------
Need a similar system for your business? 
I build custom Flask web applications and Python automation solutions for SMEs and solopreneurs. 


-----------------------------------------------------------------------------------------------------------------------------

About the Author

Kelvin Loh is a Python developer focused on Flask, desktop applications, and business automation solutions. He shares practical tutorials and real-world coding projects to help developers and small businesses build useful applications.

Comments

Popular Posts

How to Build an Audiobook Workflow Desktop System with Python?

In this tutorial, we will build a simple audiobook player using Python and CustomTkinter. You will learn how to convert text into speech using gTTS and play it with PyGame. We will also implement play, pause, and stop controls, like those in a real audio player. By the end, you will have a clean and functional desktop audiobook app. Prerequisite: This tutorial is part of the standalone tutorial. 📚 View the standalone tutorial Preliminary   Before I begin, it is recommended to activate the virtual environment before installing the relevant dependencies. python -m venv venv venv\Scripts\activate pip install customtkinter pillow gTTS pygame CTkMessagebox pypdf Then, the following steps include setting up the file structure, app.py, and two additional folders: the uploads and media folders. The media folder contains the icons necessary to build the app; there are read, pause, and stop icons, as shown on the diagram. Step 1: Build up the app interface I have 4 sections here: the...

How to Set Up PgAdmin and Adminer Using Docker Compose?

If you are new to database management with Docker, this tutorial will guide you through setting up both PgAdmin and Adminer using Docker containers. By containerising these tools, you can quickly launch lightweight and portable database management environments without installing them directly on your operating system. This approach also makes it easier to manage configurations, updates, and multiple projects across different devices.