def test_get_from_govuk_payment_with_invalid_input(self): """ Test that if the govuk_payment doesn't have the expected structure, GovUkPaymentStatusException is raised. """ scenarios = [ {'state': {'status': 'invalid'}}, {'state': {'another-key': 'another-value'}}, ] for govuk_payment in scenarios: with self.assertRaises(GovUkPaymentStatusException): GovUkPaymentStatus.get_from_govuk_payment(govuk_payment)
def test_payment_timed_out_after_capturable_with_invalid_input(self): """ Test that if the govuk_payment doesn't have the expected format, GovUkPaymentStatusException is raised. """ scenarios = [ {'state': {'status': 'invalid'}}, {'state': {'another-key': 'another-value'}}, ] for govuk_payment in scenarios: with self.assertRaises(GovUkPaymentStatusException): GovUkPaymentStatus.payment_timed_out_after_capturable(govuk_payment)
def test_payment_didnt_time_out(self): """ Test that if the govuk payment is None or it's not in failed status because of timeout, the method returns False. """ scenarios = [ None, { 'state': { 'status': 'created' } }, { 'state': { 'status': 'started' } }, { 'state': { 'status': 'submitted' } }, { 'state': { 'status': 'capturable' } }, { 'state': { 'status': 'success' } }, { 'state': { 'status': 'failed' } }, { 'state': { 'status': 'failed', 'code': 'P0001' } }, { 'state': { 'status': 'cancelled' } }, { 'state': { 'status': 'error' } }, ] for govuk_payment in scenarios: self.assertFalse( GovUkPaymentStatus.payment_timed_out_after_capturable( govuk_payment), )
def test_get_from_govuk_payment(self): """ Test that get_from_govuk_payment returns the right GovUkPaymentStatus. """ scenarios = [ (None, None), ({}, None), ( {'state': {'status': 'created'}}, GovUkPaymentStatus.created, ), ( {'state': {'status': 'started'}}, GovUkPaymentStatus.started, ), ( {'state': {'status': 'submitted'}}, GovUkPaymentStatus.submitted, ), ( {'state': {'status': 'capturable'}}, GovUkPaymentStatus.capturable, ), ( {'state': {'status': 'success'}}, GovUkPaymentStatus.success, ), ( {'state': {'status': 'failed'}}, GovUkPaymentStatus.failed, ), ( {'state': {'status': 'cancelled'}}, GovUkPaymentStatus.cancelled, ), ( {'state': {'status': 'error'}}, GovUkPaymentStatus.error, ), ] for govuk_payment, expected_status in scenarios: actual_status = GovUkPaymentStatus.get_from_govuk_payment(govuk_payment) self.assertEqual(actual_status, expected_status)
def perform_update(self): payment_client = PaymentClient() payments = payment_client.get_incomplete_payments() for payment in payments: if not self.should_be_checked(payment): continue payment_ref = payment['uuid'] govuk_id = payment['processor_id'] try: govuk_payment = payment_client.get_govuk_payment(govuk_id) previous_govuk_status = GovUkPaymentStatus.get_from_govuk_payment( govuk_payment) govuk_status = payment_client.complete_payment_if_necessary( payment, govuk_payment) # not yet finished and can't do anything so skip if govuk_status and not govuk_status.finished(): continue if previous_govuk_status != govuk_status: # refresh govuk payment to get up-to-date fields (e.g. error codes) govuk_payment = payment_client.get_govuk_payment(govuk_id) # if here, status is either success, failed, cancelled, error # or None (in case of govuk payment not found) payment_client.update_completed_payment(payment, govuk_payment) except OAuth2Error: logger.exception( 'Scheduled job: Authentication error while processing %s' % payment_ref) except RequestException as error: error_message = 'Scheduled job: Payment check failed for ref %s' % payment_ref if hasattr(error, 'response') and hasattr( error.response, 'content'): error_message += '\nReceived: %s' % error.response.content logger.exception(error_message) except GovUkPaymentStatusException: # expected much of the time pass
def test_payment_did_time_out_but_before_capturable(self): """ Test that if the govuk payment failed because of timeout but the payment was not in capturable status at some point in the past, the method returns False. """ payment_id = 'payment-id' govuk_payment = { 'payment_id': payment_id, 'state': { 'status': 'failed', 'code': 'P0020', 'message': 'Payment expired', 'finished': True, }, } with responses.RequestsMock() as rsps: rsps.add( rsps.GET, govuk_url(f'/payments/{payment_id}/events/'), status=200, json={ 'events': [ { 'payment_id': payment_id, 'state': { 'status': 'submitted', 'finished': False, }, }, ], 'payment_id': payment_id, }, ) self.assertFalse( GovUkPaymentStatus.payment_timed_out_after_capturable( govuk_payment), )