Integrate Stripe with Python Django Elegantly

Rain Wu
Random Life Journal
8 min readDec 14, 2020

--

Recently I was responsible for the integration of Stripe online payment service, and take some notes about workflow planning and SDK usage details.

Stripe would be highly recommended for the payment tasks due to its software-engineering-friendly SDK, the succinct interface and complete documentation also helpful during my development.

Image from https://stripe.com/

The third-party python project management tool poetry, and the web framework Django and its dependent REST API extension would be used in this article.

Below is my pyproject.toml file, you can refer to it while building the virtual environment.

Architecture Overview

As far as a platform service which needs to support payment feature was concerned, we can only take care of the payment events form the consumer and hand over almost all of payment processing tasks to Stripe.

Quickly draft the dream above, it will turn out a rough architecture like this:

Stripe empower you with integrated payment functions, with lower development and maintenance cost compared to other third-party services.

We can also implement business logic on the interactions of each of them without strict constraints, in order to compliant with various scenarios.

Prepare for development

Before starting development, let's make sure the Stripe SDK works fine on both our server-side and client-side.

Set up Account

Sign up for a stripe account first, then you will be able to log in to the Stripe Portal and have a view of a dashboard.

image of Stripe Portal

Server-side

All the thing we need to do for activating stripe SDK on the server-side before using it is to assign the secret key we have got on the stripe portal. I use another class StripeConfig to store the configurations, you may fill in your own key in this part.

Client-side

The Client-side needs the corresponding publishable key of the server-side’s secret key for activation so that the information during payments could be protected.

To achieve that, we can easily build a REST API endpoint for providing the publishable key.

Here I use the Javascript SDK as a demonstration.

If there is no error occurs, I think your code works :)

Build a Checkout Session for Your Consumers

Just like our perception of the whole payment storyline, it should always start with a paying scenario, consumer will agree to pay some money for the goods or services. This could occur in either the supermarket near your house or a cart page of an e-commerce platform.

Here we are ready to make it come true via Stripe.

Instantiate a Session Object

Stripe provides a session-like object to handle the process of payment, it can be initialized with the specified product, price, and currency, etc.

The redirect URLs for the success and cancel payment are also needed, it will redirect the consumers for you automatically after the operation was complete.

The stripe SDK will return a JSON payload as the return value of the session creation, it’s a fantastic design that saves our effort of dealing with the response body.

The critical field of the response is the session_id, the client-side should use that for redirecting consumers to the checkout page.

One of the feasible ways to pass session ID to the client-side is packing it in the handler’s response, just like the example code above.

Redirecting for the Users

A customized checkout session of our payment is already created and hosted by Stripe now, we only need to redirect our consumer to the corresponding page for the follow-up process.

The redirectToCheckout function will lead the consumer to the session page like below.

It should contain the necessary information about the payment and marked with a TEST MODE label if a testing key set was used, it allows us stimulating the payment process during the development without cash flow in the real world.

Stripe also provide some pre-define bank account for the testing use, you can refer to this official page for advanced details.

After the payment process finishes or the consumer regret and return to the previous page, they will be redirected to the success_url or cancel_url we specified for the session previously. I believe front-end engineers will also be very happy about this.

Check Payment Status of the Session

Handling Webhook Events from Stripe

For each key step during the payment process, Stripe has a corresponding event to be raised. Such as a payment intent was created, a payment method was attached, and a checkout session was completed, etc.

You can give it a try quickly with the stripe client tool, follow the installation guides, and log in to your account.

Now you are able to forward the webhook event to the localhost of your device with the command.

stripe listen --forward-to localhost:{YOUR_SERVICE_PORT}/{YOUR_HANDLER_ROUTE}

Stripe will give you a webhook signing secret for constructing an event properly while it is ready to forward.

The webhook event just like a POST request to our service, we can handle them and execute different processes depends on the data within the request body.

Besides, handling errors properly is necessary for avoiding malicious requests, after all, it is possible to reach this endpoint for anyone. I just simply print out the error with some pre-defined error type from the stripe SDK here, but it should be more cautious in the production environment.

Long Polling the Payment Status

However, webhooks are not 100% reliable, a poor wi-fi, an unexpected error, or even a network traffic peak are all potential risks that may cause a webhook event lost. And each time an incomplete payment records or incorrect payment result could be fatal for your business logic.

Unfortunately, it is almost impossible to solve this issue fundamentally, stripe can hardly identify each webhook request is received properly or not.

Webhook is definitely an ideal solution to build a passive event-driven mechanism, but long polling for a status check is still needed for fault tolerance.

The stripe.PaymentIntent.retrieve method help us access the payment object via the payment intent identifier, it is the critical relation between almost all object inside a payment lifecycle.

The status field inside the return JSON object describes the current status and can be used to check whether it is completed.

I would suggest you execute this status check task cyclically with an exponential growth time interval until the payment was succeeded or exceeds the maximum delay time (maybe 24 hours), which strikes a balance between load and tolerance.

Refund a Payment

Sometimes we will need to refund a payment to the consumer, it is also friendly to software engineers in the stripe SDK.

Actually, we can still plan a mechanism to make sure the refund was succeeded, but it is the same as above so I will skip this part :)

Link Partner’s Account

If you are operating a platform service, your users are not all consumers, some of them act as sellers. Stripe will charge a small fee for each payment, of course we can do the same.

To achieve that, we may spend some effort to make each of the sellers becomes a connected account of our main account, so that revenue can flow unimpeded.

Onboarding Flow

Stripe also intimately packaged the entire process of seller onboarding, all we need to implement is initialize an account link object and redirect the user to the corresponding URL for the follow-up process.

Here I assume all seller is new to stripe, so I create an account for each of them, you can use the account id of your seller directly if they are already users of Stripe.

You will be asked to provide some business information of your company in this part for activating the connect account function, if everything was completed, Stripe will take your seller to the onboarding process.

Now it’s your seller’s turn to provide their company information, and we can check their status on the dashboard.

Application Fee

Stripe mainly provides two kinds of workflow for the platform provider to charge an application fee, one is to collect payments then payout after the application fee charged, the other one is enabled other businesses to accept payments directly then pay back to our main account.

I prefer the previous one because I think it is easier for backend engineer :D~

In order to make the fee charge available, we need to append account information on both server-side and client-side.

Most of the errors that developers encounter at this step are the checkout session is created successfully but the client-side is unable to access, that is caused by authorization issue during initialization, the logs of your browser would be helpful for debugging.

Update Related Codes

Whenever a checkout session was created with a seller account specified, it was applied to the entire payment life cycle. While we want to retrieve or refund that payment, the corresponding stripe account id is needed or it is unable to access.

Stripe really did an excellent job designing their SDK for software engineers to integrate online payment workflow, solve lots of pain points of other traditional third-party services.

Feel free to leave a comment for correction or discussion, I will be glad if you found the content is helpful and leave a clap or follow this publication. Hope everything in your payment service works fine :D

--

--

Rain Wu
Random Life Journal

A software engineer specializing in distributed systems and cloud services, desire to realize various imaginations of future life through technology.