Example #1
0
    def prepareData(self, data):
        self.bill_to = {
            'firstName' : data.contact.first_name,
            'lastName' : data.contact.last_name,
            'street1': data.full_bill_street,
            'city': data.bill_city,
            'state' : data.bill_state,
            'postalCode' : data.bill_postal_code,
            'country': data.bill_country,
            'email' : data.contact.email,
            'phoneNumber' : data.contact.primary_phone,
            # Can add additional info here if you want to but it's not required
            }
        exp = data.credit_card.expirationDate.split('/')
        self.card = {
            'accountNumber' : data.credit_card.decryptedCC,
            'expirationMonth' : exp[0],
            'expirationYear' : exp[1],
            'cvNumber' : data.credit_card.ccv
            }
        currency = self.settings.CURRENCY_CODE.value
        currency = currency.replace("_", "")
        self.purchase_totals = {
            'currency' : currency,
            'grandTotalAmount' : trunc_decimal(data.balance, 2),
        }

        self.order = data
Example #2
0
    def prepareData(self, data):
        self.bill_to = {
            "firstName": data.contact.first_name,
            "lastName": data.contact.last_name,
            "street1": data.full_bill_street,
            "city": data.bill_city,
            "state": data.bill_state,
            "postalCode": data.bill_postal_code,
            "country": data.bill_country,
            "email": data.contact.email,
            "phoneNumber": data.contact.primary_phone,
            # Can add additional info here if you want to but it's not required
        }
        exp = data.credit_card.expirationDate.split("/")
        self.card = {
            "accountNumber": data.credit_card.decryptedCC,
            "expirationMonth": exp[0],
            "expirationYear": exp[1],
            "cvNumber": data.credit_card.ccv,
        }
        currency = self.settings.CURRENCY_CODE.value
        currency = currency.replace("_", "")
        self.purchase_totals = {"currency": currency, "grandTotalAmount": trunc_decimal(data.balance, 2)}

        self.order = data
Example #3
0
def set_quantity_ajax(request, template="json.html"):
    """Set the quantity for a cart item, returning results formatted for handling by script.
       **FORK: Added set cart item notes while updating cart.
    """
    data = {}
    if not request.POST:
        data['results'] = False
        data['errors'] = _('Internal error: please submit as a POST')

    else:
        success, cart, cartitem, errors = _set_quantity(request)

        data['results'] = success
        data['errors'] = errors

        # note we have to convert Decimals to strings, since simplejson doesn't know about Decimals
        if cart:
            carttotal = str(trunc_decimal(cart.total, 2))
            cartqty = cart.numItems
        else:
            carttotal = "0.00"
            cartqty = 0

        data['cart_total'] = carttotal
        data['cart_count'] = cartqty

        if cartitem:
            itemid = cartitem.id
            itemqty = cartitem.quantity
            notes = cartitem.notes
            price = str(trunc_decimal(cartitem.line_total, 2))
        else:
            itemid = -1
            itemqty = 0
            notes = ""
            price = "0.00"

        data['item_id'] = itemid
        data['item_qty'] = itemqty
        data['item_price'] = price
        data['notes'] = notes

    encoded = JSONEncoder().encode(data)
    encoded = mark_safe(encoded)
    return render_to_response(template, {'json': encoded})
Example #4
0
def moneyfmt(val, curr=None, places=-1, grouping=True, wrapcents="", current_locale=None):
    """Formats val according to the currency settings in the current locale.
    Ported-and-modified from Python 2.5
    """
    conv = get_locale_conv(current_locale)

    if places < 0:
        places = conv["int_frac_digits"]

    val = trunc_decimal(val, places)

    try:  # Required because Python < 2.5 does not have monetary arg
        s = format("%%.%if" % places, abs(val), conv, grouping, monetary=True)
    except TypeError:
        s = format("%%.%if" % places, abs(val), conv, grouping)
    # '<' and '>' are markers if the sign must be inserted between symbol and value
    s = "<" + s + ">"

    if curr is None:
        curr = config_value("SHOP", "CURRENCY")
        curr = curr.replace("_", " ")
    precedes = conv[val < 0 and "n_cs_precedes" or "p_cs_precedes"]
    separated = conv[val < 0 and "n_sep_by_space" or "p_sep_by_space"]

    if precedes:
        s = curr + (separated and " " or "") + s
    else:
        s = s + (separated and " " or "") + curr

    sign_pos = conv[val < 0 and "n_sign_posn" or "p_sign_posn"]
    sign = conv[val < 0 and "negative_sign" or "positive_sign"]

    if sign_pos == 0:
        s = "(" + s + ")"
    elif sign_pos == 1:
        s = sign + s
    elif sign_pos == 2:
        s = s + sign
    elif sign_pos == 3:
        s = s.replace("<", sign)
    elif sign_pos == 4:
        s = s.replace(">", sign)
    else:
        # the default if nothing specified;
        # this should be the most fitting sign position
        s = sign + s

    val = s.replace("<", "").replace(">", "")

    if wrapcents:
        pos = s.rfind(conv["decimal_point"])
        if pos > -1:
            pos += 1
            val = u"%s<%s>%s</%s>" % val[:pos], wrapcents, val[pos:], wrapcents

    return val
