def build_afs_request(self, money, credit_card, **options): """ Build an AFS only request. This deals directly with only the anti-fraud system rather than the full auth. process """ entries = XMLDict([('merchantID', self.merchant_id), ('merchantReferenceCode', self.get_merchant_reference_code(options))]) if 'address' in options: entries['billTo'] = self.build_bill_to(credit_card, options['address']) if 'basket_items' in options and len(options['basket_items']): for item in options['basket_items']: entry = XMLDict({'unitPrice': str(item['amount']), 'quantity': str(item['quantity'])}, attrib={'id': str(item['id'])}) entry['productName'] = item['description'] entry['totalAmount'] = str(item['totalAmount']) entries.appendlist('item', entry) else: entries['item'] = XMLDict({'unitPrice': str(money.amount), 'quantity': 1}, attrib={'id': '0'}) entries['item']['productName'] = options.get('description', '') entries['item']['totalAmount'] = str(money.amount) entries['purchaseTotals'] = self.build_grand_total(money) entries['fundingTotals'] = self.build_grand_total(money) if credit_card: entries['card'] = self.build_card(credit_card) # merchantDefinedData is a [] and should be in the order you # want it sorted in the field0-20. If it's longer than 20, # CyberSource will probably reject it. if options.get('merchantDefinedData'): entries['merchantDefinedData'] = XMLDict() field = 1 for v in options['merchantDefinedData']: entries['merchantDefinedData']['field%d' % field] = v field += 1 entries['afsService'] = XMLDict(attrib={'run': 'true'}) business_rules = self.build_business_rules(options) if business_rules: entries['businessRules'] = business_rules # Used for device fingerprinting - you should read the # documentation about what to put here. It's under NDA. if options.get('session_id'): entries['deviceFingerprintID'] = options['session_id'] return self.build_soap(entries)
def cccreditservice(self, data): response = XMLDict([('merchantReferenceCode', data['merchantReferenceCode']), ('requestID', '0305782650000167905080'), ('decision', 'ACCEPT'), ('reasonCode', '100'), ('requestToken', 'AA4JUrWguaLLQxMUGwxSWVdPS1BIRk5IMUwA2yCv'), ('purchaseTotals', {'currency':data['purchaseTotals']['currency']}), ('ccCreditReply', XMLDict([('reasonCode', '100'), ('amount', data['purchaseTotals']['grandTotalAmount']), ('reconciliationID', '1094820975023470'), ])), ]) return response
def build_capture_request(self, money, authorization, **options): entries = XMLDict([ ('merchantID', self.merchant_id), ('merchantReferenceCode', self.get_merchant_reference_code(options)), ]) entries['purchaseTotals'] = self.build_grand_total(money) tokens = self.parse_tokens(authorization) entries['orderRequestToken'] = tokens['request_token'] entries['ccCaptureService'] = XMLDict( [('authRequestID', tokens['request_id'])], attrib={'run': 'true'}) business_rules = self.build_business_rules(options) if business_rules: entries['businessRules'] = business_rules return self.build_soap(entries)
def common_response(self, data): return XMLDict([ ('IndustryType', data['IndustryType']), ('MessageType', data['MessageType']), ('MerchantID', data['MerchantID']), ('TerminalID', data['TerminalID']), ])
def build_authorization_request(self, money, credit_card, **options): entries = XMLDict([ ('merchantID', self.merchant_id), ('merchantReferenceCode', self.get_merchant_reference_code(options)), ]) if 'address' in options: entries['billTo'] = self.build_bill_to(credit_card, options['address']) entries['purchaseTotals'] = self.build_grand_total(money) entries['card'] = self.build_card(credit_card) entries['ccAuthService'] = XMLDict(attrib={'run': 'true'}) business_rules = self.build_business_rules(options) if business_rules: entries['businessRules'] = business_rules return self.build_soap(entries)
def ccauthservice(self, data): response = XMLDict([('merchantReferenceCode', data['merchantReferenceCode']), ('requestID', '0305782650000167905080'), ('decision', 'ACCEPT'), ('reasonCode', '100'), ('requestToken', 'AA4JUrWguaLLQxMUGwxSWVdPS1BIRk5IMUwA2yCv'), ('purchaseTotals', {'currency':data['purchaseTotals']['currency']}), ('ccAuthReply', XMLDict([('reasonCode', '100'), ('amount', data['purchaseTotals']['grandTotalAmount']), ('authorizationCode', '123456'), ('avsCode', 'Y'), ('avsCodeRaw', 'YYY'), ('processorResponse', 'A'), ('accountBalance', data['purchaseTotals']['grandTotalAmount']), ])), ]) return response
def build_card(self, credit_card): return XMLDict([ ('accountNumber', credit_card.number), ('expirationMonth', credit_card.month), ('expirationYear', credit_card.year), ('cvNumber', credit_card.verification_value), # ('cardType', self.get_cybersource_card_type(credit_card)), # TODO - fix the value we get from the get_cybersource_card_type call - it is always returing '005', which is "Diner's Club." # I am commenting it out for now, because it's optional for all card types; except for JCB, which we don't accept. ])
def reversal(self, data): response = XMLDict([ ('MerchantID', data['MerchantID']), ('TerminalID', data['TerminalID']), ('OrderID', data.get('OrderID', '')), ('TxRefNum', '4A785F5106CCDC41A936BFF628BF73036FEC5401'), ('TxRefIdx', '1'), ('OutstandingAmt', '0'), ('ProcStatus', '0'), ('StatusMsg', 'Approved'), ('RespTime', '121825'), ]) return {'ReversalResp': response}
def build_reversal_request(self, authorization, **options): entries = XMLDict([ ('merchantID', self.merchant_id), ('merchantReferenceCode', self.get_merchant_reference_code(options)), ]) #TODO do we need money? if 'money' in options: entries['purchaseTotals'] = self.build_grand_total( options['money']) else: entries['purchaseTotals'] = XMLDict([ ('currency', 'USD'), ('grandTotalAmount', 100), ]) tokens = self.parse_tokens(authorization) entries['orderRequestToken'] = tokens['request_token'] entries['ccAuthReversalService'] = XMLDict( [('authRequestID', tokens['request_id'])], attrib={'run': 'true'}) business_rules = self.build_business_rules(options) if business_rules: entries['businessRules'] = business_rules return self.build_soap(entries)
def build_business_rules(self, options): parts = list() def check_options(key): if options.get(key, False): parts.append((key, options[key])) for option in [ 'ignoreAVSResult', 'ignoreCVResult', 'ignoreDAVResult', 'ignoreExportResult', 'ignoreValidateResult', 'declineAVSFlags', 'scoreThreshold' ]: check_options(option) if parts: return XMLDict(parts)
def markforcapture(self, data): response = XMLDict([ ('MerchantID', data['MerchantID']), ('TerminalID', data['TerminalID']), ('OrderID', data.get('OrderID', '')), ('TxRefNum', '4A785F5106CCDC41A936BFF628BF73036FEC5401'), ('TxRefIdx', '1'), ('Amount', data.get('Amount')), ('ProcStatus', '0'), ('StatusMsg', 'Approved'), ('RespTime', '121825'), ('ApprovalStatus', '1'), ('RespCode', '00'), ('AVSRespCode', 'B'), ('AuthCode', 'tst554'), ('RespMsg', None), ('HostRespCode', '100'), ('HostAVSRespCode', 'I3'), ]) return {'MarkForCaptureResp': response}
def neworder(self, data): response = self.common_response(data) if data['MessageType'] in ('A', 'AC'): assert data.get('AccountNum') or data.get('CustomerRefNum') elif data['MessageType'] in ('FC', 'R'): assert data.get('TxRefNum') else: assert False, 'Invalid Message Type: %s' % data['MessageType'] response.update( XMLDict([ ('CardBrand', 'MC'), ('AccountNum', data.get('AccountNum')), ('OrderID', data.get('OrderID', '')), ('TxRefNum', '4A785F5106CCDC41A936BFF628BF73036FEC5401'), ('TxRefIdx', '1'), ('ProcStatus', '0'), ('ApprovalStatus', '1'), ('RespCode', '00'), ('AVSRespCode', 'B'), ('CVV2RespCode', 'M'), ('AuthCode', 'tst554'), ('RecurringAdviceCd', None), ('CAVVRespCode', None), ('StatusMsg', 'Approved'), ('RespMsg', None), ('HostRespCode', '100'), ('HostAVSRespCode', 'I3'), ('HostCVV2RespCode', 'M'), ('CustomerRefNum', '2145108'), ('CustomerName', data.get('AVSname')), ('ProfileProcStatus', '0'), ('CustomerProfileMessage', 'Profile Created'), ('RespTime', '121825'), ('PartialAuthOccurred', ''), ('RequestedAmount', ''), ('RedeemedAmount', ''), ('RemainingBalance', ''), ('CountryFraudFilterStatus', ''), ('IsoCountryCode', data.get('AVScountryCode', '')), ])) return {'NewOrderResp': response}
def build_bill_to(self, credit_card, address): if credit_card: first_name = credit_card.first_name last_name = credit_card.last_name else: first_name = address.get('first_name') last_name = address.get('last_name') return XMLDict([ ('firstName', first_name), ('lastName', last_name), ('street1', address['address1']), ('street2', address.get('address2', '')), ('city', address['city']), ('state', address['state']), ('postalCode', address['zip']), ('country', address['country']), ('phoneNumber', address.get('phone')), ('email', address.get('email', '*****@*****.**') ), # TODO: test server complains if there is no email ('ipAddress', address.get('ipaddress')), ])
def profile(self, data): response = XMLDict([ ('CustomerBin', data['CustomerBin']), ('CustomerMerchantID', data['CustomerMerchantID']), ('CustomerName', data['CustomerName']), ('CustomerRefNum', 'CUSTOMERREFNUM'), ('CustomerProfileAction', 'CREATE'), ('ProfileProcStatus', '0'), ('CustomerProfileMessage', 'Profile Request Processed'), ('CustomerAddress1', data['CustomerAddress1']), ('CustomerAddress2', data.get('CustomerAddress2', '')), ('CustomerCity', data['CustomerCity']), ('CustomerState', data['CustomerState']), ('CustomerZIP', data['CustomerZIP']), ('CustomerEmail', data.get('CustomerEmail', '')), ('CustomerPhone', data['CustomerPhone']), ('CustomerCountryCode', data['CustomerCountryCode']), ('CustomerProfileOrderOverrideInd', data['CustomerProfileOrderOverrideInd']), ('OrderDefaultDescription', data.get('OrderDefaultDescription', '')), ('OrderDefaultAmount', data.get('OrderDefaultAmount', '')), ('CustomerAccountType', data['CustomerAccountType']), ('Status', data.get('Status', 'A')), ('CardBrand', data.get('CardBrand', '')), ('CCAccountNum', data['CCAccountNum']), ('CCExpireDate', data['CCExpireDate']), ('ECPAccountDDA', ''), ('ECPAccountType', ''), ('ECPAccountRT', ''), ('ECPBankPmtDlv', ''), ('SwitchSoloStartDate', ''), ('SwitchSoloIssueNum', ''), ('BillerReferenceNumber', ''), ('RespTime', ''), ]) return {'ProfileResp': response}
def build_afs_request(self, money, credit_card, **options): """ Build an AFS only request. This deals directly with only the anti-fraud system rather than the full auth. process """ entries = XMLDict([('merchantID', self.merchant_id), ('merchantReferenceCode', self.get_merchant_reference_code(options))]) if 'address' in options: entries['billTo'] = self.build_bill_to(credit_card, options['address']) if 'basket_items' in options and len(options['basket_items']): for item in options['basket_items']: entry = XMLDict( { 'unitPrice': str(item['amount']), 'quantity': str(item['quantity']) }, attrib={'id': str(item['id'])}) entry['productName'] = item['description'] entry['totalAmount'] = str(item['totalAmount']) entries.appendlist('item', entry) else: entries['item'] = XMLDict( { 'unitPrice': str(money.amount), 'quantity': 1 }, attrib={'id': '0'}) entries['item']['productName'] = options.get('description', '') entries['item']['totalAmount'] = str(money.amount) entries['purchaseTotals'] = self.build_grand_total(money) entries['fundingTotals'] = self.build_grand_total(money) if credit_card: entries['card'] = self.build_card(credit_card) # merchantDefinedData is a [] and should be in the order you # want it sorted in the field0-20. If it's longer than 20, # CyberSource will probably reject it. if options.get('merchantDefinedData'): entries['merchantDefinedData'] = XMLDict() field = 1 for v in options['merchantDefinedData']: entries['merchantDefinedData']['field%d' % field] = v field += 1 entries['afsService'] = XMLDict(attrib={'run': 'true'}) business_rules = self.build_business_rules(options) if business_rules: entries['businessRules'] = business_rules # Used for device fingerprinting - you should read the # documentation about what to put here. It's under NDA. if options.get('session_id'): entries['deviceFingerprintID'] = options['session_id'] return self.build_soap(entries)
def build_grand_total(self, money): return XMLDict([('currency', money.currency.code), ('grandTotalAmount', money.amount)])