0
votes

Background

I'm building a Shopify embedded app and rely on the app/uninstall webhook to revoke a users access once they uninstall the app. I revoke their access by removing their access token from my db and adding them to an uninstall list.

Issue

The Shopify app/uninstall webhook is firing multiple times and sometimes very randomly (i.e 3am in the morning.) This is causing problems because occasionally if a user reinstalls the app I'll get a random uninstall webhook firing and remove their access.

Question

What is a responsible way to handle Shopify webhooks and their potential randomness/duplication so I can be confident when handling uninstalls?

1

1 Answers

2
votes

After quite a bit of testing and forum researching I've figured out a good defensive coding strategy to the randomness of Shopify webhooks.

Solution

Code defensively! Don't solely rely on the webhooks to trigger database actions. See below for my defensive coding practice.

  1. When you receive an uninstall webhook respond to it quickly with a status 200. Shopify requires that you respond within 5s. So quickly verify the webhook, add it's payload to a queue and then respond with status 200. The payload I'm adding is simply the name of the shop that uninstalled. The data sent in the body of the request is only information about the shop. It doesn't include anything unique about the webhook that fired to differentiate it from other uninstall webhooks that may fire for the same shop.
  2. Your queue should be a list that triggers another function to run once a new node is added to it. By using a queue to do the heavy lifting you can spend more time performing db actions without worrying about the 5s respond time. I'm using Firestore for a database and Cloud Firestore Triggers. That backend setup for queue processing is working great. My function only runs onCreate() of a new shop uninstall node so even if multiple uninstall webhooks fire back to back then my function only runs once.
  3. The function I run when a new uninstall is added to my queue first checks to see if I can use the shops access token that I already have saved elsewhere in the users node in my db. If I'm blocked from using the access token then this in fact is a true uninstall and should be processed. If I can still use the access token then the uninstall should be ignored.
  4. When a user reinstalls the app, I remove them from my uninstall queue and send them through the auth process again to get a new access token.