Example #5
0
def confirm_info(request):
    "Create form to send to WorldPay"
    # Check that items are in stock
    cart = Cart.objects.from_request(request)
    if cart.not_enough_stock():
        return HttpResponseRedirect(reverse("satchmo_cart"))

    try:
        order = Order.objects.from_request(request)
    except Order.DoesNotExist:
        order = None

    if not (order and order.validate(request)):
        context = {"message": _("Your order is no longer valid.")}

        return render(request, "shop_404.html", context)

    template = lookup_template(payment_module,
                               "checkout/worldpay/confirm.html")

    live = payment_module.LIVE.value
    currency = order.currency.iso_4217_code
    inst_id = payment_module.INSTID.value
    default_view_tax = config_value("TAX", "DEFAULT_VIEW_TAX")

    if live:
        post_url = payment_module.CONNECTION.value
    else:
        post_url = payment_module.CONNECTION_TEST.value

    if payment_module.MD5.value > "":
        # Doing the MD5 Signature dance
        # Generating secret "secret;amount;currency;cartId"
        balance = trunc_decimal(order.balance, 2)
        signature = "%s:%s:%s:%s" % (
            payment_module.MD5.value,
            balance,
            currency,
            order.id,
        )
        MD5 = md5(signature).hexdigest()
    else:
        MD5 = False

    ctx = {
        "order": order,
        "inst_id": inst_id,
        "currency": currency,
        "post_url": post_url,
        "default_view_tax": default_view_tax,
        "PAYMENT_LIVE": live,
        "MD5": MD5,
        "session": request.session.session_key,
    }
    return render(request, template, ctx)
Example #6
0
def set_quantity_ajax(request, template="json.html"):
    """Set the quantity for a cart item, returning results formatted for handling by script.
    """
    data = {}
    if not request.POST:
        data["results"] = False
        data["errors"] = _("Internal error: please submit as a POST")

    else:
        success, cart, cartitem, errors = _set_quantity(request)

        data["results"] = success
        data["errors"] = errors

        # note we have to convert Decimals to strings, since json doesn't know about Decimals
        if cart:
            carttotal = str(trunc_decimal(cart.total, 2))
            cartqty = cart.numItems
        else:
            carttotal = "0.00"
            cartqty = 0

        data["cart_total"] = carttotal
        data["cart_count"] = cartqty

        if cartitem:
            itemid = cartitem.id
            itemqty = cartitem.quantity
            price = str(trunc_decimal(cartitem.line_total, 2))
        else:
            itemid = -1
            itemqty = 0
            price = "0.00"

        data["item_id"] = itemid
        data["item_qty"] = itemqty
        data["item_price"] = price

    encoded = json.JSONEncoder().encode(data)
    encoded = mark_safe(encoded)
    return render(template, {"json": encoded})
Example #7
0
def set_quantity_ajax(request, template="json.html"):
    """Set the quantity for a cart item, returning results formatted for handling by script.
    """
    data = {}
    if not request.POST:
        data["results"] = False
        data["errors"] = _("Internal error: please submit as a POST")

    else:
        success, cart, cartitem, errors = _set_quantity(request)

        data["results"] = success
        data["errors"] = errors

        # note we have to convert Decimals to strings, since json doesn't know about Decimals
        if cart:
            carttotal = str(trunc_decimal(cart.total, 2))
            cartqty = cart.numItems
        else:
            carttotal = "0.00"
            cartqty = 0

        data["cart_total"] = carttotal
        data["cart_count"] = cartqty

        if cartitem:
            itemid = cartitem.id
            itemqty = cartitem.quantity
            price = str(trunc_decimal(cartitem.line_total, 2))
        else:
            itemid = -1
            itemqty = 0
            price = "0.00"

        data["item_id"] = itemid
        data["item_qty"] = itemqty
        data["item_price"] = price

    encoded = json.JSONEncoder().encode(data)
    encoded = mark_safe(encoded)
    return render(template, {"json": encoded})
