Stripe - payments platform

Summary of challenges encountered during big integration of Stripe with e-commerce service

Krzysztof "noisy" Szumny

PSD2 and New Regulations

PSD2 and New Regulations

In a typical marketplace setup, where a platform acts as an intermediary for both buyers and sellers without itself selling the product or service, the platform can no longer receive payments that are owed by buyers to sellers. If it does, it will have to obtain a payments license from a regulator and become a regulated business.

Strong Customer Authentication (SCA)

Strong Customer Authentication (SCA)

Migration

Stripe

Charge API

Stripe

Payment Intents API

Demo

Chalanges

Challenge #1: Understanding the scope

Charges/PI API

Stripe Connect

Stripe JS & Python Libraries

implementation

&

configuration

Many different products

Mixed interface for multiple features

stripe.PaymentIntent.create(
   confirm=True,
   amount=self.amount,
   currency=self.currency,
   description="full payment (%s)" % self.order.id,
   statement_descriptor=self.statement_descriptor,
   idempotency_key="charge-%s" % self.order.id,
   confirmation_method='automatic',
   setup_future_usage='off_session',
   return_url=url,
   payment_method_options=payment_method_options,
   stripe_account=stripe_user_id,
   payment_method=shared_payment_method_id,
   application_fee_amount=self.application_fee,
)

Stripe Connect Related params

needed so function would behave like stripe.PaymentIntent.confirm

customizing the 3D Secure UI

  • https://stripe.com/docs/connect/charges
  • https://stripe.com/docs/payments/3d-secure/web#custom-iframe
  • https://stripe.com/docs/payments/cards/saving-cards-after-payment
  • https://stripe.com/docs/payments/payment-intents/use-cases#one-time-payments
  • https://stripe.com/docs/api/idempotent_requests
  • https://stripe.com/docs/api/payment_intents/create#create_payment_intent-confirm

          "saving card" related param

webhook related param

    consistency related param

 

API Documentation, brief description of all params:

https://stripe.com/docs/api/payment_intents/create

Challenge #2: Replacing payment API without a downtime

Stripe

Charge API

Stripe

Payment Intents API

Solution: Feature flipper

Challenge #3: Multiple workflows

Pitchup.com direct payment

  1. User makes a booking on Pitchup
  2. Pitchup.com charges user a reservation fee
  3. User pays a campsite when he arrives (by cash, credit card, etc)

Deferred payment

  1. User makes a booking on Pitchup, in advance (for example 2 months earlier)
  2. Pitchup.com charges user a reservation fee
  3. X days before an arrival, payment for campsite is initiated by Pitchup

Immediate combined payment

  1. User makes a booking on Pitchup (for example 5 days before an arrival)
  2. Pitchup charges user a full amount immediately (reservation fee + payment for campsite

Different payment methods

+ "saved" cards

A lot of different testing scenarios

Solution: Integration tests

charge_api/test_pitchup_payment.py::TestStripePitchupPaymentChargesAPI::test_stripe_pitchup_payment_with_stored_card PASSED [  3%]
charge_api/test_pitchup_payment.py::TestStripePitchupPaymentChargesAPI::test_stripe_pitchup_payment_without_store PASSED [  6%]
charge_api/test_pitchup_payment.py::TestStripePitchupPaymentChargesAPI::test_stripe_pitchup_payment_with_store PASSED [ 10%]
intents_api/test_immediate.py::test_stripe_immediate_payment_by_anonymous_user PASSED [ 13%]
intents_api/test_immediate.py::test_stripe_immediate_payment_with_store PASSED [ 16%]
intents_api/test_immediate.py::test_stripe_immediate_payment_with_stored_charges_api_card PASSED [ 20%]
intents_api/test_immediate.py::test_stripe_immediate_payment_without_store PASSED [ 23%]
intents_api/test_immediate.py::test_stripe_immediate_payment_with_stored_card PASSED [ 26%]
test_handler_base.py::TestStoreCardBase::test_get_payment_method_id PASSED [ 30%]
test_handler_base.py::TestStoreCardBase::test_get_stripe_token PASSED [ 33%]
intents_api/test_deferred.py::test_stripe_deferred_payment_without_store PASSED [ 36%]
intents_api/test_deferred.py::test_stripe_deferred_payment_by_anonymous_user PASSED [ 40%]
intents_api/test_deferred.py::test_stripe_deferred_payment_with_legacy_1st_payment PASSED [ 43%]
intents_api/test_deferred.py::test_stripe_deferred_payment_with_stored_card PASSED [ 46%]
intents_api/test_deferred.py::test_stripe_deferred_payment_with_store PASSED [ 50%]
charge_api/test_future_payment.py::test_stripe_future_payment_uses_correct_card PASSED [ 53%]
charge_api/test_future_payment.py::test_stripe_future_payment_no_user_stored_card PASSED [ 56%]
charge_api/test_future_payment.py::test_stripe_future_payment2_without_stored_card PASSED [ 60%]
charge_api/test_future_payment.py::test_stripe_future_payment_with_store PASSED [ 63%]
charge_api/test_future_payment.py::test_stripe_future_payment_to_correct_card PASSED [ 66%]
charge_api/test_future_payment.py::test_stripe_future_payment_without_store PASSED [ 70%]
charge_api/test_future_payment.py::test_stripe_future_payment_idempotent PASSED [ 73%]
charge_api/test_future_payment.py::test_stripe_future_payment_with_stored_card PASSED [ 76%]
intents_api/test_pitchup.py::test_stripe_pitchup_payment_with_store PASSED [ 80%]
intents_api/test_pitchup.py::test_stripe_pitchup_payment_with_stored_card PASSED [ 83%]
intents_api/test_pitchup.py::test_stripe_pitchup_payment_without_store PASSED [ 86%]
intents_api/test_pitchup.py::test_stripe_pitchup_payment_by_anonymous_user PASSED [ 90%]
charge_api/test_immediate_payment.py::test_stripe_immediate_payment_with_store PASSED [ 93%]
charge_api/test_immediate_payment.py::test_stripe_immediate_payment_with_stored_card PASSED [ 96%]
charge_api/test_immediate_payment.py::test_stripe_immediate_payment_without_store PASSED [100%]
================================================== 30 passed in 185.33 seconds =====================================================

Challenge #4: Multiple implementations

Pitchup.com direct payment

  1. User makes a booking on Pitchup
  2. Pitchup.com charges user a reservation fee
  3. User pays a campsite when he arrives (by cash, credit card, etc)

Deferred payment

  1. User makes a booking on Pitchup, in advance (for example 2 months earlier)
  2. Pitchup.com charges user a reservation fee
  3. X days before an arrival, payment for campsite is initiated by Pitchup

Immediate combined payment

  1. User makes a booking on Pitchup (for example 5 days before an arrival)
  2. Pitchup charges user a full amount immediately (reservation fee + payment for campsite

Direct Payment

Implementation

Immediate Payment

Implementation

Deferred Payment

Implementation

Challenge #4: Multiple implementations

Pitchup.com direct payment

  1. User makes a booking on Pitchup
  2. Pitchup.com charges user a reservation fee
  3. User pays a campsite when he arrives (by cash, credit card, etc)

Deferred payment

  1. User makes a booking on Pitchup, in advance (for example 2 months earlier)
  2. Pitchup.com charges user a reservation fee
  3. X days before an arrival, payment for campsite is initiated by Pitchup

Immediate combined payment

  1. User makes a booking on Pitchup (for example 5 days before an arrival)
  2. Pitchup charges user a full amount immediately (reservation fee + payment for campsite

Common interface

PaymentTypeAHandler

BasePaymentHandler

PaymentTypeBHandler

PaymentTypeCHandler

Challenge #5: Too simple examples in Stripe documentation

  • How to make a simple transaction via Stripe Payment Intent API
  • How to "save a card", so use could reuse it in the future
  • How to handle 3D Secure Authorization
  • How to handle Stripe Webhook events

Frontend

Backend

3D Secure

Pop up

Stripe

Payment Intent creation

Actual Payment

Stripe JS Library

Stripe Python Library

Frontend

Backend

3D Secure

Pop up

Stripe

Payment Intent creation

Actual Payment

Stripe JS Library

Stripe Python Library

Suggestion: Pair programming

Challenge #6: Setup of Stripe Connect

Your Stripe Account

Connected accounts

Webhook

Webhook connect

Be careful to not connect your account to itself

Challenge #7: Webhook events

Your Stripe Account

Connected accounts

Webhook

Webhook connect

stripe listen \ 
       --events payment_intent.succedded,payment_intent.payment_failed \
       --forward-to localhost:9000/events
       
       
> Ready! Your webhook signing secret is whsec_2RoT8DNVbh6mVWKULRGvo64a304PjOaw (^C to quit)

Time consuming setup of webhook listener for local development

 

Two types of webhook endpoints

Your Stripe Account

Connected accounts

Webhook

Webhook connect

Events from connected account, from other platforms

Another Stripe Account

  • Format of webhook events is not always consistent
    • different structure, for events originated by actions from different API  

Challenge #8: Multiple environments

Your Stripe Account

Connected accounts

Webhook

Webhook connect

Your Stripe Account

Connected accounts

Your Stripe Account

Connected accounts

Suggestion: Setup new dedicated account(s)

Do I recommend Stripe?

Q&A

Stripe - payments platform

By noisy

Stripe - payments platform

  • 1,163