Development =========== .. _installation: 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: Invoking management commands ---------------------------- The ``manage-dev.py`` file is an entrypoint to running django management commands. The generic CLI tool for running `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 :ref:`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_json: 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://:@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 :ref:`config_json` .. _stripe_webhook_endpoint: 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: :ref:`design`). There may be other events configured as well, but these are ignored when :ref:`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. ``Events``\s 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: 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" .. image:: _images/visit-form-redirect.png :alt: 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 .. image:: _images/visit-bridgeserviceurl.png :width: 700 :alt: Visit Redirect URL For more information on custom fields, see the Visit `documentation `_