Example #8
0
def confirm_info(request):
    "Create form to send to WorldPay"
    # Check that items are in stock
    cart = Cart.objects.from_request(request)
    if cart.not_enough_stock():
        return HttpResponseRedirect(urlresolvers.reverse("satchmo_cart"))

    try:
        order = Order.objects.from_request(request)
    except Order.DoesNotExist:
        order = None

    if not (order and order.validate(request)):
        context = RequestContext(
            request, {'message': _('Your order is no longer valid.')})
        return render_to_response('shop_404.html', context)

    template = lookup_template(payment_module,
                               'checkout/worldpay/confirm.html')

    live = payment_module.LIVE.value
    currency = payment_module.CURRENCY_CODE.value
    inst_id = payment_module.INSTID.value
    default_view_tax = config_value('TAX', 'DEFAULT_VIEW_TAX')

    if live:
        post_url = payment_module.CONNECTION.value
    else:
        post_url = payment_module.CONNECTION_TEST.value

    if payment_module.MD5.value > "":
        # Doing the MD5 Signature dance
        # Generating secret "secret;amount;currency;cartId"
        balance = trunc_decimal(order.balance, 2)
        signature = "%s:%s:%s:%s" % (payment_module.MD5.value, balance,
                                     currency, order.id)
        MD5 = md5(signature).hexdigest()
    else:
        MD5 = False

    ctx = RequestContext(
        request, {
            'order': order,
            'inst_id': inst_id,
            'currency': currency,
            'post_url': post_url,
            'default_view_tax': default_view_tax,
            'PAYMENT_LIVE': live,
            'MD5': MD5,
            'session': request.session.session_key
        })
    return render_to_response(template, ctx)
Example #9
0
def confirm_info(request):
    "Create form to send to WorldPay"
    # Check that items are in stock
    cart = Cart.objects.from_request(request)
    if cart.not_enough_stock():
        return HttpResponseRedirect(urlresolvers.reverse("satchmo_cart"))

    try:
        order = Order.objects.from_request(request)
    except Order.DoesNotExist:
        order = None

    if not (order and order.validate(request)):
        context = RequestContext(request,
            {'message': _('Your order is no longer valid.')})
        return render_to_response('shop_404.html', context)

    template = lookup_template(payment_module, 'checkout/worldpay/confirm.html')


    live = payment_module.LIVE.value
    currency = payment_module.CURRENCY_CODE.value
    inst_id = payment_module.INSTID.value
    default_view_tax = config_value('TAX', 'DEFAULT_VIEW_TAX')

    if live:
        post_url = payment_module.CONNECTION.value
    else:
        post_url = payment_module.CONNECTION_TEST.value

    if payment_module.MD5.value > "":
        # Doing the MD5 Signature dance
        # Generating secret "secret;amount;currency;cartId"
        balance = trunc_decimal(order.balance, 2)
        signature = "%s:%s:%s:%s" % (payment_module.MD5.value, balance, currency, order.id)
        MD5 = md5(signature).hexdigest()
    else:
        MD5 = False

    ctx = RequestContext(request, {
        'order': order,
        'inst_id': inst_id,
        'currency': currency,
        'post_url': post_url,
        'default_view_tax': default_view_tax,
        'PAYMENT_LIVE' : live,
        'MD5' : MD5,
        'session' : request.session.session_key
    })
    return render_to_response(template, ctx)
Example #10
0
 def prepareData(self, data):
     try:
         cc = data.credit_card
         balance = trunc_decimal(data.balance, 2)
         self.packet['VendorTxCode'] = data.id
         self.packet['Amount'] = balance
         self.packet['Description'] = 'Online purchase'
         self.packet['CardType'] = cc.credit_type
         self.packet['CardHolder'] = cc.card_holder
         self.packet['CardNumber'] = cc.decryptedCC
         self.packet['ExpiryDate'] = '%02d%s' % (cc.expire_month, str(cc.expire_year)[2:])
         if cc.start_month is not None:
             self.packet['StartDate'] = '%02d%s' % (cc.start_month, str(cc.start_year)[2:])
         if cc.ccv is not None and cc.ccv != "":
             self.packet['CV2'] = cc.ccv
         if cc.issue_num is not None and cc.issue_num != "":
             self.packet['IssueNumber'] = cc.issue_num #'%02d' % int(cc.issue_num)
         addr = [data.bill_street1, data.bill_street2, data.bill_city, data.bill_state]
         self.packet['BillingAddress'] = ', '.join(addr)
         self.packet['BillingPostCode'] = data.bill_postal_code
     except Exception, e:
         log.error('preparing data, got error: %s\nData: %s', e, data)
         self.valid = False
         return
Example #11
0
def truncate_decimal(val, places=2):
    return trunc_decimal(val, places)
Example #12
0
    def getRecurringChargeData(self, testing=False):
        """Build the list of dictionaries needed to process a recurring charge.
        
        Because Authorize can only take one subscription at a time, we build a list
        of the transaction dictionaries, for later sequential posting.
        """
        if not self.arb_enabled:
            return []

        # get all subscriptions from the order
        subscriptions = self.get_recurring_orderitems()

        if len(subscriptions) == 0:
            self.log_extra('No subscription items')
            return []

        settings = self.settings
        # set up the base dictionary
        trans = {}

        if self.is_live():
            conn = settings.ARB_CONNECTION.value
            self.log_extra('Using live recurring charge connection.')
        else:
            conn = settings.ARB_CONNECTION_TEST.value
            self.log_extra('Using test recurring charge connection.')

        shop_config = Config.objects.get_current()

        trans['connection'] = conn
        trans['config'] = {
            'merchantID': settings.LOGIN.value,
            'transactionKey': settings.TRANKEY.value,
            'shop_name': shop_config.store_name,
        }
        trans['order'] = self.order
        trans['card'] = self.order.credit_card
        trans['card_expiration'] = "%4i-%02i" % (
            self.order.credit_card.expire_year,
            self.order.credit_card.expire_month)

        translist = []
        taxer = get_tax_processor(user=self.order.contact.user)

        for subscription in subscriptions:
            product = subscription.product
            subtrans = trans.copy()
            subtrans['subscription'] = subscription
            subtrans['product'] = product

            sub = product.subscriptionproduct

            trial = sub.get_trial_terms(0)
            if trial:
                price = trunc_decimal(trial.price, 2)
                trial_amount = price
                if price and subscription.product.taxable:
                    trial_amount = taxer.by_price(
                        subscription.product.taxClass, price)
                    #todo, maybe add shipping for trial?
                amount = sub.recurring_price()
                trial_occurrences = trial.occurrences
                if not trial_occurrences:
                    self.log.warn(
                        "Trial expiration period is less than one recurring billing cycle. "
                        +
                        "Authorize does not allow this, so the trial period has been adjusted to be equal to one recurring cycle."
                    )
                    trial_occurrences = 1
            else:
                trial_occurrences = 0
                trial_amount = Decimal('0.00')
                amount = subscription.total_with_tax

            occurrences = sub.recurring_times + trial_occurrences
            if occurrences > 9999:
                occurrences = 9999

            subtrans['occurrences'] = occurrences
            subtrans['trial_occurrences'] = trial_occurrences
            subtrans['trial'] = trial
            subtrans['trial_amount'] = trunc_decimal(trial_amount, 2)
            subtrans['amount'] = trunc_decimal(amount, 2)
            if trial:
                charged_today = trial_amount
            else:
                charged_today = amount

            charged_today = trunc_decimal(charged_today, 2)

            subtrans['charged_today'] = charged_today
            translist.append(subtrans)

        return translist
