def authorize_payment(self, purchase=None, amount=NOTSET, testing=False): """Authorize a single payment. Returns: ProcessorResult """ assert (purchase) if purchase.remaining == Decimal('0.00'): self.log_extra('%s is paid in full, no authorization attempted.', purchase) results = ProcessorResult(self.key, True, _("No charge needed, paid in full.")) else: if amount == NOTSET: try: pending = purchase.get_pending(self.key) amount = pending.amount except PaymentPending.DoesNotExist: amount = purchase.remaining self.log_extra('Authorizing payment of %s for %s', amount, purchase) standard = self.get_standard_charge_data(authorize=True, purchase=purchase, amount=amount) results = self.send_post(standard, testing, purchase=purchase) return results
def capture_payment(self, testing=False, purchase=None, amount=NOTSET): """Process payments without an authorization step.""" assert (purchase) recurlist = self.get_recurring_charge_data(purchase=purchase) if recurlist: success, results = self.process_recurring_subscriptions( recurlist, testing) if not success: self.log_extra( 'recur payment failed, aborting the rest of the module') return results if purchase.remaining == Decimal('0.00'): self.log_extra('%s is paid in full, no capture attempted.', purchase) results = ProcessorResult(self.key, True, _("No charge needed, paid in full.")) self.record_payment(purchase=purchase) else: self.log_extra('Capturing payment for %s', purchase) standard = self.get_standard_charge_data(amount=amount, purchase=purchase) results = self.send_post(standard, testing, purchase=purchase) return results
def process_recurring_subscriptions(self, recurlist, purchase=None, testing=False): """Post all subscription requests.""" assert (purchase) results = [] for recur in recurlist: success, reason, response, subscription_id = self.process_recurring_subscription( recur, testing=testing) if success: if not testing: payment = self.record_payment( purchase=purchase, amount=recur['charged_today'], transaction_id=subscription_id, reason_code=reason) results.append( ProcessorResult(self.key, success, response, payment=payment)) else: self.log.info( "Failed to process recurring subscription, %s: %s", reason, response) break return success, results
def capture_payment(self, testing=False, order=None, amount=NOTSET): """process the transaction through tclink""" if not order: order = self.order if amount == NOTSET: amount = order.balance if order.paid_in_full: self.log_extra('%s is paid in full, no capture attempted.', order) self.record_payment() return ProcessorResult(self.key, True, _("No charge needed, paid in full.")) self.log_extra('Capturing payment for %s', order) self.prepare_post(order, amount) result = tclink.send(self.transactionData) status = result ['status'] payment = None success = False if status == 'approved': payment = self.record_payment(order=order, amount=amount, transaction_id="", reason_code=status) success = True msg = unicode(result) else: if status == 'decline': msg = _(u'Transaction was declined. Reason: %s' % result['declinetype']) failmsg = u'Transaction was declined. Reason: %s' % result['declinetype'] elif status == 'baddata': msg = _(u'Improperly formatted data. Offending fields: %s' % result['offenders']) failmsg = u'Improperly formatted data. Offending fields: %s' % result['offenders'] else: status = "error" msg = _(u'An error occurred: %s' % result['errortype']) failmsg = u'An error occurred: %s' % result['errortype'] payment = self.record_failure(order=order, amount=amount, transaction_id="", reason_code=status, details=failmsg) return ProcessorResult(self.key, success, msg, payment=payment)
def release_authorized_payment(self, purchase=None, auth=None, testing=False): """Release a previously authorized payment.""" auth.complete = True auth.save() return ProcessorResult(self.key, True, _('Success'))
def capture_payment(self, testing=False, purchase=None, amount=NOTSET): """Process the transaction and return a ProcessorResult: """ assert (purchase) payment = self.record_payment(amount=amount, reason_code="0", purchase=purchase) return ProcessorResult(self.key, True, _('Success'), payment)
def capture_payment(self, testing=False, purchase=None, amount=NOTSET): """ Creates and sends XML representation of transaction to Cybersource """ if purchase.remaining == Decimal('0.00'): self.log_extra('%s is paid in full, no capture attempted.', purchase) self.record_payment(purchase=purchase) return ProcessorResult(self.key, True, _("No charge needed, paid in full.")) self.log_extra('Capturing payment for %s', purchase) if amount==NOTSET: amount = purchase.remaining self.prepare_content(purchase, amount) invoice = "%s" % purchase.id failct = purchase.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) # XML format is very simple, using ElementTree for generation would be overkill t = loader.get_template('bursar/gateway/cybersource_gateway/request.xml') c = Context({ 'config' : self.configuration, 'merchantReferenceCode' : invoice, 'billTo' : self.bill_to, 'purchaseTotals' : self.purchase_totals, 'card' : self.card, }) request = t.render(c) self.log_extra("Cybersource request: %s", request) conn = urllib2.Request(url=self.connection, data=request) try: f = urllib2.urlopen(conn) except urllib2.HTTPError, e: # we probably didn't authenticate properly # make sure the 'v' in your account number is lowercase return ProcessorResult(self.key, False, 'Problem parsing results')
def authorize_payment(self, purchase=None, testing=False, amount=NOTSET): """ Make an authorization for an purchase. This payment will then be captured when the purchase is set marked 'shipped'. """ assert (purchase) if amount == NOTSET: amount = self.pending_amount(purchase) cc = purchase.credit_card if cc: ccn = cc.decryptedCC ccv = cc.ccv if ccn == '4222222222222': if ccv == '222': self.log_extra('Bad CCV forced') payment = self.record_failure(amount=amount, transaction_id='2', reason_code='2', details='CCV error forced') return ProcessorResult(self.key, False, _('Bad CCV - order declined'), payment) else: self.log_extra( 'Setting a bad credit card number to force an error') payment = self.record_failure( amount=amount, transaction_id='2', reason_code='2', details='Credit card number error forced') return ProcessorResult( self.key, False, _('Bad credit card number - order declined'), payment) orderauth = self.record_authorization(amount=amount, reason_code="0", purchase=purchase) return ProcessorResult(self.key, True, _('Success'), orderauth)
def capture_payment(self, testing=False, purchase=None, amount=NOTSET): """ Purchase Orders are always successful. """ if amount == NOTSET: amount = purchase.total payment = self.record_payment(purchase=purchase, amount=amount, transaction_id="PO", reason_code='0') return ProcessorResult(self.key, True, _('Success'), payment)
def capture_payment(self, testing=False, purchase=None, amount=NOTSET): assert (purchase) if amount == NOTSET: amount = purchase.total log.debug('Capturing payment of %s', amount) payment = self.record_payment(purchase=purchase, amount=amount, transaction_id=self.key, reason_code='0') return ProcessorResult(self.key, True, _('Success'), payment)
def capture_payment(self, testing=False, order=None, amount=NOTSET): """ Process the transaction and return a ProcessorResponse """ if not order: order = self.order if amount == NOTSET: amount = order.balance payment = None valid_gc = False if self.order.paid_in_full: success = True reason_code = "0" response_text = _("No balance to pay") self.record_payment() else: try: gc = GiftCertificate.objects.from_order(self.order) valid_gc = gc.valid except GiftCertificate.DoesNotExist: success = False reason_code = "1" response_text = _("No such Gift Certificate") if not valid_gc: success = False reason_code = "2" response_text = _("Bad Gift Certificate") else: gc.apply_to_order(self.order) payment = gc.payment reason_code = "0" response_text = _("Success") success = True if not self.order.paid_in_full: response_text = _( "%s balance remains after gift certificate was applied" ) % moneyfmt(self.order.balance) return ProcessorResult(self.key, success, response_text, payment=payment)
def capture_payment(self, testing=False, purchase=None, amount=NOTSET): """ COD is always successful. """ assert (purchase) if amount == NOTSET: amount = purchase.total payment = self.record_payment(amount=amount, transaction_id=self.key, reason_code='0', purchase=purchase) return ProcessorResult(self.key, True, _('Success'), payment)
def capture_authorized_payment(self, authorization, amount=NOTSET, purchase=None): """ Capture a prior authorization """ if not purchase: purchase = authorization.purchase if amount == NOTSET: amount = authorization.amount payment = self.record_payment(amount=amount, reason_code="0", transaction_id="dummy", authorization=authorization, purchase=purchase) return ProcessorResult(self.key, True, _('Success'), payment)
def capture_authorized_payment(self, authorization, testing=False, purchase=None, amount=NOTSET): """Capture a single payment""" assert (purchase) if purchase.authorized_remaining == Decimal('0.00'): self.log_extra('No remaining authorizations on %s', purchase) return ProcessorResult(self.key, True, _("Already complete")) self.log_extra('Capturing Authorization #%i of %s', authorization.id, amount) if amount == NOTSET: amount = authorization.amount data = self.get_prior_auth_data(authorization, amount=amount) results = None if data: results = self.send_post(data, testing, purchase=purchase) return results
def send_post(self, data, testing=False, purchase=None, amount=NOTSET): """Execute the post to Authorize Net. Params: - data: dictionary as returned by get_standard_charge_data - testing: if true, then don't record the payment Returns: - ProcessorResult """ assert (purchase) self.log.info( "About to send a request to authorize.net: %(connection)s\n%(logPostString)s", data) conn = urllib2.Request(url=data['connection'], data=data['postString']) try: f = urllib2.urlopen(conn) all_results = f.read() self.log_extra('Authorize response: %s', all_results) except urllib2.URLError, ue: self.log.error("error opening %s\n%s", data['connection'], ue) return ProcessorResult( self.key, False, _('Could not talk to Authorize.net gateway'))
reason_code=status) else: payment = self.record_failure( purchase=purchase, amount=amount, transaction_id=transaction_id, reason_code=status, details=detail) return ProcessorResult(self.key, success, detail, payment=payment) except Exception, e: self.log.info('Error submitting payment: %s', e) payment = self.record_failure( purchase=purchase, amount=amount, transaction_id="", reason_code="error", details='Invalid response from bursar gateway') return ProcessorResult( self.key, False, _('Invalid response from bursar gateway')) else: return ProcessorResult(self.key, False, _('Error processing payment.'))
class PaymentProcessor(BasePaymentProcessor): """ Cybersource payment processing module You must have an account with Cybersource in order to use this module """ def __init__(self, settings={}): working_settings = { #This is the address to submit live transactions 'CONNECTION': 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.26.wsdl', #This is the address to submit test transactions 'CONNECTION_TEST': 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.26.wsdl', 'LIVE': False, 'LABEL': _('This will be passed to the translation utility'), 'CURRENCY_CODE': 'USD', 'CREDITCHOICES': ( (('American Express', 'American Express')), (('Visa','Visa')), (('Mastercard','Mastercard')), #(('Discover','Discover')) ), #Your Cybersource merchant ID - REQUIRED 'MERCHANT_ID': "", #Your Cybersource transaction key - REQUIRED 'TRANKEY': "", 'EXTRA_LOGGING': False } working_settings.update(settings) super(PaymentProcessor, self).__init__('cybersource', working_settings) self.require_settings('MERCHANT_ID', 'TRANKEY') self.contents = '' if self.is_live(): self.testflag = 'FALSE' self.connection = self.settings['CONNECTION'] else: self.testflag = 'TRUE' self.connection = self.settings['CONNECTION_TEST'] self.configuration = { 'merchantID' : self.settings['MERCHANT_ID'], 'password' : self.settings['TRANKEY'], } def prepare_content(self, purchase, amount): self.bill_to = { 'firstName' : purchase.first_name, 'lastName' : purchase.last_name, 'street1': purchase.full_bill_street, 'city': purchase.bill_city, 'state' : purchase.bill_state, 'postalCode' : purchase.bill_postal_code, 'country': purchase.bill_country, 'email' : purchase.email, 'phoneNumber' : purchase.phone, } exp = purchase.credit_card.expirationDate.split('/') self.card = { 'accountNumber' : purchase.credit_card.decryptedCC, 'expirationMonth' : exp[0], 'expirationYear' : exp[1], 'cvNumber' : purchase.credit_card.ccv } currency = self.settings['CURRENCY_CODE'] currency = currency.replace("_", "") self.purchase_totals = { 'currency' : currency, 'grandTotalAmount' : trunc_decimal(amount, 2), } def capture_payment(self, testing=False, purchase=None, amount=NOTSET): """ Creates and sends XML representation of transaction to Cybersource """ if purchase.remaining == Decimal('0.00'): self.log_extra('%s is paid in full, no capture attempted.', purchase) self.record_payment(purchase=purchase) return ProcessorResult(self.key, True, _("No charge needed, paid in full.")) self.log_extra('Capturing payment for %s', purchase) if amount==NOTSET: amount = purchase.remaining self.prepare_content(purchase, amount) invoice = "%s" % purchase.id failct = purchase.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) # XML format is very simple, using ElementTree for generation would be overkill t = loader.get_template('bursar/gateway/cybersource_gateway/request.xml') c = Context({ 'config' : self.configuration, 'merchantReferenceCode' : invoice, 'billTo' : self.bill_to, 'purchaseTotals' : self.purchase_totals, 'card' : self.card, }) request = t.render(c) self.log_extra("Cybersource request: %s", request) conn = urllib2.Request(url=self.connection, data=request) try: f = urllib2.urlopen(conn) except urllib2.HTTPError, e: # we probably didn't authenticate properly # make sure the 'v' in your account number is lowercase return ProcessorResult(self.key, False, 'Problem parsing results') f = urllib2.urlopen(conn) all_results = f.read() self.log_extra("Cybersource response: %s", all_results) tree = fromstring(all_results) parsed_results = tree.getiterator('{urn:schemas-cybersource-com:transaction-data-1.26}reasonCode') try: reason_code = parsed_results[0].text except KeyError: return ProcessorResult(self.key, False, 'Problem parsing results') response_text = CYBERSOURCE_RESPONSES.get(reason_code, 'Unknown Failure') if reason_code == '100': self.log_extra('%s successfully charged', purchase) payment = self.record_payment(purchase=purchase, amount=amount, transaction_id="", reason_code=reason_code) return ProcessorResult(self.key, True, response_text, payment=payment) else: payment = self.record_failure(purchase=purchase, amount=amount, transaction_id="", reason_code=reason_code, details=response_text) return ProcessorResult(self.key, False, response_text)
def capture_payment(self, testing=False, purchase=None, amount=NOTSET): """Execute the post to protx VSP DIRECT""" if not purchase: purchase = self.purchase if purchase.remaining == Decimal('0.00'): self.log_extra('%s is paid in full, no capture attempted.', purchase) self.record_payment(purchase=purchase) return ProcessorResult(self.key, True, _("No charge needed, paid in full.")) self.log_extra('Capturing payment for %s', purchase) if amount == NOTSET: amount = purchase.remaining self.prepare_post(purchase, amount) if self.valid: if self.settings['SKIP_POST']: self.log.info( "TESTING MODE - Skipping post to server. Would have posted %s?%s", self.url, self.postString) payment = self.record_payment(purchase=purchase, amount=amount, transaction_id="TESTING", reason_code='0') return ProcessorResult(self.key, True, _('TESTING MODE'), payment=payment) else: self.log_extra("About to post to server: %s?%s", self.url, self.postString) conn = urllib2.Request(self.url, data=self.postString) try: f = urllib2.urlopen(conn) result = f.read() self.log_extra('Process: url=%s\nPacket=%s\nResult=%s', self.url, self.packet, result) except urllib2.URLError, ue: self.log.error("error opening %s\n%s", self.url, ue) return ProcessorResult( self.key, False, 'ERROR: Could not talk to Protx gateway') try: self.response = dict( [row.split('=', 1) for row in result.splitlines()]) status = self.response['Status'] success = (status == 'OK') detail = self.response['StatusDetail'] payment = None transaction_id = "" if success: vpstxid = self.response.get('VPSTxID', '') txauthno = self.response.get('TxAuthNo', '') transaction_id = "%s,%s" % (vpstxid, txauthno) self.log.info( 'Success on purchase #%i, recording payment', self.purchase.id) payment = self.record_payment( purchase=purchase, amount=amount, transaction_id=transaction_id, reason_code=status) else: payment = self.record_failure( purchase=purchase, amount=amount, transaction_id=transaction_id, reason_code=status, details=detail) return ProcessorResult(self.key, success, detail, payment=payment) except Exception, e: self.log.info('Error submitting payment: %s', e) payment = self.record_failure( purchase=purchase, amount=amount, transaction_id="", reason_code="error", details='Invalid response from bursar gateway') return ProcessorResult( self.key, False, _('Invalid response from bursar gateway'))
payment = self.record_authorization( purchase=purchase, amount=amount, transaction_id=transaction_id, reason_code=reason_code) else: if amount <= 0: self.log_extra('Success, recording refund') else: self.log_extra('Success, recording payment') authorization = data.get('authorization', None) payment = self.record_payment(purchase=purchase, amount=amount, transaction_id=transaction_id, reason_code=reason_code, authorization=authorization) elif not testing: payment = self.record_failure(amount=amount, transaction_id=transaction_id, reason_code=reason_code, details=response_text, purchase=purchase) self.log_extra("Returning success=%s, reason=%s, response_text=%s", success, reason_code, response_text) return ProcessorResult(self.key, success, response_text, payment=payment)