How to Integrate Stripe Payments API Using Google Apps Script

Learn how to Integrate Stripe Payments API Using Google Apps Script

The Stripe Payment Links Generator, built on Google Apps Script and the Stripe API, creates one-time payment links for sharing with customers. Originally developed by Amit Argarwal, I credit him for pivotal contributions, especially in interfacing with the Stripe API. His groundwork involves generating a payment link for a single item and implementing a cache system to enhance performance and minimize latency.

Expanding on his script, I introduced three new new features:

  1. Multiple Item Payment Links: Users can specify up to 20 items they wish to sell, allowing the function to generate a corresponding payment link.
  2. Post-Payment Actions: Following a successful payment, users can opt to redirect customers to a designated URL or display a custom message.
  3. Receipt and Post-Purchase Invoice: Stripe automatically sends a receipt and post-purchase invoice to the customer’s email upon completing a payment.

Please ensure proper configuration of the Stripe API when using this script. Furthermore, it’s possible to extend this script to generate subscription payment links for recurring charges to customers.

// Insert the API key you created on your Stripe dashboard
const STRIPE_API_KEY = "Stripe API Key";


/**
 * Generate a Stripe payment link for multiple items using Google Sheets
 *
 * @param {Array} items An array of arrays, where each sub-array contains the item name and the amount to be charged
 * @param {string} currency The 3-letter currency code for the items
 * @param {string} actionAfterPayment This is either an https URL to redirect the buyer to after payment or a text message to display after payment 
 * @return {string} Stripe payment link
 * @customfunction
 */

function STRIPE(items, currency, actionAfterPayment) {
  return createLink(items, currency, actionAfterPayment);
}

function createLink(items, currency, actionAfterPayment) {
  const lineItems = items.map((item, index) => {
    const priceId = getPriceId(item[0], Math.ceil(item[1] * 100), currency);
    return {
      [`line_items[${index}][price]`]: priceId,
      [`line_items[${index}][quantity]`]: 1
    };
  });

  var key = `link${JSON.stringify(items)}${actionAfterPayment}`;
  
  if(key.length < 100){
    var paymentLink = getCache(key);
    if (paymentLink) return paymentLink;
  }
  
  if(isURL(actionAfterPayment)){
    var response = postData('https://api.stripe.com/v1/payment_links', {
      ...Object.assign({}, ...lineItems),
      'after_completion[type]': 'redirect',
      'after_completion[redirect][url]': actionAfterPayment,
      'invoice_creation[enabled]': true, 
    });
    
  } else if(actionAfterPayment != "") {
    var response = postData('https://api.stripe.com/v1/payment_links', {
      ...Object.assign({}, ...lineItems),
      'after_completion[type]': 'hosted_confirmation',
      'after_completion[hosted_confirmation][custom_message]': actionAfterPayment,
      'invoice_creation[enabled]': true, 
    });
  }

  const url = response.url;
  
  if(key.length < 100){
    setCache(key, url);
  }

  return url;
}

function getPriceId(name, price = '1234', currency = 'USD') {
  const product_id = getProductId(name);
  const key = product_id + price + currency;
  const priceId = getCache(key);
  if (priceId) return priceId;
  const api = 'https://api.stripe.com/v1/prices';
  const { data = [] } = getData(api, { limit: 100, currency, product: product_id });
  const { id: newPriceId } =
    data.find(({ unit_amount }) => String(unit_amount) === String(price)) ||
    postData(api, { currency, product: product_id, unit_amount: price });
  setCache(key, newPriceId);
  return newPriceId;
}

function getProductId(name) {
  const productId = getCache(name);
  if (productId) return productId;
  const api = 'https://api.stripe.com/v1/products';
  const { data = [] } = getData(api, { limit: 100 });
  const { id: newProductId } =
    data.find(({ name: productName }) => productName === name) || postData(api, { name });
  setCache(name, newProductId);
  return newProductId;
}

function getData(endpoint, params) {
  const response = UrlFetchApp.fetch(`${endpoint}?${convertPayload(params)}`, {
    headers: {
      Authorization: `Bearer ${STRIPE_API_KEY}`,
    },
  });

  return JSON.parse(response);
}

function postData(endpoint, params) {
  const response = UrlFetchApp.fetch(endpoint, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${STRIPE_API_KEY}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    payload: convertPayload(params),
  });

  return JSON.parse(response);
}

function convertPayload(params = {}) {
  return Object.entries(params)
    .map(([key, value]) => [encodeURIComponent(key), encodeURIComponent(value)].join('='))
    .join('&');
}

function isURL(str) {
  var httpsRegex = /^https:\/\//;
  return httpsRegex.test(str);
}

function getCache(key) {
  return CacheService.getScriptCache().get(key);
}

function setCache(key, value) {
  CacheService.getScriptCache().put(key, value, 21600);
}

Joseph Asinyo

Google Workspace Developer

I’m Joseph. I love building applications and writing Google scripts to automate Google Workspace for greater productivity. Learn more about me.

Scroll to Top