def delayed_capture(order_number, pnref=None, amt=None): """ Capture funds that have been previously authorized. Notes: * It's possible to capture a lower amount than the original auth transaction - however... * ...only one delayed capture is allowed for a given PNREF... * ...If multiple captures are required, a 'reference transaction' needs to be used. * It's safe to retry captures if the first one fails or errors :order_number: Order number :pnref: The PNREF of the authorization transaction to use. If not specified, the order number is used to retrieve the appropriate transaction. :amt: A custom amount to capture. """ if pnref is None: # No PNREF specified, look-up the auth transaction for this order number # to get the PNREF from there. try: auth_txn = models.PayflowTransaction.objects.get( comment1=order_number, trxtype=codes.AUTHORIZATION) except models.PayflowTransaction.DoesNotExist: raise exceptions.UnableToTakePayment( "No authorization transaction found with PNREF=%s" % pnref) pnref = auth_txn txn = gateway.delayed_capture(order_number, pnref, amt) if not txn.is_approved: raise exceptions.UnableToTakePayment(txn.respmsg) return txn
def _submit_payment_details(gateway_fn, order_number, amt, bankcard, billing_address=None): # Remap address fields if set. address_fields = {} if billing_address: address_fields.update({ 'first_name': billing_address['first_name'], 'last_name': billing_address['first_name'], 'street': billing_address['line1'], 'city': billing_address['line4'], 'state': billing_address['state'], 'zip': billing_address['postcode'].strip(' ') }) txn = gateway_fn(order_number, card_number=bankcard.number, cvv=bankcard.cvv, expiry_date=bankcard.expiry_month("%m%y"), amt=amt, **address_fields) if not txn.is_approved: raise exceptions.UnableToTakePayment(txn.respmsg) return txn
def credit(order_number, pnref=None, amt=None): """ Return funds that have been previously settled. :order_number: Order number :pnref: The PNREF of the authorization transaction to use. If not specified, the order number is used to retrieve the appropriate transaction. :amt: A custom amount to capture. If not specified, the entire transaction is refuneded. """ if pnref is None: # No PNREF specified, look-up the auth/sale transaction for this order number # to get the PNREF from there. try: auth_txn = models.PayflowTransaction.objects.get( comment1=order_number, trxtype__in=(codes.AUTHORIZATION, codes.SALE)) except models.PayflowTransaction.DoesNotExist: raise exceptions.UnableToTakePayment( "No authorization transaction found with PNREF=%s" % pnref) pnref = auth_txn txn = gateway.credit(order_number, pnref, amt) if not txn.is_approved: raise exceptions.PaymentError(txn.respmsg) return txn
def _submit_payment_details(gateway_fn, order_number, amt, bankcard, billing_address=None): # Oscar's bankcard class returns dates in form '01/02' - we strip the '/' to # conform to PayPal's conventions. exp_date = bankcard.expiry_date.replace('/', '') # Remap address fields if set address_fields = {} if billing_address: address_fields.update({ 'first_name': billing_address['first_name'], 'last_name': billing_address['first_name'], 'street': billing_address['line1'], 'city': billing_address['line4'], 'state': billing_address['state'], 'zip': billing_address['postcode'].strip(' ') }) txn = gateway_fn(order_number, card_number=bankcard.card_number, cvv=bankcard.cvv, expiry_date=exp_date, amt=amt, **address_fields) if not txn.is_approved: raise exceptions.UnableToTakePayment(txn.respmsg) return txn
def handle_payment(self, order_number, total_incl_tax, **kwargs): # Make submission to PayPal. try: # Using authorization here (two-stage model). You could use sale to # perform the auth and capture in one step. The choice is dependent # on your business model. facade.authorize(order_number, total_incl_tax, kwargs['bankcard'], kwargs['billing_address']) except facade.NotApproved, e: # Submission failed raise exceptions.UnableToTakePayment(e.message)
def handle_payment(self, order_number, total, **kwargs): # Override payment method to use accounts to pay for the order allocations = self.get_account_allocations() if allocations.total != total.incl_tax: raise exceptions.UnableToTakePayment( "Your account allocations do not cover the order total") try: gateway.redeem(order_number, self.request.user, allocations) except act_exceptions.AccountException: raise exceptions.UnableToTakePayment( "An error occurred with the account redemption") # If we get here, payment was successful. We record the payment # sources and event to complete the audit trail for this order source_type, __ = SourceType.objects.get_or_create(name="Account") for code, amount in allocations.items(): source = Source(source_type=source_type, amount_debited=amount, reference=code) self.add_payment_source(source) self.add_payment_event("Settle", total.incl_tax)
def handle_payment(self, order_number, total, **kwargs): # Override payment method to use accounts to pay for the order allocations = self.get_account_allocations() if allocations.total != total.incl_tax: raise exceptions.UnableToTakePayment( "SWAMAHANI, Vos moyens de paiement sont insuffisant") try: gateway.redeem(order_number, self.request.user, allocations) except act_exceptions.AccountException: raise exceptions.UnableToTakePayment( "Il y a une erreur, reesayer plus tard") # If we get here, payment was successful. We record the payment # sources and event to complete the audit trail for this order source_type, __ = SourceType.objects.get_or_create(name="Account") for code, amount in allocations.items(): source = Source(source_type=source_type, amount_debited=amount, reference=code) self.add_payment_source(source) self.add_payment_event("Settle", total.incl_tax)
def referenced_sale(order_number, pnref, amt): """ Capture funds using the bank/address details of a previous transaction This is equivalent to a *sale* transaction but without the user having to enter their payment details. There are two main uses for this: 1. This allows customers to checkout without having to re-enter their payment details. 2. It allows an initial authorisation to be settled in multiple parts. The first settle should use delayed_capture but any subsequent ones should use this method. :order_number: Order number. :pnref: PNREF of a previous transaction to use. :amt: The amount to settle for. """ txn = gateway.reference_transaction(order_number, pnref, amt) if not txn.is_approved: raise exceptions.UnableToTakePayment(txn.respmsg) return txn