def test_cant_refund_more(): transaction = transact([], price='6.00') try: dinero.get_gateway('braintree').refund(transaction, transaction.price + 1) except PaymentException as e: assert RefundError in e else: assert False, "must raise an exception"
def test_cant_refund_more(): txn = transact([]) try: dinero.get_gateway('authorize.net').refund(txn, txn.price + 1) except PaymentException as e: assert RefundError in e else: assert False, "must raise an exception"
def test_invalid_transaction(): transaction = transact([], price='7.00') transaction.transaction_id = '0' try: dinero.get_gateway('braintree').refund(transaction, transaction.price) except PaymentException as e: assert InvalidTransactionError in e else: assert False, "must raise an exception"
def test_charge_customer_xml(): gateway = dinero.get_gateway('authorize.net') price = 123.45 customer_id = '123456789' card_id = '987654321' options = { 'cvv': '123' } xml = gateway._charge_customer_xml(customer_id, card_id, price, options) should_be = trimmy( """<createCustomerProfileTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"> <merchantAuthentication> <name>{login_id}</name> <transactionKey>{transaction_key}</transactionKey> </merchantAuthentication> <transaction> <profileTransAuthCapture> <amount>{price}</amount> <customerProfileId>{customer_id}</customerProfileId> <customerPaymentProfileId>{card_id}</customerPaymentProfileId> <cardCode>{cvv}</cardCode> </profileTransAuthCapture> </transaction> </createCustomerProfileTransactionRequest>""".format( login_id=gateway.login_id, transaction_key=gateway.transaction_key, price=price, customer_id=customer_id, card_id=card_id, **options )) assert etree.tostring(xml) == should_be, "Invalid XML (\n\t%s\n\t%s\n)" % (etree.tostring(xml), should_be)
def test_payment_create_customer_xml(): gateway = dinero.get_gateway('authorize.net') options = { 'email': '*****@*****.**', 'number': '4' + '1' * 15, 'month': '12', 'year': '2012', } xml = gateway._create_customer_xml(options) should_be = trimmy( """<createCustomerProfileRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"> <merchantAuthentication> <name>{login_id}</name> <transactionKey>{transaction_key}</transactionKey> </merchantAuthentication> <profile> <email>[email protected]</email> <paymentProfiles> <payment> <creditCard> <cardNumber>4111111111111111</cardNumber> <expirationDate>2012-12</expirationDate> </creditCard> </payment> </paymentProfiles> </profile> </createCustomerProfileRequest>""".format( login_id=gateway.login_id, transaction_key=gateway.transaction_key, )) assert etree.tostring(xml) == should_be, "Invalid XML (\n\t%s\n\t%s\n)" % (etree.tostring(xml), should_be)
def delete(self): """ Delete a card from the gateway. """ gateway = get_gateway(self.gateway_name) gateway.delete_card(self) return True
def delete(self): if not self.customer_id: raise InvalidCustomerException("Cannot delete a customer that doesn't have a customer_id") gateway = get_gateway(self.gateway_name) gateway.delete_customer(self.customer_id) self.customer_id = None return True
def retrieve(cls, transaction_id, gateway_name=None): """ Fetches a transaction object from the gateway. """ gateway = get_gateway(gateway_name) resp = gateway.retrieve(transaction_id) return cls(gateway_name=gateway.name, **resp)
def settle(self, amount=None): """ If you create a transaction without settling it, you can settle it with this method. It is possible to settle only part of a transaction. If ``amount`` is None, the full transaction price is settled. """ gateway = get_gateway(self.gateway_name) return gateway.settle(self, amount or self.price)
def save(self): """ Saves changes to a customer object. """ if not self.customer_id: raise InvalidCustomerException("Cannot save a customer that doesn't have a customer_id") gateway = get_gateway(self.gateway_name) gateway.update_customer(self.customer_id, self.data) return True
def test_customer_create_xml(): gateway = dinero.get_gateway('authorize.net') options = { 'email': '*****@*****.**', 'first_name': 'Joey', 'last_name': 'Shabadoo', 'company': 'Shabadoo, Inc.', 'phone': '000-000-0000', 'fax': '000-000-0001', 'address': '123 somewhere st', 'state': 'SW', 'city': 'somewhere', 'zip': '12345', 'country': 'US', 'number': '4' + '1' * 15, 'month': '12', 'year': '2012', } xml = gateway._create_customer_xml(options) should_be = trimmy( """<createCustomerProfileRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"> <merchantAuthentication> <name>{login_id}</name> <transactionKey>{transaction_key}</transactionKey> </merchantAuthentication> <profile> <email>[email protected]</email> <paymentProfiles> <billTo> <firstName>Joey</firstName> <lastName>Shabadoo</lastName> <company>Shabadoo, Inc.</company> <address>123 somewhere st</address> <city>somewhere</city> <state>SW</state> <zip>12345</zip> <country>US</country> <phoneNumber>000-000-0000</phoneNumber> <faxNumber>000-000-0001</faxNumber> </billTo> <payment> <creditCard> <cardNumber>4111111111111111</cardNumber> <expirationDate>2012-12</expirationDate> </creditCard> </payment> </paymentProfiles> </profile> </createCustomerProfileRequest>""".format( login_id=gateway.login_id, transaction_key=gateway.transaction_key, )) assert etree.tostring(xml) == should_be, "Invalid XML (\n\t%s\n\t%s\n)" % (etree.tostring(xml), should_be)
def test_customer_create_xml(): gateway = dinero.get_gateway('authorize.net') options = { 'email': '*****@*****.**', 'first_name': 'Joey', 'last_name': 'Shabadoo', 'company': 'Shabadoo, Inc.', 'phone': '000-000-0000', 'fax': '000-000-0001', 'address': '123 somewhere st', 'state': 'SW', 'city': 'somewhere', 'zip': '12345', 'country': 'US', 'number': '4' + '1' * 15, 'month': '12', 'year': '2012', } xml = gateway._create_customer_xml(options) should_be = trimmy( """<createCustomerProfileRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"> <merchantAuthentication> <name>{login_id}</name> <transactionKey>{transaction_key}</transactionKey> </merchantAuthentication> <profile> <email>[email protected]</email> <paymentProfiles> <billTo> <firstName>Joey</firstName> <lastName>Shabadoo</lastName> <company>Shabadoo, Inc.</company> <address>123 somewhere st</address> <city>somewhere</city> <state>SW</state> <zip>12345</zip> <country>US</country> <phoneNumber>000-000-0000</phoneNumber> <faxNumber>000-000-0001</faxNumber> </billTo> <payment> <creditCard> <cardNumber>4111111111111111</cardNumber> <expirationDate>2012-12</expirationDate> </creditCard> </payment> </paymentProfiles> </profile> </createCustomerProfileRequest>""".format( login_id=gateway.login_id, transaction_key=gateway.transaction_key, )) assert etree.tostring(xml) == should_be, "Invalid XML (\n\t%s\n\t%s\n)" % ( etree.tostring(xml), should_be)
def refund(self, amount=None): gateway = get_gateway(self.gateway_name) try: return gateway.refund(self, amount or self.price) except exceptions.PaymentException: if amount is None or amount == self.price: return gateway.void(self) else: raise exceptions.PaymentException("You cannot refund a " "transaction that hasn't been settled unless you " "refund it for the full amount.")
def refund(self, amount=None): gateway = get_gateway(self.gateway_name) try: return gateway.refund(self, amount or self.price) except exceptions.PaymentException: if amount is None or amount == self.price: return gateway.void(self) else: raise exceptions.PaymentException( "You cannot refund a " "transaction that hasn't been settled unless you " "refund it for the full amount.")
def retrieve(cls, customer_id, gateway_name=None): """ Fetches a customer object from the gateway. This optionally accepts a ``gateway_name`` parameter. """ gateway = get_gateway(gateway_name) resp, cards = gateway.retrieve_customer(customer_id) # resp must have customer_id in it customer = cls(gateway_name=gateway.name, **resp) for card in cards: customer.cards.append(CreditCard(gateway_name=gateway.name, **card)) return customer
def retrieve(cls, customer_id, gateway_name=None): """ Fetches a customer object from the gateway. This optionally accepts a ``gateway_name`` parameter. """ gateway = get_gateway(gateway_name) resp, cards = gateway.retrieve_customer(customer_id) # resp must have customer_id in it customer = cls(gateway_name=gateway.name, **resp) for card in cards: customer.cards.append(CreditCard( gateway_name=gateway.name, **card )) return customer
def create(cls, price, gateway_name=None, **kwargs): """ Creates a payment. This method will actually charge your customer. :meth:`create` can be called in several different ways. You can call this with the credit card information directly. :: Transaction.create( price=200, number='4111111111111111', year='2015', month='12', # optional first_name='John', last_name='Smith,' zip='12345', address='123 Elm St', city='Denver', state='CO', cvv='900', email='*****@*****.**', ) If you have a :class:`dinero.Customer` object, you can create a transaction against the customer. :: customer = Customer.create( ... ) Transaction.create( price=200, customer=customer, ) Other payment options include ``card`` and ``check``. See :class:`dinero.CreditCard` for more information. """ gateway = get_gateway(gateway_name) resp = gateway.charge(price, kwargs) return cls(gateway_name=gateway.name, **resp)
def test_minimum_create_customer_xml(): gateway = dinero.get_gateway('authorize.net') options = { 'email': '*****@*****.**', } xml = gateway._create_customer_xml(options) should_be = trimmy( """<createCustomerProfileRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"> <merchantAuthentication> <name>{login_id}</name> <transactionKey>{transaction_key}</transactionKey> </merchantAuthentication> <profile> <email>[email protected]</email> </profile> </createCustomerProfileRequest>""".format( login_id=gateway.login_id, transaction_key=gateway.transaction_key, )) assert etree.tostring(xml) == should_be, 'Invalid XML'
def add_card(self, options, gateway_name=None): """ The first credit card is added when you call :meth:`create`, but you can add more cards using this method. :: customer.add_card( number='4222222222222', cvv='900', month='12' year='2015' address='123 Elm St', zip='12345', ) """ if not self.customer_id: raise InvalidCustomerException("Cannot add a card to a customer that doesn't have a customer_id") gateway = get_gateway(gateway_name) resp = gateway.add_card_to_customer(self, options) card = CreditCard(gateway_name=self.gateway_name, **resp) self.cards.append(card) return card
def create(cls, gateway_name=None, **kwargs): """ Creates and stores a customer object. When you first create a customer, you are required to also pass in arguments for a credit card. :: Customer.create( email='*****@*****.**', # required for credit card number='4111111111111111', cvv='900', month='12', year='2015', address='123 Elm St.', zip='12345', ) This method also accepts ``gateway_name``. """ gateway = get_gateway(gateway_name) resp = gateway.create_customer(kwargs) return cls(gateway_name=gateway.name, **resp)
def add_card(self, gateway_name=None, **options): """ The first credit card is added when you call :meth:`create`, but you can add more cards using this method. :: customer.add_card( number='4222222222222', cvv='900', month='12' year='2015' address='123 Elm St', zip='12345', ) """ if not self.customer_id: raise InvalidCustomerException( "Cannot add a card to a customer that doesn't have a customer_id" ) gateway = get_gateway(gateway_name) resp = gateway.add_card_to_customer(self, options) card = CreditCard(gateway_name=self.gateway_name, **resp) self.cards.append(card) return card
def refund(self, amount=None): """ If ``amount`` is None dinero will refund the full price of the transaction. Payment gateways often allow you to refund only a certain amount of money from a transaction. Refund abstracts the difference between refunding and voiding a payment so that normally you don't need to worry about it. However, please note that you can only refund the entire amount of a transaction before it is settled. """ gateway = get_gateway(self.gateway_name) # TODO: can this implementation live in dinero.gateways.AuthorizeNet? try: return gateway.refund(self, amount or self.price) except exceptions.PaymentException: if amount is None or amount == self.price: return gateway.void(self) else: raise exceptions.PaymentException( "You cannot refund a transaction that hasn't been settled" " unless you refund it for the full amount." )
def retrieve(cls, customer_id, gateway_name=None): gateway = get_gateway(gateway_name) resp = gateway.retrieve_customer(customer_id) # resp must have customer_id in it return cls(gateway_name=gateway.name, **resp)
def retrieve(cls, transaction_id, gateway_name=None): gateway = get_gateway(gateway_name) resp = gateway.retrieve(transaction_id) return cls(gateway_name=gateway.name, **resp)
def create(cls, price, gateway_name=None, **kwargs): gateway = get_gateway(gateway_name) resp = gateway.charge(price, kwargs) return cls(gateway_name=gateway.name, **resp)
def save(self): """ Save changes to a card to the gateway. """ gateway = get_gateway(self.gateway_name) gateway.update_card(self)
def create(cls, gateway_name=None, **kwargs): gateway = get_gateway(gateway_name) resp = gateway.create_customer(kwargs) return cls(gateway_name=gateway.name, **resp)