def build_request(self, message_type, money, credit_card, **options):

        assert isinstance(money, Money), 'TODO  always pass in a Money object - no exceptions!'

        fields = default_dict(**self.options)

        grandTotalAmount = '%.2f' % money.amount  #  CONSIDER  format AMOUNT like this better, everywhere
        grandTotalAmount = grandTotalAmount.replace('.', '')  #  CONSIDER internationalize that and respect the CurrencyExponent
        if options.has_key('billing_address'):  fields.update(options['billing_address'])  #  TODO  what about address?
        fields.update(options)
        exp_code = ( '%02i' % credit_card.month) + str(credit_card.year)[-2:] #  CONSIDER  credit_card_format
        numeric = money.currency.numeric

        # print money.currency.__dict__  #  CONSIDER  where'z the exponent?

        if 2 != len(fields['country']):
            raise ValueError('Country code must be 2 characters (%s)' % fields['country'])

        x = XML

        new_order = x.NewOrder(
                        x.IndustryType('EC'),  #  'EC'ommerce - a web buy
                        x.MessageType(message_type),
                            #  A – Authorization request
                            #  AC – Authorization and Mark for Capture
                            #  FC – Force-Capture request
                            #   R – Refund request
                        x.BIN('000001'),
                        x.MerchantID(options['merchant_id']),
                        x.TerminalID('001'),
                        # x.CardBrand(''),

# TODO SW – Switch / Solo ED – European Direct Debit EC – Electronic Check BL – Bill Me Later DP – PINLess Debit [Generic Value Used in Requests]

                        x.AccountNum(credit_card.number),
                        x.Exp(exp_code),
                        x.CurrencyCode(numeric),
                        x.CurrencyExponent('2'),  #  CONSIDER  vary this when we vary the money type
                        x.CardSecValInd('1'),  #  CONSIDER  visa & discover only - nullify for others
                        x.CardSecVal(credit_card.verification_value),
                        x.AVSzip(fields['zip']),
                        x.AVSaddress1(fields['address1']),
                        x.AVSaddress2(fields['address2']),
                        x.AVScity(fields['city']),
                        x.AVSstate(fields['state']),
                        x.AVSphoneNum(fields['phone']),
                        x.AVSname(credit_card.first_name + ' ' + credit_card.last_name),
                        x.AVScountryCode(fields['country']), #  and ensure this is ISO-compliant or we get a DTD fault
                        #x.CustomerProfileFromOrderInd('A'), # TODO: make these optional
                        #x.CustomerProfileOrderOverrideInd('NO'),
                        x.OrderID(str(fields['order_id'])),  #  TODO  do blank order_id pass validation?
                        x.Amount(grandTotalAmount)
                        )
        return xStr(XML.Request(new_order))
    def build_authorization_request_TODO(
        self, money, credit_card, **options
    ):  #  where'd "NewOrder" come from? not in docs...
        assert isinstance(money, Money), "TODO  always pass in a Money object - no exceptions!"
        fields = default_dict(**self.options)
        grandTotalAmount = "%.2f" % money.amount  #  CONSIDER  format AMOUNT like this better, everywhere
        fields.update(options["billing_address"])  #  TODO  what about address?
        fields.update(options)
        exp_code = ("%02i" % credit_card.month) + str(credit_card.year)[-2:]  #  CONSIDER  credit_card_format
        x = XML
        numeric = money.currency.numeric

        new_order = x.NewOrder(
            x.OrbitalConnectionUsername(fields["login"]),  #  TODO  from configs
            x.OrbitalConnectionPassword(fields["password"]),  #  TODO  ibid
            x.IndustryType("EC"),  #  'EC'ommerce - a web buy
            x.MessageType("A"),  #  auth fwt!
            # TODO  hallow A – Authorization request AC – Authorization and Mark for Capture FC – Force-Capture request R – Refund request
            x.BIN("1"),
            x.MerchantID("1"),
            x.TerminalID("1"),
            x.CardBrand(""),
            # TODO SW – Switch / Solo ED – European Direct Debit EC – Electronic Check BL – Bill Me Later DP – PINLess Debit [Generic Value Used in Requests]
            x.AccountNum(credit_card.number),
            x.Exp(exp_code),
            x.CurrencyCode(numeric),
            x.CurrencyExponent("2"),  #  TODO  figure out what this is it's probably important
            x.CardSecValInd("1"),  #  CONSIDER  visa & discover only - nullify for others
            x.CardSecVal(credit_card.verification_value),
            x.AVSzip(fields["zip"]),
            x.AVSaddress1(fields["address1"]),  #  TODO  pull an AVSresponse?
            x.AVSaddress2(fields["address2"]),
            x.AVScity(fields["city"]),
            x.AVSstate(fields["state"]),
            x.AVSphoneNum(fields["phone"]),
            x.AVSname(credit_card.first_name + " " + credit_card.last_name),
            x.AVScountryCode("840"),  #  CONSIDER  other countries
            x.CustomerProfileFromOrderInd("A"),
            x.CustomerProfileOrderOverrideInd("NO"),
            x.OrderID(""),  #  TODO
            x.Amount(grandTotalAmount),
        )
        return xStr(XML.Request(new_order))
    def build_authorization_request(self, money, credit_card, **options):
        numeric = money.currency.numeric

        return xStr(
            XML.Request(
                XML.AC(
                    XML.CommonData(
                        XML.CommonMandatory(
                            XML.AccountNum("4012888888881", AccountTypeInd="91"),
                            XML.POSDetails(POSEntryMode="01"),
                            XML.MerchantID("123456789012"),
                            XML.TerminalID(
                                "001",
                                TermEntCapInd="05",
                                CATInfoInd="06",
                                TermLocInd="01",
                                CardPresentInd="N",
                                POSConditionCode="59",
                                AttendedTermDataInd="01",
                            ),
                            XML.BIN("000002"),
                            XML.OrderID("1234567890123456"),
                            XML.AmountDetails(XML.Amount("000000005000")),
                            XML.TxTypeCommon(TxTypeID="G"),
                            XML.Currency(CurrencyCode=numeric, CurrencyExponent="2"),
                            XML.CardPresence(XML.CardNP(XML.Exp("1205"))),
                            XML.TxDateTime(),
                            AuthOverrideInd="N",
                            LangInd="00",
                            CardHolderAttendanceInd="01",
                            HcsTcsInd="T",
                            TxCatg="7",
                            MessageType="A",
                            Version="2",
                            TzCode="705",
                        ),
                        XML.CommonOptional(
                            XML.Comments("This is an AVS/CVV2 auth request"),
                            XML.ShippingRef("FEDEX WB12345678 Pri 1"),
                            XML.CardSecVal("705", CardSecInd="1"),
                            XML.ECommerceData(XML.ECOrderNum("1234567890123456"), ECSecurityInd="07"),
                        ),
                    ),
                    XML.Auth(
                        XML.AuthMandatory(FormatInd="H"),
                        XML.AuthOptional(
                            XML.AVSextended(
                                XML.AVSname("JOE SMITH"),
                                XML.AVSaddress1("1234 WEST MAIN STREET"),
                                XML.AVSaddress2("SUITE 123"),
                                XML.AVScity("TAMPA"),
                                XML.AVSstate("FL"),
                                XML.AVSzip("33123-1234"),
                                XML.AVScountryCode("US"),
                            )
                        ),
                    ),
                    XML.Cap(XML.CapMandatory(XML.EntryDataSrc("02")), XML.CapOptional()),
                )
            )
        )