Development

Installation

Install the package and dependencies:

pip install -r requirements.txt
pipe install -e .

Create a config.json file:

cp config-example.json config.json

Fill out the STRIPE_API_KEY and VISIT_API_KEY settings.

Setup a local (sqlite) database:

python manage-dev.py migrate
python manage-dev.py createsuperuser
python manage-dev.py loaddata prices-test.json

This will create a file db.sqlite and initialize it with the necessary tables and data. You can now run a development server by running:

python manage-dev.py runserver

Invoking management commands

The manage-dev.py file is an entrypoint to running django management commands. The generic CLI tool for running django-admin<https://docs.djangoproject.com/en/4.2/ref/django-admin/> This command requires at least one enviroment variable to be set DJANGO_SETTINGS_MODULE to point to a python module for the project’s settings as a dotted path. For local development, the path should be stripe_checkout.settings.dev. Inside the root of the stripe_checkout repository, The manage-dev.py file is preconfigured with this enviroment variable, and a CONFIG_FILENAME environment variable pointing to the config.json file created during Installation.

When invoking management commands in the deployed VMs you should use the /home/tnc/cmd.sh script instead of django-admin. This script is configured with the correct environment variables for running django commands against the deployed instance.

Settings

There are three ways of supplying settings. These are described below

Settings file

For development, use the stripe_checkout.settings.dev settings module. Deployed environments (test, uat, prod) use the stripe_checkout.settings.prod settings module. These files contain settings that are static between the environments, and contain some logic for reading and parsing environment variables that are set for specific environments.

Config file

The config file is a way to supply settings that are non-static, and therefore cannot be placed in a settings file. The config file must be a json file containing a top level dictionary, where the keys are settings (are therefore must be UPPER_CASE) and are directly interpreted as django settings. This allows the values to have an arbitrary structure other than a single string, such as an array. The config file is validated to a json schema, located in stripe_checkout.config. In order to use a specific config file, set the CONFIG_FILENAME environment variable to a file path path/to/config.json that points to a valid config file. This can be an absolute path or a relative path. For discoverability, it is better to use an absolute path.

Environment Variables

We use the DJANGO_SETTINGS_MODULE and CONFIG_FILENAME to point to the settings file dotted.path and config file path/to/config.json. There are also other environment variables for settings that cannot be static in a settings file, because they either vary between environments, or contain sensitive information. The settings files are set up in a way to read certain enviroment variables and use them for specific settings.

Note

Both the config.json and environment variables can be used for variable settings. When to use one over the other is somewhat arbitrary, but there are guidelines. Settings that are relevant to the application specifics should be placed in the config.json, such as api keys and specific stripe or visit ids. Also settings that have a more complex structure than a single string (such as an array) are more easily set using a config.json Settings that have a more infrastructure-like nature, or have to do with django internals, such as DJANGO_FRONTEND_URL or DJANGO_SECRET_KEY are supplied using environment variables. Another reason to use an environment variable is when a value needs to be processed before being assigned to the actual setting, as is the case with the DATABASE_URL environment variable.

Database

Stripe checkout needs a database to function properly. In development this is a sqlite database. You can also connect to the test database by setting the DATABASE_URL environment variable (substitute the username and password with the data in Lastpass):

export DATABASE_URL=postgres://<username>:<password>@test-postgres.geant.org/stripe_checkout

If you now run django-admin or manage-dev.py this will connect to the database for the test deployment.

Email

stripe-checkout sends an email when it sees a succeeded payment intent that doesn’t match an Order in the database, and therefore can’t link it to a visitor’s purchase. It uses Django’s send_mail functionality. Django uses the following settings:

  • EMAIL_HOST (default: localhost)

  • EMAIL_PORT (default: 25)

It so happens postfix is configured on the stripe-checkout vm’s to forward to the geant smtp servers. So we don’t need much additional configuration. We only configure the DEFAULT_FROM_EMAIL setting. The recipients for these emails can be set using the SEND_ERROR_EMAILS_TO setting in the Config file

Stripe webhook endpoint

Stripe can be configured to call a webhook endpoint for certain Stripe events. These webhooks can be configured in the Stripe Workbench. Stripe is configured to call the /stripe-event-webhook/ endpoint for payment_intent.succeeded and payment_intent.canceled webhooks (see also: Design). There may be other events configured as well, but these are ignored when processing events.

During development it is possible to register your locally running development server as an event webhook using the stripe cli and register a local listener. After setting up stripe cli and logging in, you can hook up the local developer server with the following command:

stripe listen --events payment_intent.succeeded,payment_intent.canceled \
  --forward-to 127.0.0.1:8000/stripe-event-webhook/

Upon running this command, the stripe cli will output a stripe signing secret. This is a secret key that stripe will use to sign the event payload so that we can be certain the events are actually coming from Stripe. Add this secret to you config.json as the STRIPE_SIGNING_SECRET setting and restart the development server.

Eventss will now be registered in the local database. Run the following command to process these events:

python manage-dev.py processevents

Note

One way the /stripe-event-webhook is secured is through the signing secret. The second way this endpoint is secured, is that only IP addresses from stripe can actually call this endpoint. The full list of stripe webhook IP addresses can be found here. These IP addresses are placed in the STRIPE_WEBHOOK_ALLOWED_IPS setting in the stripe_checkout.settings.prod settings module.

Visit redirect

The redirect to the stripe checkout server in Visit is done using a custom javascript snippet:

  1. Click the final page “Complete”

  2. Click “current page settings”

  3. Clikc “Edit Javascript”

Visit form redirect instructions

Warning

There is another method of adding javascript, namely in the form settings rather than the custom page settings. These are the first settings you see when editing the form. Any javascript placed here is activated for the whole form rather than a single page. Also, Javascript placed in the form settings, overrides any javascript placed in page settings, so this will deactivate the automatic redirect.

Redirect URL

The redirect url is stored in the Visit custom field bridgeserviceurl. To edit this, login to Visit, open the TNC 2025 event and follow these steps:

  1. Click on Event

  2. Click on Setup

  3. Click on Custom fields

Visit Redirect URL

For more information on custom fields, see the Visit documentation