Skip to content

Latest commit

 

History

History
208 lines (132 loc) · 7.47 KB

README.md

File metadata and controls

208 lines (132 loc) · 7.47 KB

This inner package houses the Firebase Cloud Functions of WTMG's Firebase backend.

Install

Install the dependencies, if you haven't already while following the main README:

yarn install

Configure the Cloud Functions

If you have full access, set it up.

See https://firebase.google.com/docs/functions/local-emulator#set_up_functions_configuration_optional

Run this inside the api functions dir:

firebase functions:config:get > .runtimeconfig.json

# If using Windows PowerShell, replace the above with:
# firebase functions:config:get | ac .runtimeconfig.json

Will output a JSON file similar to the following (see .runtimeconfig-example.json), which will be picked up by the emulators:


{
  "frontend": {
    "url": "https://staging.welcometomygarden.org"
  },
  "sendgrid": {
    "key": "<secret_sendgrid_key>"
    ...
  },
  "stripe": {
    "secret_key": "<secret_key>",
    "webhook_secret": "<secret_key>"
  },
}

You can replace "frontend" with the localhost URL where you are currently running whe WTMG Svelte client app, if you want.

Start dev servers

yarn serve

See package.json for alternative commands, as well as the firebase command itself. More convenience methods are available in the root package.json.

The Firebase CLI acts upon the /api folder as part of a bigger project.

Dev server troubleshooting

Sometimes the dev servers don't quit properly, and remain handing. On a restart, they will complain that the port of a certain emulator is already taken.

On macOS/Linux, you can kill the process listening on that port with:

lsof -ti tcp:8080 | xargs kill

# Or, if we're desperate:
lsof -ti tcp:8080 | xargs kill -9

Running the Stripe dev environment

The Stripe integration was set up with the core ideas from this guide: https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=elements, however, we're using collection_method: 'send_invoice' when creating subscriptions instead, and not the default auto-charge method.

This changes the way that Stripe operates on subscriptions & invoices significantly, so the real code differs from the guide.

Documentation is detailed and extensive, but also scattered. These additional resource may help:

Testing the integration

Test config

Ensure the testing private secret and webhook secret are filled in ./.runtimeconfig.json, and that the frontend has access to the publishable test key.

Set up local webhooks

Refer to the Stripe guide to set up local Stripe webhook triggers: https://stripe.com/docs/webhooks/test o.

First, install the CLI & log in.

stripe login

Then, refer webhook events to your local function emulators.

If another live testing webhook listener is already active, disable it first, to avoid having duplicate handlers for events:

(the HTTP endpoint will be printed when starting the firebase dev servers)

  1. Disable the main live test endpoint of the (temporarily) at https://dashboard.stripe.com/test/webhooks

  2. Take over its events locally by running:

    stripe listen --events customer.subscription.deleted,customer.subscription.updated,invoice.finalized,invoice.created,invoice.paid,payment_intent.processing --forward-to http://127.0.0.1:5001/wtmg-dev/europe-west1/stripeWebhooks
    
  3. Verify that /wtmg-dev/ in the URL above matches your current Firebase emulator project (did you run firebase use wtmg-dev before running Firebase emulators? Or are you using /demo-test/?). Also verify that the API emulator is active, with .env (VITE_USE_API_EMULATOR=true);

If you get an api-key-expired error, you must likely log in again. The authentication expires after 90 days.

NOTE: I've had weird behavior with --load-from-webhooks-api, with or without an extra --events key specified. Sometimes events got forwarded to the local server, and sometimes not propery (no responses were being logged). It might also depend on the staging endpoint being disabled or not. The above works dependably.

Testing payment methods

See here for fake payment details: https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=elements&element=payment#test

Stripe config notes

Running tests

This project uses the mocha test runner, and sinon for mocking/inspecting objects for tests.

To run all tests:

echo "node_modules/.bin/mocha -w" > runtests.sh && firebase --project demo-test emulators:exec --ui --only auth,firestore ./runtests.sh

This example (run from the api folder) runs tests in the group that includes the string sendMessageFromEmail:

echo "node_modules/.bin/mocha -f sendMessageFromEmail" > runtests.sh && firebase --project demo-test emulators:exec --only auth,firestore --ui ./runtests.sh

Or, when functions or Firestore triggers should also be tested:

echo "node_modules/.bin/mocha -w -f onCampsitesWrite" > runtests.sh && firebase --project demo-test emulators:exec --only auth,firestore,functions --ui ./runtests.sh

Some unit tests can be run without starting firebase emulators, because they don't have Firebase dependencies, or their dependencies (like logger in from functions-framework) work standalone.

node_modules/.bin/mocha -w -f 'inbound email parser'

To prevent Firestore-triggered functions from running (and potentially slowly hitting SendGrid), this example adds --only auth,firestore. Remove this to run the functions anyway for more realistic side-effects.

Deployment to Firebase

Use the correct environment:

firebase use wtmg-dev

Set (upload) the environment variables

  1. Akwardly ensure, one-by-one that your target environment has all the needed files (we should probably migrate to the new parametrized config, or hack around it another way)

    # Check what is live now
    firebase functions:config:get
    
    # Make changes
    firebase functions:config:set stripe.secret_key="API KEY" stripe.webh
    ook_secret="SECRET"
    
    # Check if you did well
    firebase functions:config:get
    
  2. ensure no stray .env.* files are around in the /api dir that might confuse Firebase.

Keep in mind that Stripe Webhook signing secrets are unique to the webhook endpoint. They will be different for local testing, staging and production environments.

Deploy functions

This will deploy all functions:

firebase deploy --only functions

This will deploy specific functions, for example, all new Stripe-related functions:

firebase deploy --only functions:createStripeCustomer,functions:createOrRetrieveUnpaidSubscription,functions:createCustomerPortalSession,functions:stripeWebhooks

Deploy Firestore rules

See the docs.

# For Firestore
firebase deploy --only firestore:rules

# For Storage
firebase deploy --only storage

# Both
firebase deploy --only firestore:rules,storage