A Step-by-Step Guide to Integrating Stripe with Google Apps Script

Stripe logo

Choosing the right payment processing platform is crucial for any business, and Stripe stands out as a leading choice. Stripe offers robust APIs and developer tools that make integration straightforward and customization easy. Its documentation is comprehensive and user-friendly, empowering developers to quickly set up payment processing within their applications or websites. And fortunately for many business owners who are not also professional programmers, Stripe offers no-code and low-code integration options.

In this tutorial, we'll walk through the process step-by-step to seamlessly integrate Stripe with Google Apps Script using webhooks to get your business accepting payments now!

Prerequisites

It doesn't take much to integrate Stripe with your GAS project. The basic prerequisites are:

  • 1. A Stripe account
  • 2. A Google account
  • 3. Basic familiarity with Google Apps Script

If you're worried about #3, check out some of the other tutorials I've made!

Setting Up Your Google Apps Script Project

This method listens to events from your Stripe account using Stripe webhooks. These events can automatically trigger reactions in your GAS project. You can use this to log data to a spreadsheet, automatically enable premium services to users following payment, send emails, and much more!

The first step is to set up your Google Apps Script project. I recommend creating a new file. Name this something like "Stripe Service" and start with a doPost function as shown below.

function doPost(e) {
  try {
    const jsonString = e.postData.getDataAsString();
    const eventData = JSON.parse(jsonString);

    processWebhook(eventData);

  } catch (error) {
    console.log('##STRIPE ERROR##', error);
    
    MailApp.sendEmail(
      'myemail@gmail.com, 
      'Stripe Error', 
      `A Stripe error has occurred: ${error}`
    );
  }
}

This first step is crucial. When a webhook fires, whether from Stripe or some other service, and an HTTP POST request is sent to your app, this function is automatically triggered. Inside this function, you will need to interpret the data sent from the service and use that to complete the desired tasks. Read more on how Apps Script handles this type of function here.

It's also important to wrap the code inside this function in a try...catch block to handle any errors that may occur. Be sure to log information about the error here as well as setup some sort of notification when an error occurs here. I like to use MailApp.sendEmail() here to send myself an email with information about the error when I know the error could be related to something really important or time-sensitive.

Next, you need to parse the data coming from the webhook event. This will result in the Stripe JSON Event objectthat contains information about the Stripe event that occurred on your account.

Process the Stripe Event

Once you receive the Stripe event data, you'll need to handle it based on the type of event. For example, successful payments and cancelled subscriptions are two different Stripe event types. You would process the successful payment event by fulfilling the customer's order. And if a customer cancels their subscription, you would want to make sure that the services are stopped.

To do this, create another file and name it something like "Stripe Provider". Inside this file, write the function that will be called inside the doPost function to handle the Stripe event. Depending on what you plan on doing with the data (e.g. like logging this data to an external database), you may want this to be an asynchronous function. If all you are doing is writing this data to your spreadsheet, it can remain synchronous.

To determine which function to run, you can use a series of if...else statements but I prefer a switch statement for readability.

async function processWebhook(eventData) {
  try {

    const eventType = eventData.type;

    switch (eventType) {
      case 'customer.subscription.updated':
        // Handle subscription update events
        await processSubscriptionUpdated(eventData);
        break;
      case 'customer.subscription.deleted':
        // Handle subscription deletion events
        await processSubscriptionDeleted(eventData);
        break;
      case 'invoice.payment_succeeded':
        // Handle successful invoice payment events
        await processInvoicePaymentSucceeded(eventData);
        break;
    }

  } catch (error) {

    console.error(
      `##STRIPE ERROR##; 
      eventData: ${JSON.stringify(eventData)}`, 
      error
    );

    MailApp.sendEmail(
      'myemail@gmail.com, 
      'Stripe Error', 
      `A Stripe error has occurred. 
      eventData: ${JSON.stringify(eventData)} 
      error: ${error}`
    );
  }
}

In the function below, I handle a subscription update event.

async function processSubscriptionUpdated(eventData) {
  try {

    const subscriptionData = eventData.data.object;

    const subscriptionStatus = subscriptionData.status;
    const customerId = subscriptionData.customer;
    const startDate = subscriptionData.start_date;
    const endDate = subscriptionData.ended_at;

    // Double check that subscription is active or trialing
    if (
      subscriptionStatus === 'active' || 
      subscriptionStatus === 'trialing'
    ) {
      // Start or resume premium services
      
    } else {
      // Stop or discontinue premium services
           
    }
    
  } catch (error) {
    
    console.error(
      `##STRIPE ERROR##; 
      eventData: ${JSON.stringify(eventData)}`, 
      error
    );

    MailApp.sendEmail(
      'myemail@gmail.com, 
      'Stripe Error', 
      `A Stripe error has occurred. 
      eventData: ${JSON.stringify(eventData)} 
      error: ${error}`
    );
  }
}

Deploy as a Web app

In order for all of this to work, you need to deploy your code as a web app. Once you deploy, you will receive a URL that you will paste into your Stripe configuration ont he Stripe website. You cannot get this URL without deploying this way. Also, every time you make an update to your code, you will need to redeploy and get an updated URL.

See the documentation for more information on how to deploy.

Set up Stripe

With your URL copied, go to your Stripe dashboard then navigate to the "Developers" page. From there, go to Webhooks then Add endpoint. Paste your web app URL then select the events you want to listen to.

Determining which events to listen to can be a little tricky. Keep in mind that there are events for everything that happens in Stripe, including administrative and setup events. Also, sometimes you can accomplish the same thing from multiple events. "For example, if you create a new subscription for a customer, you receive customer.subscription.created and payment_intent.succeeded events." In this case, it is possible to determine if a customer has paid for the subscription with either event. Consult the Stripe documentation for more information. Also, be sure to listen to as few events as possible. Listening to too many events can cause slowness and it just means more that you have to anticipate for in your code.