Stripe provides a clean and simple API to charge credit card. As credit card is managed at browser level, the server (trytond) does not need to be PCI DSS compliant.
Proposition
We need to store the Stripe key on the journal payment of type “Stripe”.
We need also to store if needed the Customer to be able to make recurring charge without asking credit card each time. This will be stored on a new Model account.payment.stripe.customer (similar to SEPA mandate). If the record can not be deleted but instead it will be inactivated. In this case, it will be deleted on Stripe and the key will be erased periodically by a cron task.
We need a way to retrieve token for a payment if we do not have a Customer key. This process to not require PCI DSS will need to happen in the browser of the user. For that, we should deliver at an URL a minimal web page which display the Checkout form and retrieve the posted data. To ensure this form will only be used by allowed user, we will use a token in the form that will be generated by payment.
The same work-flow will be implemented for the Customer registration (but without any amount).
Of course this checkout method could completely be skipped in favour of a custom website implementation. The purpose of this checkout from client is for telemarketer or POS.
Tryton payments are processed by group but Strip API process one payment per post. So we need to desynchronise the Tryton processing and the post to get transactional integrity. A cron task will post charge for all Stripe payments which are in the state processing (using a generated UUID for idempotents). The Charge request will use the token stored on the payment or the Customer id. If the charge succeed then the payment is passed to succeeded also. If the charge fails depending on the error, the payment will be failed (card_error ) or retried later (technical issue).
Yes the documentation says so. I guess it is because the Customer ID is linked to your account.
But any way, we will not expose it to any user using a field access.
The Customer is indeed a token that allow to debit a card. So a Party could (even if it is not really useful) have many cards and so many Customer key.
The token for credit card can be used only once so I think it is correct to store it on the payment because it will be paid only once.
I don’t think this is correct. It is possible to store a credit card. A customer record on the Stripe side can have multiple credit cards. It is possible to define which card to charge in the charge object [1].
On the stripe side there are 3 objects: customer, card and payment. I feel like we can decide whether we map these to 3 or 2 models on the Tryton side.
map 3 models:
party → customer
card ( new model ) → card
payment → payment
With the second option, we could store the Stripe customer ID on the card model only and obviously map other “detail” fields from the party to the Stripe customer object.
One thing I am not sure about is where to store Stripe API credentials.
Best practice is to store these in environment variables or conf file, but this does not make sense to me in regards to Tryton because of the fact that multiple databases can be run in a single instance and it is likely that each database should have different credentials.
Stripe is also capable of processing ACH payments, which are useful here in the US. If you can build this feature into the module as well I would be happy to contribute.