Example #13
0
    def getStandardChargeData(self):
        """Build the dictionary needed to process a credit card charge"""
        order = self.order
        if order.paid_in_full:
            self.log_extra('No standard charges, order is paid in full.')
            return None

        settings = self.settings
        trans = {}
        balance = trunc_decimal(order.balance, 2)
        trans['amount'] = balance
        
        if self.is_live():
            conn = settings.CONNECTION.value
            self.log_extra('Using live connection.')
        else:
            testflag = 'TRUE'
            conn = settings.CONNECTION_TEST.value
            self.log_extra('Using test connection.')
            
        if self.settings.SIMULATE.value:
            testflag = 'TRUE'
        else:
            testflag = 'FALSE'

        trans['connection'] = conn
            
        capture = settings.CAPTURE.value
        trans['authorize_only'] = not capture

        if capture:
            transaction_type = 'AUTH_CAPTURE'
            self.log_extra('Will capture payment.')
        else:
            transaction_type = 'AUTH_ONLY'
            self.log_extra('Authorizing payment, no capture.')
                        
        trans['configuration'] = {
            'x_login' : settings.LOGIN.value,
            'x_tran_key' : settings.TRANKEY.value,
            'x_version' : '3.1',
            'x_relay_response' : 'FALSE',
            'x_test_request' : testflag,
            'x_delim_data' : 'TRUE',
            'x_delim_char' : '|',
            'x_type': transaction_type,
            'x_method': 'CC',
            }
        
        self.log_extra('standard charges configuration: %s', trans['configuration'])
        
        trans['custBillData'] = {
            'x_first_name' : order.contact.first_name,
            'x_last_name' : order.contact.last_name,
            'x_address': order.full_bill_street,
            'x_city': order.bill_city,
            'x_state' : order.bill_state,
            'x_zip' : order.bill_postal_code,
            'x_country': order.bill_country,
            'x_phone' : order.contact.primary_phone
            }
    
        self.log_extra('standard charges configuration: %s', trans['custBillData'])
        balance = trunc_decimal(order.balance, 2)
        trans['amount'] = balance
        
        trans['transactionData'] = {
            'x_amount' : balance,
            'x_card_num' : order.credit_card.decryptedCC,
            'x_exp_date' : order.credit_card.expirationDate,
            'x_card_code' : order.credit_card.ccv,
            'x_invoice_num' : order.id
            }

        part1 = urlencode(trans['configuration']) + "&"
        part2 = "&" + urlencode(trans['custBillData'])
        trans['postString'] = part1 + urlencode(trans['transactionData']) + part2
        
        redactedData = {
            'x_amount' : balance,
            'x_card_num' : order.credit_card.display_cc,
            'x_exp_date' : order.credit_card.expirationDate,
            'x_card_code' : "REDACTED",
            'x_invoice_num' : order.id
        }
        self.log_extra('standard charges transactionData: %s', redactedData)
        trans['logPostString'] = part1 + urlencode(redactedData) + part2
        
        return trans
Example #14
0
 def test_equal_to_half_rounds_up(self):
     self.assertEqual(trunc_decimal("0.005", 2), Decimal("0.01"))
Example #15
0
def truncate_decimal(val, places=2):
    return trunc_decimal(val, places)
Example #16
0
 def test_over_half_rounds_up(self):
     self.assertEqual(trunc_decimal("0.009", 2), Decimal("0.01"))
Example #17
0
 def test_under_half_rounds_down(self):
     self.assertEqual(trunc_decimal("0.004", 2), Decimal("0.00"))
