[FIX] pos_stripe: use payment provider method for payment capture

Before this commit:
 If you make a PoS payment using a Stripe terminal, you will have
 the following JS Traceback:
 ```js
 TypeError: Cannot read properties of undefined (reading 'data')
    at Proxy.captureAfterPayment
 ```

 This happens on the line:
 `capturePayment.charges.data[0].payment_method_details.card_present.brand;`
 It occurs as Stripe API most recent version does not provide the
 `charges` value anymore.
 > The charges property on PaymentIntent has been removed
 source:
 https://stripe.com/docs/upgrades#2022-11-15

After this commit:
 We skip the data if not mentioned on the JS side.
 In addition of that, we use the `_stripe_make_request`
 method of the Stripe payment provider as it
 force in its header to use a certain Stripe API version
 compatible with the features that we are looking for.

opw-3097460

closes odoo/odoo#108851

X-original-commit: 6a6057caf63d7e6a60dac190b2ea1ebb954d8f6a
Signed-off-by: Loan (LSE) <lse@odoo.com>
Signed-off-by: Quentin Lejeune (qle) <qle@odoo.com>
This commit is contained in:
Loan (LSE)
2022-12-30 17:24:49 +01:00
committed by =
parent d040a518bc
commit fd0d077a7a
2 changed files with 13 additions and 12 deletions
+11 -11
View File
@@ -31,10 +31,17 @@ class PosPaymentMethod(models.Model):
raise ValidationError(_('Terminal %s is already used on payment method %s.',\
payment_method.stripe_serial_number, existing_payment_method.display_name))
def _get_stripe_payment_provider(self):
stripe_payment_provider = self.env['payment.provider'].search([('code', '=', 'stripe')], limit=1)
if not stripe_payment_provider:
raise UserError(_("Stripe payment provider is missing"))
return stripe_payment_provider
@api.model
def _get_stripe_secret_key(self):
stripe_secret_key = self.env['payment.provider'].search([('code', '=', 'stripe')], limit=1).stripe_secret_key
stripe_secret_key = self._get_stripe_payment_provider().stripe_secret_key
if not stripe_secret_key:
raise ValidationError(_('Complete the Stripe onboarding.'))
@@ -95,8 +102,7 @@ class PosPaymentMethod(models.Model):
if not self.env.user.has_group('point_of_sale.group_pos_user'):
raise AccessError(_("Do not have access to fetch token from Stripe"))
endpoint = ('https://api.stripe.com/v1/payment_intents/%s/capture') % \
(werkzeug.urls.url_quote(paymentIntentId))
endpoint = ('payment_intents/%s/capture') % (werkzeug.urls.url_quote(paymentIntentId))
data = None
if amount is not None:
@@ -104,16 +110,10 @@ class PosPaymentMethod(models.Model):
"amount_to_capture": self._stripe_calculate_amount(amount),
}
try:
resp = requests.post(endpoint, data=data, auth=(self.sudo()._get_stripe_secret_key(), ''), timeout=TIMEOUT)
except requests.exceptions.RequestException:
_logger.exception("Failed to call stripe_capture_payment endpoint")
raise UserError(_("There are some issues between us and Stripe, try again later."))
return resp.json()
return self._get_stripe_payment_provider()._stripe_make_request(endpoint, data)
def action_stripe_key(self):
res_id = self.env['payment.provider'].search([('code', '=', 'stripe')], limit=1).id
res_id = self._get_stripe_payment_provider().id
# Redirect
return {
'name': _('Stripe'),
@@ -141,7 +141,8 @@ const PaymentStripe = PaymentInterface.extend({
captureAfterPayment: async function (processPayment, line) {
const capturePayment = await this.capturePayment(processPayment.paymentIntent.id);
line.card_type = capturePayment.charges.data[0].payment_method_details.card_present.brand;
if (capturePayment.charges)
line.card_type = capturePayment.charges.data[0].payment_method_details.card_present.brand;
line.transaction_id = capturePayment.id;
},