Developers March 23, 2020

How the heck do ya'all keep your payment logic organized?

Corstian

I am currently working with Stripe, and while I am truly impressed by the quality of their API's and well thought out models, I'm having a hard time properly implementing this within my own architecture.

The main problem I do have is dealing with all the edge cases. I'm trying to condense the logic exposed by stripe into three handlers which I want to expose to my own front-end, which on a conceptual level are:

  1. setPaymentMethod
  2. setSubscription
  3. cancelSubscription

I for one am quite allergic to messy code, and currently the logic dealing with creating a new subscription is more like conditional spaghetti. How do you keep your payment logic organized, and maybe more importantly, well tested including all edge cases?

To what levels have you gone to ensure payments can go through successfully? Am I the only one here being paranoid that people will be turned away because they are unable to get a paid subscription?

  1. 2

    A Stripe micro service with the following routes

    POST /customers
    POST /subscriptions
    DELETE /subscriptions

    You likely want to include reCAPTCHA to prevent card testing & maybe want to listen for webhooks

    POST /recaptcha
    POST /webhooks/invoice/payment-succeeded

    1. 1

      What do you do with this information in your backend? Do you make a call to the Stripe API's every time you need some subscription related information? How do you deal with the situation when Strong Customer Authentication (SCA) is required (which I believe is mainly an issue in Europe)?

      1. 1

        Stripe has a number of backend SDKs that you can use within each route's logic. Auth should be decoupled from Stripe. Your visitor can create an account with you which provisions an account within your auth & then a new customer in Stripe. Your auth provider should be able to generate short lived JWTs that you can include in each request header to any of your micro services. You can then use your auth providers backend SDK (they should have one) to verify the JWT/request as legit & then safely interact with Stripe through their SDK.

      2. 1

        This comment was deleted 2 months ago.

        1. 1

          SCA would require customers to sign in with their bank when making a purchase. Stripe would automatically handle this by emailing the customer, but giving this is a break of their flow I prefer to include this in the payment process.

          Maybe you were thinking about PCI compliance.

          1. 2

            This comment was deleted 2 months ago.

            1. 2

              There you have a great point, but given I have it working it would be a waste to throw it away wouldn't it 😎

  2. 1

    Decide on some business rules up front that will limit the edge cases you need to account for. For example, many sites don't offer refunds. If you cancel, your subscription just expires at the end of the current period instead of renewing. Now you don't have to deal with refunds.

    If you are mainly thinking through the backend components of dealing with Stripe, you may want to check this out: https://www.masteringmodernpayments.com/. It's written for Ruby on Rails, but the concepts are laid out in a simple and clear manner.

    1. 1

      Thanks for the resource! Though it's offline now, I'm able to access it through the wayback machine.

      Seems useful! I can definitely relate to the introduction :)

  3. 1

    This is a great question. I haven’t actually implemented stripe in https://storycreatorapp.com I plan to do that really soon. My first set of customers I just had them pay me via PayPal.

    I’m thinking it shouldn’t be too hard but this questions has me rethinking that. Perhaps you’re overthinking it? Do you have need for the code in multiple places in the UI? You could just write a react hook if you need it in multiple locations.

    I’m thinking I’ll just need it in one simple payment form. So a hook might be overkill. Will just have a nice container for the payments page and break up the components and functions into little pieces. Testing is easier when functions are broken up into digestible meaningful chunks.

    Once I actually implement it I’ll chime back in :)

    1. 1

      I'm looking forward to hearing about your experiences! The Stripe Elements API for React includes a context which can be used via hooks, hence this is in fact the least of my worries.

      The most difficult part IMHO is dealing with the server side of things, where various checks have to be done, depending on the situation. Creating a customer in Stripe, adding (tokenized) card details, choosing the subscription, and handling several edge cases such as a re-subscribe, failed (initial) payments, trial periods, and up and down grades.

      I have started writing a blogpost on the way I deal with payments, primarily to keep myself focused through all the details. Maybe it might help you through some details later on!

  4. 1

    This comment was deleted 2 months ago.

  5. 1

    This comment was deleted 5 months ago.

    1. 2

      Interesting template! Few questions;

      • What's the reason you went with collecting credit card information (hence subjecting yourself to PCI compliance audits) instead of going with Stripe Elements?
      • Any specific reason you require a certain order of requests? (For example, the requirement to cancel an existing subscription before creating a new one)
      • Listing subscriptions for a customer will include cancelled subscriptions, right?

      Besides that the logic seems pretty familiar; lots of if statements. Also, I only use the payment intents as a side effect of creating a subscription, and accompanying charge.

      1. 1

        This comment was deleted 5 months ago.

        1. 1

          In the error code you say the balance carries over when cancelling the subscription. How do you manage to prorate without modifying the existing subscription?

          On multiple subscriptions; I understand the design choice, but looking back I think my question is based too much on my own practice of running endpoints to get something done (setSubscription for example, which creates or updates a subscription) instead of having separate CRUD operations, when it makes sense. Again, thanks for sharing your template!

Recommended Posts