Example #18
0
    def getRecurringChargeData(self, testing=False):
        """Build the list of dictionaries needed to process a recurring charge.
        
        Because Authorize can only take one subscription at a time, we build a list
        of the transaction dictionaries, for later sequential posting.
        """
        if not self.arb_enabled:
            return []
        
        # get all subscriptions from the order
        subscriptions = self.get_recurring_orderitems()
        
        if len(subscriptions) == 0:
            self.log_extra('No subscription items')
            return []

        settings = self.settings            
        # set up the base dictionary
        trans = {}

        if self.is_live():
            conn = settings.ARB_CONNECTION.value
            self.log_extra('Using live recurring charge connection.')
        else:
            conn = settings.ARB_CONNECTION_TEST.value
            self.log_extra('Using test recurring charge connection.')
        
        shop_config = Config.objects.get_current()
        
        trans['connection'] = conn
        trans['config'] = {
            'merchantID' : settings.LOGIN.value,
            'transactionKey' : settings.TRANKEY.value,
            'shop_name' : shop_config.store_name,
        }
        trans['order'] = self.order
        trans['card'] = self.order.credit_card
        trans['card_expiration'] =  "%4i-%02i" % (self.order.credit_card.expire_year, self.order.credit_card.expire_month)
        
        translist = []
        taxer = get_tax_processor(user = self.order.contact.user)
        
        for subscription in subscriptions:
            product = subscription.product
            subtrans = trans.copy()
            subtrans['subscription'] = subscription
            subtrans['product'] = product
            
            sub = product.subscriptionproduct
            
            trial = sub.get_trial_terms(0)
            if trial:
                price = trunc_decimal(trial.price, 2)
                trial_amount = price
                if price and subscription.product.taxable:
                    trial_amount = taxer.by_price(subscription.product.taxClass, price)
                    #todo, maybe add shipping for trial?
                amount = sub.recurring_price()
                trial_occurrences = trial.occurrences
                if not trial_occurrences:
                    self.log.warn("Trial expiration period is less than one recurring billing cycle. " +
                        "Authorize does not allow this, so the trial period has been adjusted to be equal to one recurring cycle.")
                    trial_occurrences = 1
            else:
                trial_occurrences = 0
                trial_amount = Decimal('0.00')
                amount = subscription.total_with_tax

            occurrences = sub.recurring_times + trial_occurrences
            if occurrences > 9999:
                occurrences = 9999

            subtrans['occurrences'] = occurrences
            subtrans['trial_occurrences'] = trial_occurrences
            subtrans['trial'] = trial
            subtrans['trial_amount'] = trunc_decimal(trial_amount, 2)
            subtrans['amount'] = trunc_decimal(amount, 2)
            if trial:
                charged_today = trial_amount
            else:
                charged_today = amount
            
            charged_today = trunc_decimal(charged_today, 2)
                
            subtrans['charged_today'] = charged_today
            translist.append(subtrans)
            
        return translist
Example #19
0
    def getStandardChargeData(self):
        """Build the dictionary needed to process a credit card charge"""
        order = self.order
        if order.paid_in_full:
            self.log_extra('No standard charges, order is paid in full.')
            return None

        settings = self.settings
        trans = {}
        balance = trunc_decimal(order.balance, 2)
        trans['amount'] = balance

        if self.is_live():
            conn = settings.CONNECTION.value
            self.log_extra('Using live connection.')
        else:
            testflag = 'TRUE'
            conn = settings.CONNECTION_TEST.value
            self.log_extra('Using test connection.')

        if self.settings.SIMULATE.value:
            testflag = 'TRUE'
        else:
            testflag = 'FALSE'

        trans['connection'] = conn

        capture = settings.CAPTURE.value
        trans['authorize_only'] = not capture

        if capture:
            transaction_type = 'AUTH_CAPTURE'
            self.log_extra('Will capture payment.')
        else:
            transaction_type = 'AUTH_ONLY'
            self.log_extra('Authorizing payment, no capture.')

        trans['configuration'] = {
            'x_login': settings.LOGIN.value,
            'x_tran_key': settings.TRANKEY.value,
            'x_version': '3.1',
            'x_relay_response': 'FALSE',
            'x_test_request': testflag,
            'x_delim_data': 'TRUE',
            'x_delim_char': '|',
            'x_type': transaction_type,
            'x_method': 'CC',
        }

        self.log_extra('standard charges configuration: %s',
                       trans['configuration'])

        trans['custBillData'] = {
            'x_first_name': order.contact.first_name,
            'x_last_name': order.contact.last_name,
            'x_address': order.full_bill_street,
            'x_city': order.bill_city,
            'x_state': order.bill_state,
            'x_zip': order.bill_postal_code,
            'x_country': order.bill_country,
            'x_phone': order.contact.primary_phone.phone
        }

        self.log_extra('standard charges configuration: %s',
                       trans['custBillData'])
        balance = trunc_decimal(order.balance, 2)
        trans['amount'] = balance

        trans['transactionData'] = {
            'x_amount': balance,
            'x_card_num': order.credit_card.decryptedCC,
            'x_exp_date': order.credit_card.expirationDate,
            'x_card_code': order.credit_card.ccv,
            'x_invoice_num': order.id
        }

        part1 = urlencode(trans['configuration']) + "&"
        part2 = "&" + urlencode(trans['custBillData'])
        trans['postString'] = part1 + urlencode(
            trans['transactionData']) + part2

        redactedData = {
            'x_amount': balance,
            'x_card_num': order.credit_card.display_cc,
            'x_exp_date': order.credit_card.expirationDate,
            'x_card_code': "REDACTED",
            'x_invoice_num': order.id
        }
        self.log_extra('standard charges transactionData: %s', redactedData)
        trans['logPostString'] = part1 + urlencode(redactedData) + part2

        return trans