Skip to content
Snippets Groups Projects
Commit 7807bc85 authored by Damien Bouvy's avatar Damien Bouvy Committed by fw-bot
Browse files

[FIX] payment_stripe_sca: on-the-fly customer conversion


Payment tokens created before the installation of this module and that
used the Charge API did not need to keep the card reference on Odoo's
side - since we were allowed by the API to simply specify a customer
reference when creating a charge and it would take the default one for
that customer. Odoo creates one customer per payment token (even if it's
the same partner), so there was no uncertainty there.

Now, with the PaymentIntent API, the payment method reference is
mandatory. We have a field to keep it in db, but this info needs to be
retrieved for tokens created before the module's installation. This fix
introduces that remote call.

closes odoo/odoo#37206

X-original-commit: 1b760a98
Signed-off-by: default avatarNicolas Martinelli (nim) <nim@odoo.com>
parent 1067f3bd
Branches
Tags
No related merge requests found
......@@ -177,6 +177,9 @@ class PaymentTransactionStripeSCA(models.Model):
"_stripe_create_payment_intent: Values received:\n%s", pprint.pformat(res)
)
return res
if not self.payment_token_id.stripe_payment_method:
# old token before installing stripe_sca, need to fetch data from the api
self.payment_token_id._stripe_sca_migrate_customer()
charge_params = {
"amount": int(
self.amount
......@@ -367,3 +370,38 @@ class PaymentTokenStripeSCA(models.Model):
"This method can no longer be used with the payment_stripe_sca module."
)
def _stripe_sca_migrate_customer(self):
"""Migrate a token from the old implementation of Stripe to the SCA one.
In the old implementation, it was possible to create a valid charge just by
giving the customer ref to ask Stripe to use the default source (= default
card). Since we have a one-to-one matching between a saved card, this used to
work well - but now we need to specify the payment method for each call and so
we have to contact stripe to get the default source for the customer and save it
in the payment token.
This conversion will happen once per token, the first time it gets used following
the installation of the module."""
self.ensure_one()
url = "customers/%s" % (self.acquirer_ref)
data = self.acquirer_id._stripe_request(url, method="GET")
sources = data.get('sources', {}).get('data', [])
pm_ref = False
if sources:
if len(sources) > 1:
_logger.warning('stripe sca customer conversion: there should be a single saved source per customer!')
pm_ref = sources[0].get('id')
else:
url = 'payment_methods'
params = {
'type': 'card',
'customer': self.acquirer_ref,
}
payment_methods = self.acquirer_id._stripe_request(url, params, method='GET')
cards = payment_methods.get('data', [])
if len(cards) > 1:
_logger.warning('stripe sca customer conversion: there should be a single saved source per customer!')
pm_ref = cards and cards[0].get('id')
if not pm_ref:
raise ValidationError(_('Unable to convert Stripe customer for SCA compatibility. Is there at least one card for this customer in the Stripe backend?'))
self.stripe_payment_method = pm_ref
_logger.info('converted old customer ref to sca-compatible record for payment token %s', self.id)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment