In-app purchases

The community has periodic questions, and sometimes detailed discussions with links to many other resources, regarding how to enable in-app purchases. It's indeed possible, and can be pretty comprehensive, but complex, with Apps Script and the robust APIs offered by payment processors.

As @juanpa has outlined, it's also possible to implement in a thoroughly no-code manner. Here's an illustrated description of one barebones technique. It uses Stripe for processing payments and Make for managing the confirmation of payment submission. (While Make is clunkier to set up than the often recommended Zapier, Make's free tier is far more generous. See more from @Fabian_Weller regarding using Make with AppSheet.)

Steps

Stripe: Payment links

Create a payment link for each type of in-app purchase you want to make available to app users. These might be, for example, an app subscription for x months or access to a premium app feature. A single link can include multiple distinct products as separate line items.

For each link, you can either fix the quantity of each line item or allow the user to adjust the quantity. If you fix the quantity, then in your app you'll be able to reliably show the user the quantity that is pending payment. If you allow the user to adjust the quantity, you'll have an additional detail to reconcile after payment is submitted.

In this example, each payment link is for a different fixed quantity of the same single product.

dbaum_1-1682194134078.png

For each link, you can include custom metadata. This can be helpful in many ways--especially in the following use cases:

  • Within your app, you need to process different types of purchases differently (e.g., some are in a subscriptions table and some are in a premium features table).
  • You need some but not all payments made through your Stripe account to be processed within your app (e.g., some payments are for in-app purchases and some are not).

In this example, one payment link's metadata reflects that the link is for in-app purchases that are part of a category named "...credits".

dbaum_2-1682196497014.png

AppSheet: Tables

Items available for purchase

Create a table with a row for each type of in-app purchase you want to make available to app users. Include columns at least for:

  • Name
  • Price
  • Payment Link URL

Other columns can also help you provide useful app features, such as quantity.

User purchases

Create a table with a row for each purchase. Include columns at least for:

  • ID (table key)
  • Reference to the "Items available for purchase" table
  • Status (e.g., Pending, Canceled)
  • Payment Link URL with a row-specific parameter
    • This column allows you to later match a submitted payment to its row's specific purchase. Use an Initial value expression to concatenate the Stripe payment link with the following URL parameter: client_reference_id=ID. A few additional URL parameters are also available to track or prefill information and can be helpful, including prefilled_email. Here's an example of a full template: https://buy.stripe.com/{Stripe payment link ID}?prefilled_email={user email}&client_reference_id={row ID}

Other columns can also help you provide useful app features, such as timestamps and user.

Make: Scenario

Create a scenario that comprises at least the following modules:

  • Stripe Watch Events: Receive webhooks posted by Stripe's Checkout Session Completed event
  • AppSheet Edit a Record: Update the user purchase row's status (e.g., from "Pending" to "Paid")
    • For the row's key, reference the client_reference_id, which Stripe extracts from the row-specific payment link URL's parameters and then includes in the webhook sent to Make.

Filters, additional modules, and other Make features can also help you manage your process, such as:

Tips to keep in mind while creating the scenario:

  • If you're creating separate scenarios using Stripe test and live data, name your connections and webhooks correspondingly to keep them straight.
  • After creating the trigger module connected to Stripe, run the scenario once to have it load the webhook schema so that you can then reference in subsequent modules the schema's values, such as client_reference_id.

In this example, the (partially represented) scenario detects completed checkout sessions, filters out events not for in-app purchases, routes the flow based on the purchase category, and updates AppSheet table columns.

dbaum_3-1682198108697.png

dbaum_4-1682198179101.png

dbaum_5-1682198221860.png

dbaum_6-1682198315893.png

dbaum_7-1682198407533.png

AppSheet: Actions

The following actions constitute the minimum to enable a user purchase journey.

  • Purchase: Add a row to the "user purchases" table.
  • Pay: Go to a website - Launch the row-specific payment link URL.

Other actions can also help you provide useful app features, such as:

  • Email payment link: Start an email - Generate a draft email for the user to send the payment link (e.g., to someone else responsible for paying).
  • Cancel purchase: Set the value of a column - Update a row value to reflect the purchase is canceled (e.g., to exclude the row from a list of purchases pending payment).

In this example, a user selects the "Purchase credits" action and after adding a row via a form view can complete the payment as well as perform other actions.

dbaum_8-1682199803356.png

dbaum_9-1682199895862.png

dbaum_10-1682199958603.png

14 7 1,204
7 REPLIES 7

Nice, very very nice.. thank you!

As always, the tip is detailed, systematic in your customary style. Such a detailed tip for payments system integration was an ask for many years. You described a solution with Stripe and Make. I think it will serve as an approach foundation for other combinations as well -some other payment system and other integration platforms. Thank you very much @dbaum . 

Excellent guide!  This has been requested for a LONG time; I'm sure this will be extremely helpful to a ton of people out there.

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

You might be able to remove the "Make" integration all together....

  • From Stripe you can create a webhook (in the "Developer" panel)
    9611bbef-e361-47ef-bd02-b5d871bbcd74
  • That webhook can be triggered based on X conditions
  • The webhook can then send the data of the interaction to an API endpoint
  • You can create your own API endpoint using Google Scripts
  • MultiTech_0-1682364817112.png
  • You can then create scripts that "catch" the data when it comes into the API, and does whatever you need it to do.

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

Amazing work!  This has been a LONG request thing, thanks for putting this together!


@MultiTech wrote:

You might be able to remove the "Make" integration all together....


Definitely possible. I have other AppSheet integrations set up exactly as you describe--i.e., create a callback endpoint using Apps Script that receives data posted by another service and then processes that data (e.g., using AppSheet API to update an app's data).

I encourage anyone for whom it's helpful: Use the entirely no-code approach to get up and running pretty quickly, and then transition to your own custom Apps Script project if a service like Make or Zapier becomes too expensive or otherwise doesn't meet your needs. Developing in Apps Script is a great learning opportunity, and you can do really customized and intricate things that make your app even more valuable.

BTW, there's also a role for Apps Script within the upstream portion of this integration--and that part actually has a somewhat shorter learning curve than setting up a webhook endpoint.

Instead of relying on pre-existing payment links, it's possible to use Call a script automation tasks to create payment links on the fly or even one-off checkout sessions.


@dbaum wrote:

Developing in Apps Script is a great learning opportunity, and you can do really customized and intricate things that make your app even more valuable.


And if you get stuck, we're all here to help!  There are some legit GAS masters in this community.

Plus there's this new thing you might have heard of??? Chat... G... something??? (^_^)  Unprecedented what can be accomplished with that helping you along the way.

EVEN IF YOU IMPLEMENT THIS IN THE APP, YOU WILL BE REJECTED BY APPLE. 

THIS INFORMATION IS THE MOST CRUCIAL FACTOR AS YOU WILL BE REJECTED FOR TRYING TO BYPASS APPLES' IN-APP PURCHASES.

YOU WILL WORK ON THIS PROJECT FOR AT LEAST A FULL DAY TO GET REJECTED BY THE MOST PROMINENT THIRD-PARTY THAT YOU WANT TO WORK WITH.  

- See how to implement in-app purchase with the StoreKit framework.
- Review step-by-step instructions for creating in-app purchases in App Store Connect.
- Learn more about our policies for apps that offer paid digital content and services.

COMPLIANCE AND RELEVANCE ARE KEYS TO SUCCEED. FILL UP THE FOLLOWING FORM TO REQUEST APPLE AN ENTITLEMENT. This entitlement allows apps that offer in-app purchases on the iOS or iPadOS App Store on the United States storefront to also include a link to the developer’s website that informs users of other ways to purchase digital goods and services.

https://developer.apple.com/contact/request/storekit-external-entitlement-us/

Learn more.

THE MILLION DOLLAR QUESTION IS: HOW COME THE APPSHEETS; DOCUMENTATION AND THE SUPPORT TEAM HAS NO-THING AT ALL TO HELP ABOUT THIS.

NO DATA, NOT A SINGLE WORD ABOUT HOW THEIR USERS SHOULD CHARGE THEIR CUSTOMERS BUT IN FACT, YOU CAN FIND MANY WAYS HOW THEY CHARGE YOU.

Top Labels in this Space