def test_create_next_double_payment(caplog, creation_params): creation_params['registration'].transaction = MagicMock( status=TransactionStatus.successful) _, double_payment = PaymentTransaction.create_next(**creation_params) log = extract_logs(caplog, one=True, name='indico.payment').message assert 'already paid' in log assert double_payment
def register_transaction(registration, amount, currency, action, provider=None, data=None): """Create a new transaction for a certain transaction action. :param registration: the `Registration` associated to the transaction :param amount: the (strictly positive) amount of the transaction :param currency: the currency used for the transaction :param action: the `TransactionAction` of the transaction :param provider: the payment method name of the transaction, or '_manual' if no payment method has been used :param data: arbitrary JSON-serializable data specific to the transaction's provider """ new_transaction = PaymentTransaction.create_next(registration=registration, action=action, amount=amount, currency=currency, provider=provider, data=data) if new_transaction: db.session.flush() if new_transaction.status == TransactionStatus.successful: registration.update_state(paid=True) elif new_transaction.status == TransactionStatus.cancelled: registration.update_state(paid=False) notify_registration_state_update(registration) return new_transaction
def register_transaction(registration, amount, currency, action, provider=None, data=None): """Creates a new transaction for a certain transaction action. :param registration: the `Registration` associated to the transaction :param amount: the (strictly positive) amount of the transaction :param currency: the currency used for the transaction :param action: the `TransactionAction` of the transaction :param provider: the payment method name of the transaction, or '_manual' if no payment method has been used :param data: arbitrary JSON-serializable data specific to the transaction's provider """ new_transaction, double_payment = PaymentTransaction.create_next( registration=registration, action=action, amount=amount, currency=currency, provider=provider, data=data ) if new_transaction: db.session.flush() if double_payment: notify_double_payment(registration) if new_transaction.status == TransactionStatus.successful: registration.update_state(paid=True) elif new_transaction.status == TransactionStatus.cancelled: registration.update_state(paid=False) notify_registration_state_update(registration) return new_transaction
def adjust_payment_form_data(self, data): """Prepare the payment form shown to registrants.""" # indico does not seem to provide stacking of settings # we merge event on top of global settings, but remove defaults event_settings = data['event_settings'] global_settings = data['settings'] plugin_settings = { key: event_settings[key] if event_settings.get(key) is not None else global_settings[key] for key in (set(event_settings) | set(global_settings)) } # parameters of the transaction - amount, currency, ... transaction = self._get_transaction_parameters(data, plugin_settings) init_response = self._init_payment_page( sixpay_url=plugin_settings['url'], transaction_data=transaction, ) data['payment_url'] = init_response['RedirectUrl'] # create pending transaction and store Saferpay transaction token if not PaymentTransaction.create_next( registration=data['registration'], amount=data['amount'], currency=data['currency'], action=TransactionAction.pending, provider=provider, data={'Init_PP_response': init_response}): data['registration'].transaction.data = { 'Init_PP_response': init_response } return data
def test_create_next_with_exception(caplog, mocker, creation_params, exception): mocker.patch.object(TransactionStatusTransition, 'next') TransactionStatusTransition.next.side_effect = exception('TEST_EXCEPTION') transaction = PaymentTransaction.create_next(**creation_params) log = extract_logs(caplog, one=True, name='indico.payment') assert transaction is None assert 'TEST_EXCEPTION' in log.message if log.exc_info: assert log.exc_info[0] == exception
def test_ipn_is_transaction_duplicated(txn_id, payment_status, expected): request.form = {'payment_status': 'Completed', 'txn_id': '12345'} rh = RHPaypalIPN() rh.registration = MagicMock() rh.registration.transaction = None assert not rh._is_transaction_duplicated() transaction = PaymentTransaction(provider='paypal', data={ 'payment_status': payment_status, 'txn_id': txn_id }) rh.registration.transaction = transaction assert rh._is_transaction_duplicated() == expected
def migrate_transactions(self): self.messages.append(cformat("%{magenta!} - Payment Transactions:")) print cformat("%{white!}migrating payment transactions") count = 0 errors = 0 warnings = 0 for event, registrant, transaction in committing_iterator(self._iter_transactions()): try: data = self._get_transaction_data(transaction, event) except ValueError as e: print cformat("%{red!}{0} (evt: {1}, reg: {2})").format(e, event.id, registrant._id) errors += 1 continue if data['provider'] == '_manual' and data['amount'] == 0.0: print cformat("%{yellow!}Skipping {0[provider]} transaction (evt: {1}, reg: {2}) " "with zero amount: {0[amount]} {0[currency]}").format(data, event.id, registrant._id) warnings += 1 continue elif data['amount'] < 0.0: print cformat("%{yellow!}Skipping {0[provider]} transaction (evt: {1}, reg: {2}) " "with negative amount: {0[amount]} {0[currency]}").format(data, event.id, registrant._id) warnings += 1 continue pt = PaymentTransaction(event_id=int(event.id), registrant_id=int(registrant._id), status=TransactionStatus.successful, **data) count += 1 print cformat("%{cyan}{0}").format(pt) db.session.add(pt) if warnings: warning_msg = cformat("%{yellow!}There were {0} warnings during the migration " "of the payment transactions.").format(warnings) self.messages.append(' ' + warning_msg) print warning_msg if errors: msg = cformat("%{red!}There were some errors during the migration of the payment transactions.\n" "{0} transactions were not migrated and will be lost.\n").format(errors) else: msg = cformat("%{green!}migration of {0} payment transactions successful\n").format(count) self.messages.append(' ' + '\n '.join(msg.split('\n'))) print msg
def _create_transaction(status, **params): params.setdefault('amount', 10) params.setdefault('currency', 'USD') params.setdefault('provider', '_manual') params.setdefault('data', {}) return PaymentTransaction(status=status, **params)
def test_create_next(creation_params): transaction, double_payment = PaymentTransaction.create_next(**creation_params) assert isinstance(transaction, PaymentTransaction) assert not double_payment
def test_create_next(creation_params): transaction = PaymentTransaction.create_next(**creation_params) assert isinstance(transaction, PaymentTransaction)
def test_create_next_double_payment(caplog, creation_params): creation_params['registration'].transaction = MagicMock(status=TransactionStatus.successful) _, double_payment = PaymentTransaction.create_next(**creation_params) log = extract_logs(caplog, one=True, name='indico.payment').message assert 'already paid' in log assert double_payment
def has_data(self): return bool(PaymentTransaction.find().count())