Skip to content

Building a Stripe App: A Step-by-Step Guide to QR Code Generation

Building a Stripe App: A Step-by-Step Guide to QR Code Generation

Why Build a Stripe App?

I recently participated in an audio space with the Stripe team, and something they said really stuck with me: the Stripe app store is a growing area that isn't overly saturated yet. There's a lot of potential for new apps, and companies can use this opportunity to grow.

I work at a company called This Dot Labs, and we've created several Stripe apps and even own one. After looking at the data, I can confirm that the Stripe team was right!

Creating a QR Code Generator App

For this tutorial, we'll build a QR code app that can take a URL and generate a code for it. This is a good use case to help you understand the ins and outs of Stripe's developer tools. stripeQRCode

Why QR Codes?

QR codes are useful tools that have become common in e-commerce, restaurants, and other industries. While Stripe already has a QR code tool, we'll make our own to familiarize ourselves with their syntax and problem-solving approaches.

Project Structure

Before we dive into the implementation, let's look at the structure of our Stripe App QR Code project:

  • .vscode: Contains settings for Visual Studio Code
  • source/views: Holds the main application views
  • .gitignore: Specifies files to ignore in version control
  • stripe-app.json: Defines the Stripe app configuration
  • ui-extensions.d.ts: TypeScript declaration file for UI extensions
  • .build: this is where the built Stripe app gets placed. image (85)

Step-by-Step Implementation

1. Install Stripe Locally

First, you need to install Stripe on your local machine. The documentation provides great instructions for this:

  • For Mac users: Use Brew to install
  • For Windows users: Download the package and add it to your environment variables

You can find the details here in the stripe docs to install the Stripe CLI https://docs.stripe.com/stripe-cli

When using Windows, you must do stripe login from Powershell, NOT from Git bash or any other tool. After the server is up, then you can continue using git bash for everything else. After stripe login, you need to enter stripe apps start. Once you do that, the server is up and running and you can go back to using git bash or any other tool.

2. Install Dependencies

We'll be using an extra package for QR code generation. Install it using npm:

npm install qrcode

3. Set Up the Main Component

Let's look at the home.tsx file, where we'll use Stripe's UI components:

import { Box, ContextView, Button, TextField, Banner } from 
'@stripe/ui-extension-sdk/ui';

These components are similar to other UI libraries like Bootstrap or Tailwind CSS.

4. Create the UI Structure

Our app will have:

  • An input field for the URL
  • Validation using a regex pattern
  • Error handling for invalid URLs
  • QR code generation and display

Here is the Home.tsx file that is located in the src/views folder image (86)

import {
  Box,
  ContextView,
  Button,
  TextField,
  Img,
  Banner,
} from "@stripe/ui-extension-sdk/ui";
import { useState } from 'react';
import QRCode from 'qrcode';
const Home = () => {
  const [url, setUrl] = useState('');
  const [qrCode, setQrCode] = useState('');
  const [error, setError] = useState('');
  const generateQRCode = async () => {
    try {
      if (!url) {
        setError("Please enter a URL.");
        return;
      }
//basic regex pattern for URL validation
      const urlPattern = new RegExp(
        '^(https?:\\/\\/)?' +
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' +
        '((\\d{1,3}\\.){3}\\d{1,3}))' +
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' +
        '(\\?[;&a-z\\d%_.~+=-]*)?' +
        '(\\#[-a-z\\d_]*)?', 'i'
      );
      if (!urlPattern.test(url)) {
        setError("Please enter a valid URL (e.g., https://example.com)");
        return;
      }
      const qrCodeDataUrl = await QRCode.toDataURL(url, {
        width: 200,
        margin: 2,
      });
      setQrCode(qrCodeDataUrl);
      setError('');
    } catch (error) {
      console.error("Error generating QR code", error);
      setError("Failed to generate QR Code. Please try again.");
    }
  };
  return (
    <ContextView
      title="URL QR Code Generator"
      brandColor="#635bff"
      externalLink={{
        label: "Stripe Docs",
        href: "https://stripe.com/docs",
      }}
    >
      <Box css={{ stack: "y", rowGap: "large", padding: "medium" }}>
        <Box css={{ font: "heading", marginBottom: "medium" }}>
          Generate User Payment QR Code
        </Box>
        <TextField
          label="Enter URL"
          placeholder="https://example.com"
          value={url}
          onChange={(e) => setUrl(e.target.value)}
          type="url"
        />
        {error && (
          <Banner
            type="critical"
            title="Error"
            description={error}
          />
        )}
        <Button
          type="primary"
          onPress={() => generateQRCode()}
          disabled={!url}
        >
          Generate QR Code
        </Button>
        {qrCode && (
          <Box css={{
            stack: "y",
            rowGap: "medium",
            alignSelfY: "center",
            marginTop: "large"
          }}>
            <Box css={{ font: "heading" }}>Your QR Code</Box>
            <Img
              src={qrCode}
              alt="Generated QR Code"
            />
            <Button
              type="secondary"
              onPress={() => {
                window.open(qrCode, '_blank');
              }}
            >
              Download QR Code
            </Button>
          </Box>
        )}
      </Box>
    </ContextView>
  );
};
export default Home;
  • ContextView` is at the top level of the app where we see the Title and the link to the Stripe Docs that we placed in our Context View.
  • Box is how you use Divs.
  • Banners can be used to show notification errors or any other item you wish to display.
  • Textfields are input fields.
  • Everything else is pretty self-explanatory.

5. Handle Content Security Policy

One problem I personally ran into was when I tried to redirect users, the Stripe policies would block it since I did not express that I knew what it was doing. I had to go into the stripe-app.json file and mention the specific security policies. For this particular exercise, I kept these as null.

This is my stripe-app.json file.

{
    "id": "com.example.my-stripe-app",
    "version": "0.0.1",
    "name": "My Stripe App",
    "icon": "",
    "permissions": [],
    "stripe_api_access_type": "platform",
    "ui_extension": {
        "views": [
            {
                "viewport": "stripe.dashboard.home.overview",
                "component": "Home"
            },
            {
                "viewport": "stripe.dashboard.invoice.detail",
                "component": "Invoice"
            }
        ],
        "content_security_policy": {
            "connect-src": null,
            "image-src": null,
            "purpose": ""
        }
    }
}

6. Configure App Views

As you can see here, the stripe-app.json file shows the views for each file I have. The Home.tsx file and the Invoice.tsx are also included This is our way of saying that for each view we have, show the app functionality on that page. Our stripe-app.json file will show it but also, the manifest.js file in our .build folder will also show the same. Any view that doesn't have a file will not show the application's functionality. So, if I were to go to transactions, the app would not show the same logic as the home or invoices page.

By following these steps, you'll have a fully functional QR code generator app for Stripe. This is just a simple example, but the potential for Stripe apps is massive, especially for businesses serving e-commerce customers.

If you need help or get stuck, don't hesitate to reach out, danny.thompson@thisdot.co. The Stripe team is also very active in answering questions, so leverage them as a resource. Happy coding!

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co