From 8a811d9da4e443abd3fe616f8d5f0c1092f389bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 12 Jan 2018 13:09:11 +0100 Subject: [PATCH] Implement all charge events issue6960 review36831002 --- CHANGELOG | 1 + payment.py | 30 +++++++++++++--- tests/scenario_account_payment_stripe.rst | 44 +++++++++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d07b81ec5c..d0d6016ac9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Support all charge events * Support dispute Version 4.6.0 - 2017-10-30 diff --git a/payment.py b/payment.py index 33fdc71552..f457d65a15 100644 --- a/payment.py +++ b/payment.py @@ -496,8 +496,14 @@ class Account(ModelSQL, ModelView): type_ = payload['type'] if type_ == 'charge.succeeded': return self.webhook_charge_succeeded(data) + if type_ == 'charge.captured': + return self.webhook_charge_captured(data) elif type_ == 'charge.failed': return self.webhook_charge_failed(data) + elif type_ == 'charge.pending': + return self.webhook_charge_pending(data) + elif type_ == 'charge.refunded': + return self.webhook_charge_refunded(data) elif type_ == 'charge.dispute.created': return self.webhook_charge_dispute_created(data) elif type_ == 'charge.dispute.closed': @@ -510,7 +516,7 @@ class Account(ModelSQL, ModelView): return self.webhook_source_canceled(data) return None - def webhook_charge_succeeded(self, payload): + def webhook_charge_succeeded(self, payload, _event='charge.succeeded'): pool = Pool() Payment = pool.get('account.payment') @@ -519,16 +525,32 @@ class Account(ModelSQL, ModelView): ('stripe_charge_id', '=', charge['id']), ]) if not payments: - logger.error("charge.succeeded: No payment '%s'", charge['id']) + logger.error(": No payment '%s'", _event, charge['id']) for payment in payments: # TODO: remove when https://bugs.tryton.org/issue4080 with Transaction().set_context(company=payment.company.id): + if payment.state == 'succeeded': + Payment.fail([payment]) payment.stripe_captured = charge['captured'] + payment.stripe_amount = ( + charge['amount'] - charge['amount_refunded']) payment.save() - if charge['status'] == 'succeeded' and charge['captured']: - Payment.succeed([payment]) + if payment.amount: + if charge['status'] == 'succeeded' and charge['captured']: + Payment.succeed([payment]) + else: + Payment.fail([payment]) return bool(payments) + def webhook_charge_captured(self, payload): + return self.webhook_charge_succeeded(payload, _event='charge.captured') + + def webhook_charge_pending(self, payload): + return self.webhook_charge_succeeded(payload, _event='charge.pending') + + def webhook_charge_refunded(self, payload): + return self.webhook_charge_succeeded(payload, _event='charge.pending') + def webhook_charge_failed(self, payload): pool = Pool() Payment = pool.get('account.payment') diff --git a/tests/scenario_account_payment_stripe.rst b/tests/scenario_account_payment_stripe.rst index 9695b88dd8..943ff60b5b 100644 --- a/tests/scenario_account_payment_stripe.rst +++ b/tests/scenario_account_payment_stripe.rst @@ -277,3 +277,47 @@ Capture lower amount:: u'succeeded' >>> bool(payment.stripe_captured) True + +Simulate charge.refunded event with partial amount:: + + >>> StripeAccount.webhook([stripe_account], { + ... 'type': 'charge.refunded', + ... 'data': { + ... 'object': { + ... 'id': payment.stripe_charge_id, + ... 'object': 'charge', + ... 'amount': 4200, + ... 'amount_refunded': 4000, + ... 'captured': True, + ... 'status': 'succeeded', + ... }, + ... }, + ... }, {}) + [True] + >>> payment.reload() + >>> payment.amount + Decimal('2.00') + >>> payment.state + u'succeeded' + +Simulate charge.refunded event with full amount:: + + >>> StripeAccount.webhook([stripe_account], { + ... 'type': 'charge.refunded', + ... 'data': { + ... 'object': { + ... 'id': payment.stripe_charge_id, + ... 'object': 'charge', + ... 'amount': 4200, + ... 'amount_refunded': 4200, + ... 'captured': True, + ... 'status': 'succeeded', + ... }, + ... }, + ... }, {}) + [True] + >>> payment.reload() + >>> payment.amount + Decimal('0.00') + >>> payment.state + u'failed'