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
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
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})
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
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)
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})
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)
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)
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
def truncate_decimal(val, places=2): return trunc_decimal(val, places)
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
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
def test_equal_to_half_rounds_up(self): self.assertEqual(trunc_decimal("0.005", 2), Decimal("0.01"))
def test_over_half_rounds_up(self): self.assertEqual(trunc_decimal("0.009", 2), Decimal("0.01"))
def test_under_half_rounds_down(self): self.assertEqual(trunc_decimal("0.004", 2), Decimal("0.00"))
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
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