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)])