def _order_requested(sender, order, **kwargs): # Check the status at PSP if status is still locked if order.status == StatusDefinition.LOCKED: order_payment = OrderPayment.get_latest_by_order(order) service = PaymentService(order_payment) service.check_payment_status()
def check_status(self, request, pk=None): order_payment = OrderPayment.objects.get(pk=pk) service = PaymentService(order_payment) service.check_payment_status() order_payment_url = reverse('admin:payments_orderpayment_change', args=(order_payment.id,)) response = HttpResponseRedirect(order_payment_url) return response
def get_redirect_url(self, *args, **kwargs): order_payment = get_object_or_404(OrderPayment, id=kwargs['order_payment_id']) service = PaymentService(order_payment) service.check_payment_status() return "{0}/orders/{1}/success".format(get_current_host(), order_payment.order.id)
def perform_update(self, serializer): serializer.save(amount=serializer.validated_data['order'].total) # store integration_data in non-persisted card_data field serializer.instance.card_data = serializer.validated_data[ 'integration_data'] service = PaymentService(serializer.instance) try: service.check_payment_status() except PaymentException as error: raise ParseError(detail=str(error))
def check_payment_statuses(order_payments, tenant): connection.set_tenant(tenant) with LocalTenant(tenant, clear_tenant=True): for order_payment in order_payments: service = PaymentService(order_payment) try: service.check_payment_status() except (PaymentException, TypeError): pass
def post(self, request, *args, **kwargs): payload = json.loads(request.body)['data'] transaction_reference = payload["collection_request"]["id"] payment = get_object_or_404( BeyonicPayment, transaction_reference=transaction_reference) service = PaymentService(payment.order_payment) try: service.check_payment_status() return HttpResponse('success') except PaymentException: return HttpResponse('success')
def check_status(self, request, pk=None): order_payment = OrderPayment.objects.get(pk=pk) service = PaymentService(order_payment) try: service.check_payment_status() except PaymentException as e: self.message_user(request, 'Error checking status {}'.format(e), level='WARNING') order_payment_url = reverse('admin:payments_orderpayment_change', args=(order_payment.id, )) response = HttpResponseRedirect(order_payment_url) return response
class TestPaymentLogger(BluebottleTestCase, FsmTestMixin): @patch('bluebottle.payments_docdata.adapters.gateway.DocdataClient') def setUp(self, mock_client): super(TestPaymentLogger, self).setUp() # Mock response to creating the payment at docdata instance = mock_client.return_value instance.create.return_value = {'order_key': 123, 'order_id': 123} self.order = OrderFactory.create(total=35) self.order_payment = OrderPaymentFactory.create( payment_method='docdataIdeal', order=self.order, integration_data={'default_pm': 'ideal'}) self.service = PaymentService(self.order_payment) def test_create_payment_create_log(self): """ This test will start the process of creating a new payment and tests if a log associated has been created """ # Get the number of logs in the table last_log = PaymentLogEntry.objects.all().order_by('-timestamp')[:1][0] # The latest entry should be for the payment associated with this test self.assertEqual(last_log.payment_id, self.order_payment.payment.id) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_authorized_status_logged(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalAcquirerApproved': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() last_log = PaymentLogEntry.objects.all().order_by('-timestamp')[:1][0] # Check that the status change was logged self.assertEqual(last_log.payment_id, self.order_payment.payment.id) self.assertEqual( last_log.message, 'DocdataPayment object - a new payment status authorized') self.assertEqual(last_log.level, 'INFO')
def get(self, request, **kwargs): merchant_order_id = kwargs["merchant_order_id"] try: # Try to load new style OrderPayment order_payment_id = merchant_order_id.split("-")[0] order_payment = OrderPayment.objects.get(pk=order_payment_id) except OrderPayment.DoesNotExist: # Try to load old style DocdataPayment. try: payment = DocdataPayment.objects.get(merchant_order_id=merchant_order_id) order_payment = payment.order_payment except DocdataPayment.DoesNotExist: raise Exception("Couldn't find Payment for merchant_order_id: {0}".format(merchant_order_id)) service = PaymentService(order_payment) service.check_payment_status() return HttpResponse("success")
class TestPaymentLogger(BluebottleTestCase, FsmTestMixin): @patch.object(DocdataClient, 'create') def setUp(self, mock_client_create): super(TestPaymentLogger, self).setUp() mock_client_create.return_value = {'order_key': 123, 'order_id': 123} self.order = OrderFactory.create(total=35) self.order_payment = OrderPaymentFactory.create( payment_method='docdataIdeal', order=self.order, integration_data={'default_pm': 'ideal'}) self.service = PaymentService(self.order_payment) def test_create_payment_create_log(self): """ This test will start the process of creating a new payment and tests if a log associated has been created """ # Get the number of logs in the table last_log = PaymentLogEntry.objects.all().order_by('-timestamp')[:1][0] # The latest entry should be for the payment associated with this test self.assertEqual(last_log.payment_id, self.order_payment.payment.id) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_authorized_status_logged(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalAcquirerApproved': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() last_log = PaymentLogEntry.objects.all().order_by('-timestamp')[:1][0] # Check that the status change was logged self.assertEqual(last_log.payment_id, self.order_payment.payment.id) self.assertEqual(last_log.message, 'DocdataPayment object - a new payment status authorized') self.assertEqual(last_log.level, 'INFO')
def get(self, request, **kwargs): merchant_order_id = kwargs['merchant_order_id'] try: # Try to load new style OrderPayment order_payment_id = merchant_order_id.split('-')[0] order_payment = OrderPayment.objects.get(pk=order_payment_id) except OrderPayment.DoesNotExist: # Try to load old style DocdataPayment. try: payment = DocdataPayment.objects.get( merchant_order_id=merchant_order_id) order_payment = payment.order_payment except DocdataPayment.DoesNotExist: raise Exception( "Couldn't find Payment for merchant_order_id: {0}".format( merchant_order_id)) service = PaymentService(order_payment) service.check_payment_status() return HttpResponse('success')
def reload_status(self, request, queryset): for order in queryset.all(): for order_payment in order.order_payments.all(): service = PaymentService(order_payment) service.check_payment_status()
def reload_status(self, request, queryset): for order in queryset.all(): for order_payment in order.order_payments.all(): service = PaymentService(order_payment) service.check_payment_status()
def _order_requested(sender, order, **kwargs): # Check the status at PSP if status is still locked if order.status == StatusDefinition.LOCKED: order_payment = OrderPayment.get_latest_by_order(order) service = PaymentService(order_payment) service.check_payment_status()
class PaymentsDocdataTestCase(BluebottleTestCase, FsmTestMixin): @patch('bluebottle.payments_docdata.adapters.gateway.DocdataClient') def setUp(self, mock_client): super(PaymentsDocdataTestCase, self).setUp() # Mock response to creating the payment at docdata instance = mock_client.return_value instance.create.return_value = {'order_key': 123, 'order_id': 123} # Mock create payment patch.object(DocdataPaymentAdapter, 'create_payment', fake_create_payment) self.order = OrderFactory.create() self.order_payment = OrderPaymentFactory.create(order=self.order, payment_method='docdataIdeal', integration_data={ 'default_pm': 'ideal'}) self.service = PaymentService(order_payment=self.order_payment) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_authorized_status(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalAcquirerApproved': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order_payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order, StatusDefinition.PENDING) mock_transaction.assert_called_once_with( mock_fetch_status.return_value.payment[0]) @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_transaction(self, mock_fetch_status): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalAcquirerApproved': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order_payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order, StatusDefinition.PENDING) transaction = Transaction.objects.get() self.assertEqual(transaction.authorization_amount, 1000) self.assertEqual(transaction.raw_response, str(mock_fetch_status.return_value.payment[0])) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_new(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response('NEW') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.STARTED) self.assert_status(self.order_payment, StatusDefinition.STARTED) self.assert_status(self.order, StatusDefinition.LOCKED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_redirected(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'REDIRECTED_FOR_AUTHORIZATION') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.STARTED) self.assert_status(self.order_payment, StatusDefinition.STARTED) self.assert_status(self.order, StatusDefinition.LOCKED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_authenticated(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHENTICATED') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.STARTED) self.assert_status(self.order_payment, StatusDefinition.STARTED) self.assert_status(self.order, StatusDefinition.LOCKED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_error(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZATION_FAILED') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.FAILED) self.assert_status(self.order_payment, StatusDefinition.FAILED) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_settled(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.SETTLED) self.assert_status(self.order_payment, StatusDefinition.SETTLED) self.assert_status(self.order, StatusDefinition.SUCCESS) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_chargeback(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000', 'totalChargedback': '1000'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.CHARGED_BACK) self.assert_status(self.order_payment, StatusDefinition.CHARGED_BACK) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_refund(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000', 'totalRefunded': '1000'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.REFUNDED) self.assert_status(self.order_payment, StatusDefinition.REFUNDED) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_chargeback_refund(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000', 'totalRefunded': '500', 'totalChargedback': '500'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.REFUNDED) self.assert_status(self.order_payment, StatusDefinition.REFUNDED) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_two_payments(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', payments=[{ 'id': '1234', 'status': 'FAILED', 'amount': '1000', 'paymentMethod': 'MASTERCARD' }, { 'id': '12345', 'status': 'AUTHORIZED', 'amount': '1000', 'paymentMethod': 'MASTERCARD' }], totals={'totalCaptured': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.SETTLED) self.assert_status(self.order_payment, StatusDefinition.SETTLED) self.assert_status(self.order, StatusDefinition.SUCCESS) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_partially_settled(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '500', 'totalRegistered': '1000'} ) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.UNKNOWN) self.assert_status(self.order_payment, StatusDefinition.UNKNOWN) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_failed_success_status(self, mock_fetch_status, mock_transaction): # Check the order can go from failed to success when the payment goes from # cancelled to paid. # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response('CANCELED') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.CANCELLED) self.assert_status(self.order_payment, StatusDefinition.CANCELLED) self.assert_status(self.order, StatusDefinition.FAILED) # Check that the status propagated through to order mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={'totalCaptured': '1000', 'totalRegistered': '1000'} ) self.service.check_payment_status() self.assert_status(self.order_payment, StatusDefinition.SETTLED) self.assert_status(self.order, StatusDefinition.SUCCESS) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_no_payment_method_change(self, mock_fetch_status, mock_transaction): self.assertEquals(PaymentLogEntry.objects.count(), 1) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED') order = OrderFactory.create() order_payment = OrderPaymentFactory.create( order=order, payment_method='docdataCreditcard') docdata_payment = DocdataPaymentFactory.create( order_payment=order_payment, default_pm='mastercard', payment_cluster_id='1234', total_gross_amount=100) DocdataTransactionFactory.create(payment=docdata_payment, payment_method='VISA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get(reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataCreditcard') @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_payment_method_change(self, mock_fetch_status, mock_transaction): self.skipTest('Skipping test until we update it.') # Two payment log entries already exist: 2x 'a new payment status "started" ' self.assertEquals(PaymentLogEntry.objects.count(), 2) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED') order = OrderFactory.create() # Ensure that we use an existing payment_method or the adapter throws an exception order_payment = OrderPaymentFactory.create( order=order, payment_method='docdataPaypal') docdata_payment = DocdataPaymentFactory.create( order_payment=order_payment, default_pm='paypal', payment_cluster_id='1235', total_gross_amount=100) DocdataTransactionFactory.create(payment=docdata_payment, payment_method='VISA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get(reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataPaypal') # Check that all is logged correctly self.assertEquals( PaymentLogEntry.objects.filter(payment=docdata_payment).count(), 5) # The status changes triggers the # creation of more payment log entries log = PaymentLogEntry.objects.all()[0] self.assertEqual(log.message, "{0} - Payment method changed for payment with id {1}" " and order payment with id {2}.".format( docdata_payment, docdata_payment.id, docdata_payment.order_payment.id)) self.assertEqual(log.payment.id, docdata_payment.id) self.assertEqual(log.level, 'INFO') @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_unknown_payment_method_change(self, mock_fetch_status, mock_transaction): self.skipTest('Skipping test until we update it.') # Two payment log entries already exist: 2x 'a new payment status "started" ' self.assertEquals(PaymentLogEntry.objects.count(), 2) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED') order = OrderFactory.create() # Ensure that we use an existing payment_method or the adapter throws an exception order_payment = OrderPaymentFactory.create(order=order, payment_method='docdataPaypal') docdata_payment = DocdataPaymentFactory.create( order_payment=order_payment, default_pm='paypal', payment_cluster_id='1236', total_gross_amount=100) DocdataTransactionFactory.create(payment=docdata_payment, payment_method='BLABLABLA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get(reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataPaypal') # Check that all is logged correctly self.assertEquals( PaymentLogEntry.objects.filter(payment=docdata_payment).count(), 5) log = PaymentLogEntry.objects.all()[0] self.assertEqual(log.message, "{0} - Payment method '{1}' not found for payment " "with id {2} and order payment with id {3}.".format( docdata_payment, 'BLABLABLA', docdata_payment.id, docdata_payment.order_payment.id)) self.assertEqual(log.payment.id, docdata_payment.id) self.assertEqual(log.level, 'WARNING')
def _process_monthly_order(monthly_order, send_email=False): if monthly_order.processed: logger.info( "Order for {0} already processed".format(monthly_order.user)) return False ten_days_ago = timezone.now() + timezone.timedelta(days=-10) recent_orders = Order.objects.filter(user=monthly_order.user, order_type='recurring', updated__gt=ten_days_ago) if recent_orders.count() > 0: message = "Skipping '{0}' recently processed a recurring order for {1}:".format( monthly_order, monthly_order.user) logger.warn(message) for closed_order in recent_orders.all(): logger.warn("Recent Order Number: {0}".format(closed_order.id)) # Set an error on this monthly order monthly_order.error = message monthly_order.save() return False order = Order.objects.create(status=StatusDefinition.LOCKED, user=monthly_order.user, order_type='recurring') order.save() logger.info( "Creating Order for {0} with {1} donations".format(monthly_order.user, monthly_order.donations.count())) for monthly_donation in monthly_order.donations.all(): donation = Donation.objects.create(amount=monthly_donation.amount, project=monthly_donation.project, order=order) donation.save() integration_data = {'account_name': monthly_order.name, 'account_city': monthly_order.city, 'iban': monthly_order.iban, 'bic': monthly_order.bic, 'agree': True} order_payment = OrderPayment(order=order, user=monthly_order.user, payment_method=PAYMENT_METHOD, integration_data=integration_data) order_payment.save() try: service = PaymentService(order_payment) service.start_payment() except PaymentException as e: error_message = "Problem starting payment. {0}".format(e) monthly_order.error = "{0}".format(e.message) monthly_order.save() logger.error(error_message) order_payment.delete() order.delete() return False logger.debug("Payment for '{0}' started.".format(monthly_order)) monthly_order.processed = True monthly_order.error = '' monthly_order.save() # Try to update status service.check_payment_status() # Send an email to the user. if send_email: mail_monthly_donation_processed_notification(monthly_order) return True
class PaymentsDocdataTestCase(BluebottleTestCase, FsmTestMixin): @patch('bluebottle.payments_docdata.adapters.gateway.DocdataClient') def setUp(self, mock_client): super(PaymentsDocdataTestCase, self).setUp() # Mock response to creating the payment at docdata instance = mock_client.return_value instance.create.return_value = {'order_key': 123, 'order_id': 123} # Mock create payment patch.object(DocdataPaymentAdapter, 'create_payment', fake_create_payment) self.order = OrderFactory.create() self.order_payment = OrderPaymentFactory.create( order=self.order, payment_method='docdataIdeal', integration_data={'default_pm': 'ideal'}) self.service = PaymentService(order_payment=self.order_payment) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_authorized_status(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalAcquirerApproved': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order_payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order, StatusDefinition.PENDING) mock_transaction.assert_called_once_with( mock_fetch_status.return_value.payment[0]) @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_transaction(self, mock_fetch_status): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalAcquirerApproved': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order_payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order, StatusDefinition.PENDING) transaction = Transaction.objects.get() self.assertEqual(transaction.authorization_amount, 1000) self.assertEqual(transaction.raw_response, str(mock_fetch_status.return_value.payment[0])) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_new(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response('NEW') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.STARTED) self.assert_status(self.order_payment, StatusDefinition.STARTED) self.assert_status(self.order, StatusDefinition.LOCKED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_redirected(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'REDIRECTED_FOR_AUTHORIZATION') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.STARTED) self.assert_status(self.order_payment, StatusDefinition.STARTED) self.assert_status(self.order, StatusDefinition.LOCKED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_authenticated(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHENTICATED') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.STARTED) self.assert_status(self.order_payment, StatusDefinition.STARTED) self.assert_status(self.order, StatusDefinition.LOCKED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_error(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZATION_FAILED') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.FAILED) self.assert_status(self.order_payment, StatusDefinition.FAILED) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_settled(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.SETTLED) self.assert_status(self.order_payment, StatusDefinition.SETTLED) self.assert_status(self.order, StatusDefinition.SUCCESS) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_chargeback(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000', 'totalChargedback': '1000' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.CHARGED_BACK) self.assert_status(self.order_payment, StatusDefinition.CHARGED_BACK) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_refund(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000', 'totalRefunded': '1000' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.REFUNDED) self.assert_status(self.order_payment, StatusDefinition.REFUNDED) self.assert_status(self.order, StatusDefinition.REFUNDED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_chargeback_refund(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000', 'totalRefunded': '500', 'totalChargedback': '500' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.REFUNDED) self.assert_status(self.order_payment, StatusDefinition.REFUNDED) self.assert_status(self.order, StatusDefinition.REFUNDED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_two_payments(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', payments=[{ 'id': '1234', 'status': 'FAILED', 'amount': '1000', 'paymentMethod': 'MASTERCARD' }, { 'id': '12345', 'status': 'AUTHORIZED', 'amount': '1000', 'paymentMethod': 'MASTERCARD' }], totals={ 'totalCaptured': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.SETTLED) self.assert_status(self.order_payment, StatusDefinition.SETTLED) self.assert_status(self.order, StatusDefinition.SUCCESS) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_partially_settled(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '500', 'totalRegistered': '1000' }) self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.UNKNOWN) self.assert_status(self.order_payment, StatusDefinition.UNKNOWN) self.assert_status(self.order, StatusDefinition.FAILED) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_failed_success_status(self, mock_fetch_status, mock_transaction): # Check the order can go from failed to success when the payment goes from # cancelled to paid. # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'CANCELED') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.CANCELLED) self.assert_status(self.order_payment, StatusDefinition.CANCELLED) self.assert_status(self.order, StatusDefinition.FAILED) # Check that the status propagated through to order mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED', totals={ 'totalCaptured': '1000', 'totalRegistered': '1000' }) self.service.check_payment_status() self.assert_status(self.order_payment, StatusDefinition.SETTLED) self.assert_status(self.order, StatusDefinition.SUCCESS) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_no_payment_method_change(self, mock_fetch_status, mock_transaction): self.assertEquals(PaymentLogEntry.objects.count(), 1) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED') order = OrderFactory.create() order_payment = OrderPaymentFactory.create( order=order, payment_method='docdataCreditcard') docdata_payment = DocdataPaymentFactory.create( order_payment=order_payment, default_pm='mastercard', payment_cluster_id='1234', total_gross_amount=100) DocdataTransactionFactory.create(payment=docdata_payment, payment_method='VISA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get( reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataCreditcard') @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_payment_method_change(self, mock_fetch_status, mock_transaction): self.skipTest('Skipping test until we update it.') # Two payment log entries already exist: 2x 'a new payment status "started" ' self.assertEquals(PaymentLogEntry.objects.count(), 2) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED') order = OrderFactory.create() # Ensure that we use an existing payment_method or the adapter throws an exception order_payment = OrderPaymentFactory.create( order=order, payment_method='docdataPaypal') docdata_payment = DocdataPaymentFactory.create( order_payment=order_payment, default_pm='paypal', payment_cluster_id='1235', total_gross_amount=100) DocdataTransactionFactory.create(payment=docdata_payment, payment_method='VISA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get( reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataPaypal') # Check that all is logged correctly self.assertEquals( PaymentLogEntry.objects.filter(payment=docdata_payment).count(), 5) # The status changes triggers the # creation of more payment log entries log = PaymentLogEntry.objects.all()[0] self.assertEqual( log.message, "{0} - Payment method changed for payment with id {1}" " and order payment with id {2}.".format( docdata_payment, docdata_payment.id, docdata_payment.order_payment.id)) self.assertEqual(log.payment.id, docdata_payment.id) self.assertEqual(log.level, 'INFO') @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_unknown_payment_method_change(self, mock_fetch_status, mock_transaction): self.skipTest('Skipping test until we update it.') # Two payment log entries already exist: 2x 'a new payment status "started" ' self.assertEquals(PaymentLogEntry.objects.count(), 2) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response( 'AUTHORIZED') order = OrderFactory.create() # Ensure that we use an existing payment_method or the adapter throws an exception order_payment = OrderPaymentFactory.create( order=order, payment_method='docdataPaypal') docdata_payment = DocdataPaymentFactory.create( order_payment=order_payment, default_pm='paypal', payment_cluster_id='1236', total_gross_amount=100) DocdataTransactionFactory.create(payment=docdata_payment, payment_method='BLABLABLA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get( reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataPaypal') # Check that all is logged correctly self.assertEquals( PaymentLogEntry.objects.filter(payment=docdata_payment).count(), 5) log = PaymentLogEntry.objects.all()[0] self.assertEqual( log.message, "{0} - Payment method '{1}' not found for payment " "with id {2} and order payment with id {3}.".format( docdata_payment, 'BLABLABLA', docdata_payment.id, docdata_payment.order_payment.id)) self.assertEqual(log.payment.id, docdata_payment.id) self.assertEqual(log.level, 'WARNING')
def get_redirect_url(self, *args, **kwargs): order_payment = get_object_or_404(OrderPayment, id=kwargs['order_payment_id']) service = PaymentService(order_payment) service.check_payment_status() return "{0}/orders/{1}/success".format(get_current_host(), order_payment.order.id)
def batch_check_status(self, request, queryset): for order_payment in queryset: service = PaymentService(order_payment) service.check_payment_status()
def _process_monthly_order(monthly_order, send_email=False): if monthly_order.processed: logger.info("Order for {0} already processed".format( monthly_order.user)) return {'order_payment_id': None, 'processed': True} order_success = [StatusDefinition.PENDING, StatusDefinition.SUCCESS] ten_days_ago = timezone.now() + timezone.timedelta(days=-10) recent_orders = Order.objects.filter(user=monthly_order.user, order_type='recurring', status__in=order_success, updated__gt=ten_days_ago) if recent_orders.count() > 0: message = "Skipping '{0}' recently processed a recurring order for {1}:".format( monthly_order, monthly_order.user) logger.warn(message) for closed_order in recent_orders.all(): logger.warn("Recent Order Number: {0}".format(closed_order.id)) # Set an error on this monthly order monthly_order.error = message monthly_order.save() return {'order_payment_id': None, 'processed': False} order = Order.objects.create(status=StatusDefinition.LOCKED, user=monthly_order.user, order_type='recurring') order.save() logger.info("Creating Order for {0} with {1} donations".format( monthly_order.user, monthly_order.donations.count())) for monthly_donation in monthly_order.donations.all(): donation = Donation.objects.create(amount=monthly_donation.amount, project=monthly_donation.project, order=order) donation.save() integration_data = { 'account_name': monthly_order.name, 'account_city': monthly_order.city, 'iban': monthly_order.iban, 'bic': monthly_order.bic, 'agree': True } order_payment = OrderPayment(order=order, user=monthly_order.user, payment_method=PAYMENT_METHOD, integration_data=integration_data) order_payment.save() try: service = PaymentService(order_payment) service.start_payment() except PaymentException as e: error_message = "Problem starting payment. {0}".format(e) monthly_order.error = "{0}".format(e.message) monthly_order.save() logger.error(error_message) return {'order_payment_id': order_payment.id, 'processed': False} logger.debug("Payment for '{0}' started.".format(monthly_order)) monthly_order.processed = True monthly_order.error = '' monthly_order.save() # Try to update status service.check_payment_status() # Send an email to the user. if send_email: mail_monthly_donation_processed_notification(monthly_order) return {'order_payment_id': order_payment.id, 'processed': True}
class PaymentsDocdataTestCase(TestCase, FsmTestMixin): @patch.object(DocdataClient, 'create') def setUp(self, mock_client_create): # Mock response to creating the payment at docdata mock_client_create.return_value = {'order_key': 123, 'order_id': 123} # Mock create payment mock_create_payment = patch.object(DocdataPaymentAdapter, 'create_payment', fake_create_payment) self.order = OrderFactory.create() self.order_payment = OrderPaymentFactory.create(order=self.order, payment_method='docdataIdeal', integration_data={'default_pm': 'ideal'}) self.service = PaymentService(order_payment=self.order_payment) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_check_authorized_status(self, mock_fetch_status, mock_transaction): # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response('AUTHORIZED') self.service.check_payment_status() # Check that the status propagated through to order self.assert_status(self.order_payment.payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order_payment, StatusDefinition.AUTHORIZED) self.assert_status(self.order, StatusDefinition.PENDING) @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_no_payment_method_change(self, mock_fetch_status, mock_transaction): self.assertEquals(PaymentLogEntry.objects.count(), 2) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response('AUTHORIZED') order = OrderFactory.create() order_payment = OrderPaymentFactory.create(order=order, payment_method='docdataCreditcard') docdata_payment = DocdataPaymentFactory.create(order_payment=order_payment, default_pm='mastercard', payment_cluster_id='1234', total_gross_amount=100) docdata_transaction = DocdataTransactionFactory.create(payment=docdata_payment, payment_method='VISA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get(reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataCreditcard') @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_payment_method_change(self, mock_fetch_status, mock_transaction): self.skipTest('Skipping test until we update it.') # Two payment log entries already exist: 2x 'a new payment status "started" ' self.assertEquals(PaymentLogEntry.objects.count(), 2) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response('AUTHORIZED') order = OrderFactory.create() # Ensure that we use an existing payment_method or the adapter throws an exception order_payment = OrderPaymentFactory.create(order=order, payment_method='docdataPaypal') docdata_payment = DocdataPaymentFactory.create(order_payment=order_payment, default_pm='paypal', payment_cluster_id='1235', total_gross_amount=100) docdata_transaction = DocdataTransactionFactory.create(payment=docdata_payment, payment_method='VISA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get(reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataPaypal') # Check that all is logged correctly self.assertEquals(PaymentLogEntry.objects.filter(payment=docdata_payment).count(), 5) # The status changes triggers the # creation of more payment log entries log = PaymentLogEntry.objects.all()[0] self.assertEqual(log.message, "{0} - Payment method changed for payment with id {1} and order payment with id {2}.".format(docdata_payment, docdata_payment.id, docdata_payment.order_payment.id)) self.assertEqual(log.payment.id, docdata_payment.id) self.assertEqual(log.level, 'INFO') @patch.object(DocdataPaymentAdapter, '_store_payment_transaction') @patch.object(DocdataPaymentAdapter, '_fetch_status') def test_unknown_payment_method_change(self, mock_fetch_status, mock_transaction): self.skipTest('Skipping test until we update it.') # Two payment log entries already exist: 2x 'a new payment status "started" ' self.assertEquals(PaymentLogEntry.objects.count(), 2) # Mock the status check with docdata mock_fetch_status.return_value = self.create_status_response('AUTHORIZED') order = OrderFactory.create() # Ensure that we use an existing payment_method or the adapter throws an exception order_payment = OrderPaymentFactory.create(order=order, payment_method='docdataPaypal') docdata_payment = DocdataPaymentFactory.create(order_payment=order_payment, default_pm='paypal', payment_cluster_id='1236', total_gross_amount=100) docdata_transaction = DocdataTransactionFactory.create(payment=docdata_payment, payment_method='BLABLABLA') c = Client() merchant_order_id = "{0}-1".format(order_payment.id) resp = c.get(reverse('docdata-payment-status-update', kwargs={'merchant_order_id': merchant_order_id})) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.content, 'success') # Reload the order payment order_payment = OrderPayment.objects.get(id=order_payment.id) self.assertEqual(order_payment.payment_method, 'docdataPaypal') # Check that all is logged correctly self.assertEquals(PaymentLogEntry.objects.filter(payment=docdata_payment).count(), 5) log = PaymentLogEntry.objects.all()[0] self.assertEqual(log.message, "{0} - Payment method '{1}' not found for payment with id {2} and order payment with id {3}.".format( docdata_payment, 'BLABLABLA', docdata_payment.id, docdata_payment.order_payment.id)) self.assertEqual(log.payment.id, docdata_payment.id) self.assertEqual(log.level, 'WARNING')