def testTruncDecimal(self): """Test trunc_decimal's rounding behavior.""" val = trunc_decimal("0.004", 2) self.assertEqual(val, Decimal("0.00")) val = trunc_decimal("0.005", 2) self.assertEqual(val, Decimal("0.01")) val = trunc_decimal("0.009", 2) self.assertEqual(val, Decimal("0.01"))
def prepare_post(self, data, amount): invoice = "%s" % data.id failct = data.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) try: cc = data.credit_card balance = trunc_decimal(data.balance, 2) self.packet["VendorTxCode"] = invoice 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: self.log.error("preparing data, got error: %s\nData: %s", e, data) self.valid = False return
def prepare_content(self, order, amount): self.bill_to = { 'firstName' : order.bill_first_name, 'lastName' : order.bill_last_name, 'street1': order.full_bill_street, 'city': order.bill_city, 'state' : order.bill_state, 'postalCode' : order.bill_postal_code, 'country': order.bill_country, 'email' : order.contact.email, 'phoneNumber' : order.contact.primary_phone, # Can add additional info here if you want to but it's not required } exp = order.credit_card.expirationDate.split('/') self.card = { 'accountNumber' : order.credit_card.decryptedCC, 'expirationMonth' : exp[0], 'expirationYear' : exp[1], 'cvNumber' : order.credit_card.ccv } currency = self.settings.CURRENCY_CODE.value currency = currency.replace("_", "") self.purchase_totals = { 'currency' : currency, 'grandTotalAmount' : trunc_decimal(amount, 2), }
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('LANGUAGE','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
def remaining(self): payments = [p.amount for p in self.order.payments.all()] if payments: amount = reduce(operator.add, payments) else: amount = Decimal('0.00') remaining = self.order.total - amount if remaining > self.amount: remaining = self.amount return trunc_decimal(remaining, 2)
def get_prior_auth_data(self, authorization, amount=None): """Build the dictionary needed to process a prior auth capture.""" settings = self.settings trans = {'authorization' : authorization} remaining = authorization.remaining() if amount is None or amount > remaining: amount = remaining balance = trunc_decimal(amount, 2) trans['amount'] = amount 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 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': 'PRIOR_AUTH_CAPTURE', 'x_trans_id' : authorization.transaction_id } self.log_extra('prior auth configuration: %s', trans['configuration']) trans['transactionData'] = { 'x_amount' : balance, } part1 = urlencode(trans['configuration']) postdata = part1 + "&" + urlencode(trans['transactionData']) trans['postString'] = postdata self.log_extra('prior auth poststring: %s', postdata) trans['logPostString'] = postdata return trans
def get_prior_auth_data(self, authorization, amount=NOTSET): """Build the dictionary needed to process a prior auth capture.""" settings = self.settings trans = {'authorization' : authorization} remaining = authorization.remaining() if amount == NOTSET or amount > remaining: amount = remaining balance = trunc_decimal(amount, 2) trans['amount'] = amount 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 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': 'PRIOR_AUTH_CAPTURE', 'x_trans_id' : authorization.transaction_id } self.log_extra('prior auth configuration: %s', trans['configuration']) trans['transactionData'] = { 'x_amount' : balance, } part1 = urlencode(trans['configuration']) postdata = part1 + "&" + urlencode(trans['transactionData']) trans['postString'] = postdata self.log_extra('prior auth poststring: %s', postdata) trans['logPostString'] = postdata return trans
def prepare_data(self, order): from satchmo_utils.numbers import trunc_decimal #import pdb #pdb.set_trace() self.order = order addrnum = ADDRNUM.search(order.bill_street1) if addrnum is not None: addrnum = addrnum.group("value") self.bill_to = { 'firstName' : order.contact.first_name, 'lastName' : order.contact.last_name, 'street1': order.bill_street1, 'street2': order.bill_street2, 'addrnum': addrnum, 'city': order.bill_city, 'state' : order.bill_state, 'postalCode' : order.bill_postal_code, 'country': order.bill_country, 'email' : order.contact.email, 'phoneNumber' : order.contact.primary_phone, # Can add additional info here if you want to but it's not required } exp = order.credit_card.expirationDate.split('/') self.card = { 'accountNumber' : order.credit_card.decryptedCC, 'expirationMonth' : exp[0], 'expirationYear' : exp[1], 'cvNumber' : order.credit_card.ccv } #currency = self.settings.CURRENCY_CODE.value currency = 'USD' currency = currency.replace("_", "") self.purchase_totals = { 'currency' : currency, 'grandTotalAmount' : "%.02f"%trunc_decimal(order.balance, 2), 'shipping' : "%.02f"%trunc_decimal(order.shipping_sub_total,2), 'tax' : "%.02f"%trunc_decimal(order.tax+order.shipping_tax,2), 'sub_total': "%.02f"%trunc_decimal(order.discounted_sub_total,2), }
def get_prior_auth_data(self, authorization, amount=None): """Build the dictionary needed to process a prior auth capture.""" settings = self.settings trans = {"authorization": authorization} remaining = authorization.remaining() if amount is None or amount > remaining: amount = remaining balance = trunc_decimal(amount, 2) trans["amount"] = amount 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 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": "PRIOR_AUTH_CAPTURE", "x_trans_id": authorization.transaction_id, } self.log_extra("prior auth configuration: %s", trans["configuration"]) trans["transactionData"] = {"x_amount": balance} part1 = urlencode(trans["configuration"]) postdata = part1 + "&" + urlencode(trans["transactionData"]) trans["postString"] = postdata self.log_extra("prior auth poststring: %s", postdata) trans["logPostString"] = postdata return trans
def prepare_post(self, data, amount): invoice = "%s" % data.id failct = data.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) try: cc = data.credit_card balance = trunc_decimal(data.balance, 2) self.packet['VendorTxCode'] = invoice 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 as e: self.log.error('preparing data, got error: %s\nData: %s', e, data) self.valid = False return # handle pesky unicode chars in names for key, value in self.packet.items(): try: value = value.encode('utf-8') self.packet[key] = value except AttributeError: pass self.postString = urlencode(self.packet) self.url = self.connection self.valid = True
def prepare_post(self, data, amount): invoice = "%s" % data.id failct = data.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) try: cc = data.credit_card balance = trunc_decimal(data.balance, 2) self.packet['VendorTxCode'] = invoice 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: self.log.error('preparing data, got error: %s\nData: %s', e, data) self.valid = False return
def prepare_post(self, data, amount): 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: self.log.error('preparing data, got error: %s\nData: %s', e, data) self.valid = False return
def testTruncDecimal(self): """Test trunc_decimal's rounding behavior.""" # val = trunc_decimal("0.004", 2) # self.assertEqual(val, Decimal("0.00")) val = trunc_decimal("0.005", 2) self.assertEqual(val, Decimal("0.01")) val = trunc_decimal("0.009", 2) self.assertEqual(val, Decimal("0.01")) val = trunc_decimal("2E+1", places=2) self.assertEqual(val, Decimal('20.00')) val = trunc_decimal(2.1E+1, places=2) self.assertEqual(val, Decimal('21.00')) val = trunc_decimal(2.1223E+1, places=2) self.assertEqual(val, Decimal('21.23')) val = trunc_decimal("2.1223E+1", places=2) self.assertEqual(val, Decimal('21.23'))
def _balance(self): if self.total is None: self.force_recalculate_total(save=True) return trunc_decimal(self.total-self.balance_paid, 2)
def force_recalculate_total(self, save=True): """Calculates sub_total, taxes and total.""" zero = Decimal("0.0000000000") total_discount = Decimal("0.0000000000") discount = Discount.objects.by_code(self.discount_code) discount.calc(self) discounts = discount.item_discounts itemprices = [] fullprices = [] for lineitem in self.orderitem_set.all(): lid = lineitem.id if lid in discounts: lineitem.discount = discounts[lid] else: lineitem.discount = zero # now double check against other discounts, such as tiered discounts adjustment = get_product_quantity_adjustments(lineitem.product, qty=lineitem.quantity) if adjustment and adjustment.price: baseprice = adjustment.price.price finalprice = adjustment.final_price() #We need to add in any OrderItemDetail price adjustments before we do anything else baseprice += lineitem.get_detail_price() finalprice += lineitem.get_detail_price() if baseprice > finalprice or baseprice != lineitem.unit_price: unitdiscount = (lineitem.discount/lineitem.quantity) + baseprice-finalprice unitdiscount = trunc_decimal(unitdiscount, 2) linediscount = unitdiscount * lineitem.quantity total_discount += linediscount fullydiscounted = (baseprice - unitdiscount) * lineitem.quantity lineitem.unit_price = baseprice lineitem.discount = linediscount lineitem.line_item_price = baseprice * lineitem.quantity log.debug('Adjusting lineitem unit price for %s. Full price=%s, discount=%s. Final price for qty %d is %s', lineitem.product.slug, baseprice, unitdiscount, lineitem.quantity, fullydiscounted) if save: lineitem.save() itemprices.append(lineitem.sub_total) fullprices.append(lineitem.line_item_price) shipprice = Price() shipprice.price = self.shipping_cost shipadjust = PriceAdjustmentCalc(shipprice) if 'Shipping' in discounts: shipadjust += PriceAdjustment('discount', _('Discount'), discounts['Shipping']) signals.satchmo_shipping_price_query.send(self, adjustment=shipadjust) shipdiscount = shipadjust.total_adjustment() self.shipping_discount = shipdiscount total_discount += shipdiscount self.discount = total_discount if itemprices: item_sub_total = reduce(operator.add, itemprices) else: item_sub_total = zero if fullprices: full_sub_total = reduce(operator.add, fullprices) else: full_sub_total = zero self.sub_total = full_sub_total taxProcessor = get_tax_processor(self) totaltax, taxrates = taxProcessor.process() self.tax = totaltax # clear old taxes for taxdetl in self.taxes.all(): taxdetl.delete() for taxdesc, taxamt in taxrates.items(): taxdetl = OrderTaxDetail(order=self, tax=taxamt, description=taxdesc, method=taxProcessor.method) taxdetl.save() log.debug("Order #%i, recalc: sub_total=%s, shipping=%s, discount=%s, tax=%s", self.id, moneyfmt(item_sub_total), moneyfmt(self.shipping_sub_total), moneyfmt(self.discount), moneyfmt(self.tax)) self.total = Decimal(item_sub_total + self.shipping_sub_total + self.tax) if save: self.save()
def get_charge_data(self, amount=None): """ Build the dictionary needed to process a credit card charge. Return: a dictionary with the following key-values: * log_string: the transaction data without the sensible buyer data. Suitable for logs. * credit_card, amount, address, ship_address, customer_info : the payflowpro.classes.* instances to be passed to self.payflow """ order = self.order if amount is None: amount = order.balance balance = trunc_decimal(amount, 2) ret = { 'credit_card': CreditCard( acct=order.credit_card.decryptedCC, expdate="%02d%02d" % (order.credit_card.expire_month, order.credit_card.expire_year % 100), cvv2=order.credit_card.ccv, ), 'amount': Amount(amt=balance,), 'address': Address( street=order.full_bill_street, zip=order.bill_postal_code, city=order.bill_city, state=order.bill_state, country=order.bill_country, ), 'ship_address': ShippingAddress( shiptostreet=order.full_ship_street, shiptocity=order.ship_city, shiptofirstname=order.ship_first_name, shiptolastname=order.ship_last_name, shiptostate=order.ship_state, shiptocountry=order.ship_country, shiptozip=order.ship_postal_code, ), 'customer_info': CustomerInfo( firstname=order.bill_first_name, lastname=order.bill_last_name, ), } redacted_data = ret.copy() redacted_data['credit_card'] = { 'acct': order.credit_card.display_cc, 'expdate': "%d%d" % (order.credit_card.expire_year, order.credit_card.expire_month), 'cvv2': "REDACTED", } dicts = [getattr(d, 'data', d) for d in redacted_data.values()] ret['log_string'] = "\n".join("%s: %s" % (k, v) for d in dicts for k, v in d.items()) return ret
def get_standard_charge_data(self, amount=None, authorize=False): """Build the dictionary needed to process a credit card charge""" order = self.order settings = self.settings trans = {} if amount is None: amount = order.balance balance = trunc_decimal(amount, 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 trans['authorize_only'] = authorize if not authorize: transaction_type = 'AUTH_CAPTURE' else: transaction_type = 'AUTH_ONLY' 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.bill_first_name, 'x_last_name' : order.bill_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_email' : order.contact.email, } if order.contact.primary_phone: trans['custBillData']['x_phone'] = order.contact.primary_phone.phone trans['custShipData'] = { 'x_ship_to_first_name' : order.ship_first_name, 'x_ship_to_last_name' : order.ship_last_name, 'x_ship_to_address' : order.full_ship_street, 'x_ship_to_city' : order.ship_city, 'x_ship_to_state' : order.ship_state, 'x_ship_to_zip' : order.ship_postal_code, 'x_ship_to_country' : order.ship_country, } self.log_extra('standard charges configuration: %s', trans['custBillData']) invoice = "%s" % order.id failct = order.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) if not self.is_live(): # add random test id to this, for testing repeatability invoice = "%s_test_%s_%i" % (invoice, timezone.now().strftime('%m%d%y'), random.randint(1,1000000)) cc = order.credit_card.decryptedCC ccv = order.credit_card.ccv if not self.is_live() and cc == '4222222222222': if ccv == '222': self.log_extra('Setting a bad ccv number to force an error') ccv = '1' else: self.log_extra('Setting a bad credit card number to force an error') cc = '1234' trans['transactionData'] = { 'x_amount' : balance, 'x_card_num' : cc, 'x_exp_date' : order.credit_card.expirationDate, 'x_card_code' : ccv, 'x_invoice_num' : invoice } part1 = urlencode(trans['configuration']) + "&" part2 = "&" + urlencode(trans['custBillData']) part3 = "&" + urlencode(trans['custShipData']) trans['postString'] = part1 + urlencode(trans['transactionData']) + part2 + part3 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' : invoice } self.log_extra('standard charges transactionData: %s', redactedData) trans['logPostString'] = part1 + urlencode(redactedData) + part2 return trans
def get_recurring_charge_data(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
def get_charge_data(self, amount=None): """ Build the dictionary needed to process a credit card charge. Return: a dictionary with the following key-values: * log_string: the transaction data without the sensible buyer data. Suitable for logs. * credit_card, amount, address, ship_address, customer_info : the payflowpro.classes.* instances to be passed to self.payflow """ order = self.order if amount is None: amount = order.balance balance = trunc_decimal(amount, 2) ret = { 'credit_card': CreditCard( acct=order.credit_card.decryptedCC, expdate="%02d%02d" % (order.credit_card.expire_month, order.credit_card.expire_year % 100), cvv2=order.credit_card.ccv, ), 'amount': Amount(amt=balance,), 'address': Address( street=order.full_bill_street, zip=order.bill_postal_code, city=order.bill_city, state=order.bill_state, country=order.bill_country, ), 'ship_address': ShippingAddress( shiptostreet=order.full_ship_street, shiptocity=order.ship_city, shiptofirstname=order.ship_first_name, shiptolastname=order.ship_last_name, shiptostate=order.ship_state, shiptocountry=order.ship_country, shiptozip=order.ship_postal_code, ), 'customer_info': CustomerInfo( firstname=order.contact.first_name, lastname=order.contact.last_name, ), } redacted_data = ret.copy() redacted_data['credit_card'] = { 'acct': order.credit_card.display_cc, 'expdate': "%d%d" % (order.credit_card.expire_year, order.credit_card.expire_month), 'cvv2': "REDACTED", } dicts = [getattr(d, 'data', d) for d in redacted_data.values()] ret['log_string'] = "\n".join("%s: %s" % (k, v) for d in dicts for k, v in d.items()) return ret
def truncate_decimal(val, places=2): return trunc_decimal(val, places)
def get_standard_charge_data(self, amount=None, authorize=False): """Build the dictionary needed to process a credit card charge""" order = self.order settings = self.settings trans = {} if amount is None: amount = order.balance balance = trunc_decimal(amount, 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 trans['authorize_only'] = authorize if not authorize: transaction_type = 'AUTH_CAPTURE' else: transaction_type = 'AUTH_ONLY' 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.bill_first_name, 'x_last_name' : order.bill_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, 'x_email' : order.contact.email, } trans['custShipData'] = { 'x_ship_to_first_name' : order.ship_first_name, 'x_ship_to_last_name' : order.ship_last_name, 'x_ship_to_address' : order.full_ship_street, 'x_ship_to_city' : order.ship_city, 'x_ship_to_state' : order.ship_state, 'x_ship_to_zip' : order.ship_postal_code, 'x_ship_to_country' : order.ship_country, } self.log_extra('standard charges configuration: %s', trans['custBillData']) invoice = "%s" % order.id failct = order.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) if not self.is_live(): # add random test id to this, for testing repeatability invoice = "%s_test_%s_%i" % (invoice, timezone.now().strftime('%m%d%y'), random.randint(1,1000000)) cc = order.credit_card.decryptedCC ccv = order.credit_card.ccv if not self.is_live() and cc == '4222222222222': if ccv == '222': self.log_extra('Setting a bad ccv number to force an error') ccv = '1' else: self.log_extra('Setting a bad credit card number to force an error') cc = '1234' trans['transactionData'] = { 'x_amount' : balance, 'x_card_num' : cc, 'x_exp_date' : order.credit_card.expirationDate, 'x_card_code' : ccv, 'x_invoice_num' : invoice } part1 = urlencode(trans['configuration']) + "&" part2 = "&" + urlencode(trans['custBillData']) part3 = "&" + urlencode(trans['custShipData']) trans['postString'] = part1 + urlencode(trans['transactionData']) + part2 + part3 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' : invoice } self.log_extra('standard charges transactionData: %s', redactedData) trans['logPostString'] = part1 + urlencode(redactedData) + part2 return trans
def get_standard_charge_data(self, amount=NOTSET, authorize=False): """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 = {} if amount == NOTSET: amount = order.balance balance = trunc_decimal(amount, 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 trans['authorize_only'] = authorize if not authorize: transaction_type = 'AUTH_CAPTURE' else: transaction_type = 'AUTH_ONLY' 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, 'x_email' : order.contact.email, } 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
def get_standard_charge_data(self, amount=None, authorize=False): """Build the dictionary needed to process a credit card charge""" order = self.order settings = self.settings trans = {} if amount is None: amount = order.balance balance = trunc_decimal(amount, 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 trans["authorize_only"] = authorize if not authorize: transaction_type = "AUTH_CAPTURE" else: transaction_type = "AUTH_ONLY" 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.bill_first_name, "x_last_name": order.bill_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, "x_email": order.contact.email, } trans["custShipData"] = { "x_ship_to_first_name": order.ship_first_name, "x_ship_to_last_name": order.ship_last_name, "x_ship_to_address": order.full_ship_street, "x_ship_to_city": order.ship_city, "x_ship_to_state": order.ship_state, "x_ship_to_zip": order.ship_postal_code, "x_ship_to_country": order.ship_country, } self.log_extra("standard charges configuration: %s", trans["custBillData"]) invoice = "%s" % order.id failct = order.paymentfailures.count() if failct > 0: invoice = "%s_%i" % (invoice, failct) if not self.is_live(): # add random test id to this, for testing repeatability invoice = "%s_test_%s_%i" % (invoice, timezone.now().strftime("%m%d%y"), random.randint(1, 1000000)) cc = order.credit_card.decryptedCC ccv = order.credit_card.ccv if not self.is_live() and cc == "4222222222222": if ccv == "222": self.log_extra("Setting a bad ccv number to force an error") ccv = "1" else: self.log_extra("Setting a bad credit card number to force an error") cc = "1234" trans["transactionData"] = { "x_amount": balance, "x_card_num": cc, "x_exp_date": order.credit_card.expirationDate, "x_card_code": ccv, "x_invoice_num": invoice, } part1 = urlencode(trans["configuration"]) + "&" part2 = "&" + urlencode(trans["custBillData"]) part3 = "&" + urlencode(trans["custShipData"]) trans["postString"] = part1 + urlencode(trans["transactionData"]) + part2 + part3 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": invoice, } self.log_extra("standard charges transactionData: %s", redactedData) trans["logPostString"] = part1 + urlencode(redactedData) + part2 return trans