def shop_billing_update_credit_card(request): from django.conf import settings from store_admin.forms import CreditCardForm from payments.gateways.braintreegw import BraintreeGateway shop = request.shop form = CreditCardForm(request.POST or None) error_message = None if request.method == "POST": if form.is_valid(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) customer_id = shop.billing_info().customer_id cc_cardholder = form.cleaned_data['card_holder_name'] cc_number = form.cleaned_data['card_number'] cc_expiration_date = form.cleaned_data['expiration_date'] cc_security_number = form.cleaned_data['security_number'] result = gw.new_customer_credit_card(customer_id, cc_cardholder, cc_number, cc_expiration_date, cc_security_number) if result.is_success: request.flash['message'] = "Your credit card information was successfully updated!" request.flash['severity'] = "success" return HttpResponseRedirect(reverse("billing_overview")) else: error_message = result.message or "No error message available" params = {'form': form, 'error_message': error_message} return render_to_response('store_admin/account/billing_update_credit_card.html', params, RequestContext(request))
def shop_cancel_subscription(request, shop_id): from subscriptions.models import Subscription shop = get_object_or_404(Shop, pk=shop_id) profile = shop.admin.get_profile() try: subscription = Subscription.objects.filter(owner=profile).get() gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) result = gw.cancel_subscription(subscription.subscription_id) if result.is_success: subscription.status = 'C' subscription.save() subscription_cancelation = SubscriptionCancelation(shop=shop, subscription=subscription) subscription_cancelation.save() request.flash['message'] = _("Subscription Cancelled") request.flash['severity'] = "success" return HttpResponseRedirect(reverse('subscription_overview')) request.flash['message'] = _("Subscription could not be cancelled. %s" % result.message) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_overview')) except Subscription.DoesNotExist: request.flash['message'] = _("Subscription not found!") request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_overview'))
def update_settled_braintree_payments(): today = datetime.datetime.today() yesterday = datetime.datetime.today() - datetime.timedelta(1) #today = datetime.datetime(2010, 8, 25) gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) transactions = gw.get_daily_transactions(yesterday) logging.info("%s transactions were found yesterday %s" % (len(transactions), yesterday)) for transaction in transactions: if gw.is_settled(transaction.id): logging.info("Transaction ID=%s was SETTLED! Updating the associated sell instance..." % transaction.id) try: btx = BrainTreeTransaction.objects.filter(transaction_id=transaction.id).get() if btx.sell.payment.state_actual.state != "PA": btx.sell.payment.pay() logging.info("%s was marked as paid..." % btx.sell) else: logging.info("%s was already marked as paid, nothing to do..." % btx.sell) except BrainTreeTransaction.DoesNotExist: logging.critical("Transaction ID=%s is not associated to any Sell!!" % transaction.id) elif gw.is_submitted_for_settlement(transaction.id): logging.info("Transaction ID=%s is SUBMITTED_FOR_SETTLEMENT yet! Nothing to do, wait to status change to SETTLED" % transaction.id) logging.info("Check how long is in this situation... do something if several days have passed") elif gw.is_authorized(transaction.id): logging.info("Transaction ID=%s is AUTHORIZED! This should not be never happend because we programatically set the transaction to be submitted_for_settlement" % transaction.id) else: logging.info("Transaction ID=%s has status = %s" % (transaction.id, transaction.status)) try: btx = BrainTreeTransaction.objects.filter(transaction_id=transaction.id).get() btx.sell.payment.pay() except BrainTreeTransaction.DoesNotExist: logging.critical("Transaction ID=%s is not associated to any Sell!!" % transaction.id)
def send_daily_transactions_notifications(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) today = datetime.datetime.today() transactions = gw.get_transactions(today) try: msg = "This a daily transaction summary [%s]\n" % today msg = msg + "====================================================" for key in transactions.iterkeys(): total = 0 t_list = transactions[key] msg += "\n" + "[%s] transactions (with status %s) were found" % (len(t_list), key) + "\n\n" for transaction in t_list: msg += "\t transaction_id : %s\n" % transaction.id msg += "\t type : %s\n" % transaction.type msg += "\t amount : u$s %s\n" % transaction.amount msg += "\t subscription_id : %s\n" % transaction.subscription_id for key in transaction.customer.keys(): val = transaction.customer[key] if val: msg += "\t customer_%s : %s\n" % (key, transaction.customer[key]) total += decimal.Decimal(transaction.amount) msg += "\t - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n" msg += "\nTOTAL : u$s %s\n" % total msg += "===============================================================\n" send_mail('Daily Transaction Statuses', msg, '*****@*****.**', [b for (a,b) in settings.ADMINS], fail_silently=True) logging.debug(msg) except Exception, e: send_mail('Error when trying to get daily transaction statuses', e , '*****@*****.**', [b for (a,b) in settings.ADMINS], fail_silently=True)
def shop_billing_update_credit_card(request): from django.conf import settings from store_admin.forms import CreditCardForm from payments.gateways.braintreegw import BraintreeGateway shop = request.shop form = CreditCardForm(request.POST or None) error_message = None if request.method == "POST": if form.is_valid(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) customer_id = shop.billing_info().customer_id cc_cardholder = form.cleaned_data['card_holder_name'] cc_number = form.cleaned_data['card_number'] cc_expiration_date = form.cleaned_data['expiration_date'] cc_security_number = form.cleaned_data['security_number'] result = gw.new_customer_credit_card(customer_id, cc_cardholder, cc_number, cc_expiration_date, cc_security_number) if result.is_success: request.flash[ 'message'] = "Your credit card information was successfully updated!" request.flash['severity'] = "success" return HttpResponseRedirect(reverse("billing_overview")) else: error_message = result.message or "No error message available" params = {'form': form, 'error_message': error_message} return render_to_response( 'store_admin/account/billing_update_credit_card.html', params, RequestContext(request))
def change_subscription_plan(request, plan_id): plan_id = long(plan_id) shop = request.shop new_plan = get_object_or_404(SubscriptionPlan, pk=plan_id) logging.debug("New Plan >> %s" % new_plan) shop_subscription = Subscription.objects.filter(owner=shop.admin.get_profile()).get() logging.debug("Current Plan >> %s" % shop_subscription.plan) if shop_subscription.plan.id != plan_id: gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) result = gw.change_subscription(shop_subscription.subscription_id, new_plan.plan_id) if result.is_success: shop_subscription.plan = new_plan shop_subscription.save() request.flash['message'] = _("Congratulations!! You have successfully changed your subscription plan to %s!" % new_plan.name) request.flash['severity'] = "success" return HttpResponseRedirect(reverse('subscription_plans')) else: logging.error(result.message) request.flash['message'] = _("There was an error when trying to upgrade/downgrade your subscription plan!") request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_plans')) else: request.flash['message'] = _("You are already subscribed to this plan!") request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_plans'))
def shop_cancel_subscription(request, shop_id): from subscriptions.models import Subscription shop = get_object_or_404(Shop, pk=shop_id) profile = shop.admin.get_profile() try: subscription = Subscription.objects.filter(owner=profile).get() gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) result = gw.cancel_subscription(subscription.subscription_id) if result.is_success: subscription.status = 'C' subscription.save() subscription_cancelation = SubscriptionCancelation( shop=shop, subscription=subscription) subscription_cancelation.save() request.flash['message'] = _("Subscription Cancelled") request.flash['severity'] = "success" return HttpResponseRedirect(reverse('subscription_overview')) request.flash['message'] = _( "Subscription could not be cancelled. %s" % result.message) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_overview')) except Subscription.DoesNotExist: request.flash['message'] = _("Subscription not found!") request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_overview'))
def send_daily_invoice_notification(): today = datetime.datetime.today() #today = datetime.datetime(2010, 7, 15) gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) transactions = gw.get_daily_transactions(today) logging.info("%s transactions were found today %s" % (len(transactions), today)) for transaction in transactions: if transaction.subscription_id is not None: invoice = Invoice() invoice.cc_mask = '*'*12 + transaction.credit_card_details.masked_number[12:] invoice.cc_type = transaction.credit_card_details.card_type invoice.charge = decimal.Decimal(transaction.amount) invoice.currency = transaction.currency_iso_code invoice.transaction_status_response = transaction.processor_response_text invoice.transaction_type = transaction.type.lower() invoice.transaction_id = transaction.id invoice.customer_name = "%s %s" % (transaction.customer_details.first_name, transaction.customer_details.last_name) invoice.customer_email = transaction.customer_details.email invoice.customer_id = transaction.customer_details.id invoice.shop_dns = "<Unspecified Shop>" if transaction.customer_details.website is None else transaction.customer_details.website try: shop_id = None if transaction.vault_customer.custom_fields is '' else transaction.vault_customer.custom_fields.get("shop_id", None) if shop_id is not None: try: shop = Shop.objects.get(id=shop_id) invoice.shop = shop invoice.market_place = shop.marketplace.name except Shop.DoesNotExist: logging.error("Shop ID = %s not exist for user %s" % (shop_id, invoice.customer_name)) pass else: logging.error("User %s has not setted shop_id property in braintree" % invoice.customer_name) except Exception, e: logging.error(e) pass invoice.subscription_id = transaction.subscription_id subscription = gw.get_subscription_details(invoice.subscription_id) invoice.plan_id = subscription.plan_id invoice.valid_from = subscription.billing_period_start_date invoice.valid_up_to = subscription.billing_period_end_date invoice.next_billing_date = subscription.next_billing_date invoice.save() msg = invoice.to_text() logging.info("Sending email to %s. tx=%s, charge=%s, " % (invoice.customer_name, invoice.transaction_id, invoice.charge)) mail = EmailMessage(subject='%s | Notification Invoice' % invoice.market_place, body=msg, from_email=settings.EMAIL_FROM, to=[invoice.customer_email]+[mail for name, mail in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Notification Invoice\"}'}) mail.send(fail_silently=True)
def extra_data(self): """ This function uses the gateway to get additional information stored in braintree servers Subscription object --------------------- add_ons balance billing_day_of_month billing_period_end_date billing_period_start_date price cancel create create_signature days_past_due discounts trial_duration failure_count find first_billing_date gateway id merchant_account_id number_of_billing_cycles next_billing_date paid_through_date payment_method_token plan_id price status retryCharge transactions trial_duration_unit trial_period trial_duration update_signature verify_keys @return: [billing_period_start_date, billing_period_end_date, next_billing_date, price, transactions] """ from django.conf import settings from payments.gateways.braintreegw import BraintreeGateway gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) subscription = gw.get_subscription_details(self.subscription_id) return [ subscription.billing_period_start_date, #0 subscription.billing_period_end_date, #1 subscription.next_billing_date, #2 subscription.price, #3 subscription.transactions, #4 subscription.status, #5 subscription.balance, #6 subscription.payment_method_token, #7 subscription.transactions, #8 ]
def update_customer_id(self): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) try: subscription_id = self.shop.subscription().subscription_id except: logging.critical("Could not update Customer ID for shop %s" % self.shop) return subs = gw.get_subscription_details(subscription_id) cid = subs.transactions[0].customer_details.id self.customer_id = cid self.save() logging.critical("Billing info Customer ID for shop %s updated" % self.shop)
def send_daily_transactions_notifications(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) today = datetime.datetime.today() transactions = gw.get_transactions(today) try: msg = "This a daily transaction summary [%s]\n" % today msg = msg + "====================================================" for key in transactions.iterkeys(): total = 0 t_list = transactions[key] msg += "\n" + "[%s] transactions (with status %s) were found" % ( len(t_list), key) + "\n\n" for transaction in t_list: msg += "\t transaction_id : %s\n" % transaction.id msg += "\t type : %s\n" % transaction.type msg += "\t amount : u$s %s\n" % transaction.amount msg += "\t subscription_id : %s\n" % transaction.subscription_id for key in transaction.customer.keys(): val = transaction.customer[key] if val: msg += "\t customer_%s : %s\n" % ( key, transaction.customer[key]) total += decimal.Decimal(transaction.amount) msg += "\t - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n" msg += "\nTOTAL : u$s %s\n" % total msg += "===============================================================\n" mail = EmailMessage( subject='Daily Transaction Statuses', body=msg, from_email=settings.EMAIL_FROM, to=[mail for (name, mail) in settings.STAFF], headers={ 'X-SMTPAPI': '{\"category\": \"Daily Transaction Statuses\"}' }) mail.send(fail_silently=True) # send_mail('Daily Transaction Statuses', msg, settings.EMAIL_FROM, [mail for (name, mail) in settings.STAFF], fail_silently=True) logging.debug(msg) except Exception, e: mail = EmailMessage( subject='Error when trying to get daily transaction statuses', body=e, from_email=settings.EMAIL_FROM, to=[mail for (name, mail) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Error\"}'}) mail.send(fail_silently=True)
def credit_card(self): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) customer = None cc_bean = {} try: customer = gw.get_customer_details(self.customer_id) cc = customer.credit_cards[0] cc_bean['card_type'] = cc.card_type cc_bean['expiration_date'] = cc.expiration_date cc_bean['masked_number'] = "************" + cc.masked_number[12:] cc_bean['expired'] = cc.is_expired cc_bean['token'] = cc.token except Exception, e: logging.critical(e)
def get_daily_transactions_data(day): from payments.gateways.braintreegw import BraintreeGateway from django.conf import settings gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) params = {} try: transactions = gw.get_transactions(day) params['day'] = day params['columns'] = [ "TransactionID", "Amount", "Website", "Email", "User" ] sections = [] for status in transactions.iterkeys(): section = {} section['type'] = status t_list = transactions[status] section['len'] = len(t_list) section['txs'] = [] total = 0 for transaction in t_list: user_name = "- Unknown -" if transaction.customer_details.first_name is None or transaction.customer_details.last_name is None else "%s, %s" % ( transaction.customer_details.last_name, transaction.customer_details.first_name) tx = [ transaction.id, "u$s %s" % round(decimal.Decimal(transaction.amount), 2), transaction.customer_details.website, transaction.customer_details.email, user_name ] total += decimal.Decimal(transaction.amount) section['txs'].append(tx) section['total'] = total sections.append(section) params['sections'] = sections except Exception, e: logging.info(e)
def send_past_due_notification(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) past_due_days = 2 subscriptions = gw.get_past_due_subscriptions(past_due_days) logging.info("%s subscriptions were found with status past due" % len(subscriptions)) for subscription in subscriptions: try: local_subscription = Subscription.objects.filter(subscription_id=subscription.id).get() #Send email to Site Admin msg = "We have found that Subscription (id=%s, plan=%s) for shop %s is past due. An email to shop owner will be sent to inform about this situation" % (local_subscription.subscription_id, local_subscription.plan.name ,local_subscription.owner.shop) logging.info(msg) mail = EmailMessage(subject='Past due Subscription', body=msg, from_email=settings.EMAIL_FROM, to=[b for (a,b) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Past Due Subscription\"}'}) mail.send(fail_silently=True) # send_mail('Past due Subscription', msg, settings.EMAIL_FROM, [b for (a,b) in settings.STAFF], fail_silently=True) #Send email to shop owner msg = "We notice you that your subscription (%s) for shop %s is %s days past due." % (local_subscription.plan.name ,local_subscription.owner.shop, past_due_days) mail = EmailMessage(subject='Past due Subscription', body=msg, from_email=settings.EMAIL_FROM, to=[local_subscription.owner.user.email], headers={'X-SMTPAPI': '{\"category\": \"Past Due Subscription\"}'}) mail.send(fail_silently=True) # send_mail('Past due Suscription', msg, settings.EMAIL_FROM, [local_subscription.owner.user.email], fail_silently=True) except Subscription.DoesNotExist: error_msg = "Subscription<id%s> was not found. A past due subscription was found in braintree, but this subscription do not correspond with any in the system" % subscription.id logging.error(error_msg) mail = EmailMessage(subject='Subscription not found', body=error_msg, from_email=settings.EMAIL_FROM, to=[b for (a,b) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Error\"}'}) mail.send(fail_silently=True) # send_mail('Subscription not found', error_msg , settings.EMAIL_FROM, [b for (a,b) in settings.STAFF], fail_silently=True) except Exception, e: mail = EmailMessage(subject='Error when trying to check past due subscriptions', body=e, from_email=settings.EMAIL_FROM, to=[b for (a,b) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Error\"}'}) mail.send(fail_silently=True)
def send_daily_transactions_notifications(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) today = datetime.datetime.today() transactions = gw.get_transactions(today) try: msg = "This a daily transaction summary [%s]\n" % today msg = msg + "====================================================" for key in transactions.iterkeys(): total = 0 t_list = transactions[key] msg += "\n" + "[%s] transactions (with status %s) were found" % (len(t_list), key) + "\n\n" for transaction in t_list: msg += "\t transaction_id : %s\n" % transaction.id msg += "\t type : %s\n" % transaction.type msg += "\t amount : u$s %s\n" % transaction.amount msg += "\t subscription_id : %s\n" % transaction.subscription_id for key in transaction.customer.keys(): val = transaction.customer[key] if val: msg += "\t customer_%s : %s\n" % (key, transaction.customer[key]) total += decimal.Decimal(transaction.amount) msg += "\t - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n" msg += "\nTOTAL : u$s %s\n" % total msg += "===============================================================\n" mail = EmailMessage(subject='Daily Transaction Statuses', body=msg, from_email=settings.EMAIL_FROM, to=[mail for (name, mail) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Daily Transaction Statuses\"}'}) mail.send(fail_silently=True) # send_mail('Daily Transaction Statuses', msg, settings.EMAIL_FROM, [mail for (name, mail) in settings.STAFF], fail_silently=True) logging.debug(msg) except Exception, e: mail = EmailMessage(subject='Error when trying to get daily transaction statuses', body=e, from_email=settings.EMAIL_FROM, to=[mail for (name, mail) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Error\"}'}) mail.send(fail_silently=True)
def send_past_due_notification(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) past_due_days = 2 subscriptions = gw.get_past_due_subscriptions(past_due_days) logging.info("%s subscriptions were found with status past due" % len(subscriptions)) for subscription in subscriptions: try: local_subscription = Subscription.objects.filter(subscription_id=subscription.id).get() #Send email to Site Admin msg = "We have found that Subscription (id=%s, plan=%s) for shop %s is past due. An email to shop owner will be sent to inform about this situation" % (local_subscription.subscription_id, local_subscription.plan.name ,local_subscription.owner.shop) logging.info(msg) send_mail('Past due Subscription', msg, '*****@*****.**', [b for (a,b) in settings.ADMINS], fail_silently=True) #Send email to shop owner msg = "We notice you that your subscription (%s) for shop %s is %s days past due." % (local_subscription.plan.name ,local_subscription.owner.shop, past_due_days) send_mail('Past due Suscription', msg, '*****@*****.**', [local_subscription.owner.user.email], fail_silently=True) except Subscription.DoesNotExist: error_msg = "Subscription<id%s> was not found. A past due subscription was found in braintree, but this subscription do not correspond with any in the system" % subscription.id logging.error(error_msg) send_mail('Subscription not found', error_msg , '*****@*****.**', [b for (a,b) in settings.ADMINS], fail_silently=True) except Exception, e: send_mail('Error when trying to check past due subscriptions', e , '*****@*****.**', [b for (a,b) in settings.ADMINS], fail_silently=True)
def get_daily_transactions_data(day): from payments.gateways.braintreegw import BraintreeGateway from django.conf import settings gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) params = {} try: transactions = gw.get_transactions(day) params['day'] = day params['columns'] = ["TransactionID", "Amount", "Website", "Email", "User"] sections = [] for status in transactions.iterkeys(): section = {} section['type'] = status t_list = transactions[status] section['len'] = len(t_list) section['txs'] = [] total = 0 for transaction in t_list: user_name = "- Unknown -" if transaction.customer_details.first_name is None or transaction.customer_details.last_name is None else "%s, %s" % (transaction.customer_details.last_name, transaction.customer_details.first_name) tx = [transaction.id, "u$s %s" % round(decimal.Decimal(transaction.amount), 2), transaction.customer_details.website, transaction.customer_details.email, user_name] total += decimal.Decimal(transaction.amount) section['txs'].append(tx) section['total'] = total sections.append(section) params['sections'] = sections except Exception, e: logging.info(e)
def change_subscription_plan(request, plan_id): plan_id = long(plan_id) shop = request.shop new_plan = get_object_or_404(SubscriptionPlan, pk=plan_id) logging.debug("New Plan >> %s" % new_plan) shop_subscription = Subscription.objects.filter( owner=shop.admin.get_profile()).get() logging.debug("Current Plan >> %s" % shop_subscription.plan) if shop_subscription.plan.id != plan_id: gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) result = gw.change_subscription(shop_subscription.subscription_id, new_plan.plan_id) if result.is_success: shop_subscription.plan = new_plan shop_subscription.save() request.flash['message'] = _( "Congratulations!! You have successfully changed your subscription plan to %s!" % new_plan.name) request.flash['severity'] = "success" return HttpResponseRedirect(reverse('subscription_plans')) else: logging.error(result.message) request.flash['message'] = _( "There was an error when trying to upgrade/downgrade your subscription plan!" ) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_plans')) else: request.flash['message'] = _( "You are already subscribed to this plan!") request.flash['severity'] = "error" return HttpResponseRedirect(reverse('subscription_plans'))
def update_settled_braintree_payments(): today = datetime.datetime.today() yesterday = datetime.datetime.today() - datetime.timedelta(1) #today = datetime.datetime(2010, 8, 25) gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) transactions = gw.get_daily_transactions(yesterday) logging.info("%s transactions were found yesterday %s" % (len(transactions), yesterday)) for transaction in transactions: if gw.is_settled(transaction.id): logging.info( "Transaction ID=%s was SETTLED! Updating the associated sell instance..." % transaction.id) try: btx = BrainTreeTransaction.objects.filter( transaction_id=transaction.id).get() if btx.sell.payment.state_actual.state != "PA": btx.sell.payment.pay() logging.info("%s was marked as paid..." % btx.sell) else: logging.info( "%s was already marked as paid, nothing to do..." % btx.sell) except BrainTreeTransaction.DoesNotExist: logging.critical( "Transaction ID=%s is not associated to any Sell!!" % transaction.id) elif gw.is_submitted_for_settlement(transaction.id): logging.info( "Transaction ID=%s is SUBMITTED_FOR_SETTLEMENT yet! Nothing to do, wait to status change to SETTLED" % transaction.id) logging.info( "Check how long is in this situation... do something if several days have passed" ) elif gw.is_authorized(transaction.id): logging.info( "Transaction ID=%s is AUTHORIZED! This should not be never happend because we programatically set the transaction to be submitted_for_settlement" % transaction.id) else: logging.info("Transaction ID=%s has status = %s" % (transaction.id, transaction.status)) try: btx = BrainTreeTransaction.objects.filter( transaction_id=transaction.id).get() btx.sell.payment.pay() except BrainTreeTransaction.DoesNotExist: logging.critical( "Transaction ID=%s is not associated to any Sell!!" % transaction.id)
def refund(self): if self.payment.state_actual.state == 'PA': if self.is_manual_payment(): pass if self.is_paypal_payment(): from payments.gateways.paypal import PayPalGateway from payments.models import PayPalShopSettings, PayPalTransaction paypal_gw = PayPalGateway(username=settings.PAYPAL_USERNAME, password=settings.PAYPAL_PASSWORD, sign=settings.PAYPAL_SIGNATURE, debug=settings.PAYPAL_DEBUG) try: txn = PayPalTransaction.objects.filter(sell=self).get() paypal_gw.RefundTransaction(txn.transaction_id, 'Full', 'USD', self.total, "Programatic refund from shop admin") except PayPalTransaction.DoesNotExist: raise SellError("PayPalTransaction not found. Refund can't be performed...") if self.is_google_checkout(): from payments.gateways.googlecheckout import GoogleCheckoutGateway, GoogleCheckoutOrder from payments.models import GoogleCheckoutShopSettings try: google_settings = GoogleCheckoutShopSettings.objects.filter(shop = self.shop).get() except GoogleCheckoutShopSettings.DoesNotExist: raise SellError("Google Checkout Settings are disabled! Refund can't be performed") googlecheckout_gw = GoogleCheckoutGateway(google_settings.merchant_id, google_settings.merchant_key, debug=True) try: order = GoogleCheckoutOrder.objects.filter(sell=self).get() refund = googlecheckout_gw.refund_order(order.order_number, self.total, "Programatic refund from shop admin") except GoogleCheckoutOrder.DoesNotExist: raise SellError("This sell it's not associated to any GoogleCheckoutOrder! Refund can't be performed") if self.is_braintree(): from payments.gateways.braintreegw import BraintreeGateway from payments.models import BrainTreeTransaction try: bt_txn = BrainTreeTransaction.objects.filter(sell=self).get() except BrainTreeTransaction.DoesNotExist: raise SellError('There is no Braintree transaction associated to this sell!') gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) refund = gw.refund_transaction(bt_txn.transaction_id) if not refund.is_success: message = "" if refund.transaction: code = refund.transaction.processor_response_code text = refund.transaction.processor_response_text message = "Refund Failed! %s.\[%s] %s" % (refund.message, code, text) else: for error in refund.errors.deep_errors: txt = "attribute: %s, code: %s. %s" (error.attribute, error.code, error.message) message += txt + "\n" raise SellError("Can't do refund. %s" % message) for item in self.sellitem_set.all(): item.product.increase_qty(item.qty) item.product.activate() item.save() self.cancel = True self.save() self.payment.refunded() else: raise SellError('Can not refund this sell, your state is not paid.')
def clean(self): init_user = self.initial['user'] cleaned_data = self.cleaned_data # try: # a = self.initial.get("result") # logging.critical(a) # return cleaned_data # except Exception: # pass # # logging.critical("Trying to validate credit cards") if cleaned_data.has_key('cc_expiration_year') and cleaned_data.has_key( 'cc_expiration_month'): date_str = "%s-%s" % (cleaned_data['cc_expiration_year'], cleaned_data['cc_expiration_month']) card_expire = datetime.datetime.strptime(date_str, "%Y-%m") if card_expire < datetime.datetime.now(): msg = u"Card expired." self._errors["cc_expiration_year"] = self.error_class([msg]) self._errors["cc_expiration_month"] = self.error_class([msg]) # These fields are no longer valid. Remove them from the # cleaned data. del cleaned_data["cc_expiration_year"] del cleaned_data["cc_expiration_month"] bt_gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) first_name = init_user.first_name last_name = init_user.first_name email = init_user.email cc_number = cleaned_data.get("cc_number", None) if cc_number is None: self._errors["cc_number"] = self.error_class( ["This field is required!"]) month = cleaned_data.get("cc_expiration_month", None) year = cleaned_data.get("cc_expiration_year", None) if month is None or year is None: raise forms.ValidationError(_("Expiration date invalid format.")) cc_expiration_date = "%s/%s" % (month, year) cc_security_number = cleaned_data.get("card_security_number", None) if cc_security_number is None: self._errors["card_security_number"] = self.error_class( ["This field is required!"]) reuse_address = cleaned_data.get("shop_address", None) if reuse_address == False: #Take data filled by user in the form street = cleaned_data.get("billing_street", None) if street is None or street == u'': self._errors["billing_street"] = self.error_class( ["This field is required!"]) city = cleaned_data.get("billing_city", None) if city is None or city == u'': self._errors["billing_city"] = self.error_class( ["This field is required!"]) state = cleaned_data.get("billing_state", None) if state is None or state == u'': self._errors["billing_state"] = self.error_class( ["This field is required!"]) zip = cleaned_data.get("billing_zip", None) if zip is None or zip == u'': self._errors["billing_zip"] = self.error_class( ["This field is required!"]) else: #Use data filled on first step street = self.initial['street'] zip = self.initial['zip'] state = self.initial['state'] city = self.initial['city'] shop_name = "thisisafake.shop.com" shop_id = "-1" result = bt_gw.create_customer(first_name, last_name, email, cc_number, cc_expiration_date, cc_security_number, street, city, state, zip, shop_name, shop_id) if result.is_success: self.result = result self.initial["result"] = result else: raise forms.ValidationError(_(result.message)) return cleaned_data
def checkout_confirm(request): from payments.gateways.googlecheckout import GoogleCheckoutGateway from payments.gateways.paypal import PayPalGateway from payments.gateways.braintreegw import BraintreeGateway from payments.models import GoogleCheckoutShopSettings, PayPalShopSettings, ManualPaymentShopSettings, BraintreeShopSettings #A list of payment method, each payment method know how to render as a link #payment_methods = request.shop.get_payment_methods() payment_buttons = [] #profile = request.user.get_profile() cart = request.cart shop = request.shop if not cart.is_available(): request.flash['message'] = 'Items not longer available: ' for item in cart.items_not_availables(): request.flash['message'] += item.product.title cart.remove_not_available_items() return HttpResponseRedirect(reverse('my_shopping')) try: google_settings = GoogleCheckoutShopSettings.objects.filter( shop=shop).get() googlecheckout_gw = GoogleCheckoutGateway(google_settings.merchant_id, google_settings.merchant_key, debug=True) button = googlecheckout_gw.render_button(cart) payment_buttons.append(button) except GoogleCheckoutShopSettings.DoesNotExist: pass try: braintree_settings = BraintreeShopSettings.objects.filter( shop=shop).get() braintree_gw = BraintreeGateway( braintree_settings.merchant_id, braintree_settings.public_key, braintree_settings.private_key, ) button = braintree_gw.render_button(cart, request) payment_buttons.append(button) except BraintreeShopSettings.DoesNotExist: pass try: paypal_settings = PayPalShopSettings.objects.filter(shop=shop).get() paypal_gw = PayPalGateway(username=settings.PAYPAL_USERNAME, password=settings.PAYPAL_PASSWORD, sign=settings.PAYPAL_SIGNATURE, debug=settings.PAYPAL_DEBUG) button = paypal_gw.render_button() payment_buttons.append(button) except PayPalShopSettings.DoesNotExist: pass try: manual_payment_settings = ManualPaymentShopSettings.objects.filter( shop=shop) url = reverse("myshopping_checkout_manual_payment") if manual_payment_settings.count(): button = """ <div> <h3>Manual Payments</h3>\n <form name='manual_payment' action='%s' method='POST'>\n """ % url for idx, payment in enumerate(manual_payment_settings): input = '\t<input type="radio" name="manual_payment_id" checked="%d" value="%s"> %s </input><br/>\n' % ( 1 if idx == 0 else 0, payment.id, payment.name) button += input button += "<br/>" button += "<button class='primaryAction small awesome' type='submit'>Submit</button>\n" button += "</form>\n" button += "</div>" logging.debug(button) payment_buttons.append(button) except Exception, e: logging.error(e)
def done(self, request, form_list): user = request.user cleaned_data = {} [cleaned_data.update(form.cleaned_data) for form in form_list] plan_id = cleaned_data['plan_id'].plan_id #Update address profile = user.get_profile() profile.street_address = cleaned_data['street'] profile.city = cleaned_data['city'] profile.state = cleaned_data['state'] profile.zip = cleaned_data['zip'] profile.country = 'United States' profile.save() billing_street = cleaned_data['billing_street'].encode('ascii', 'ignore') billing_city = cleaned_data['billing_city'].encode('ascii', 'ignore') billing_state = cleaned_data['billing_state'].encode('ascii', 'ignore') billing_zip = cleaned_data['billing_zip'].encode('ascii', 'ignore') date_str = "%s-%s" % (cleaned_data['cc_expiration_year'], cleaned_data['cc_expiration_month']) card_expire = datetime.datetime.strptime(date_str, "%Y-%m") """ Create shop """ shop = Shop.objects.create(marketplace=request.marketplace, name=cleaned_data['shop_name'].lower(), admin=user, name_store=cleaned_data['name_store']) """ Braintree subscription """ #Create a new Customer with Financial data in braintree bt_gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) result = (form_list[2]).result if result.is_success: customer_id = result.customer.id update = bt_gw.update_customer_shopname(customer_id, shop.id, shop.default_dns) if update.is_success: token = result.customer.credit_cards[0].token else: transaction.rollback() request.flash['message'] = unicode(_("%s" % update.message)) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('market_sell_signup')) else: transaction.rollback() logging.error(result.errors.errors.data) logging.error(result.message) request.flash['message'] = unicode(_("%s" % result.message)) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('market_sell_signup')) #Create a Subscription in braintree linked to the customer created before result = bt_gw.create_subscription(plan_id, token) if result.is_success: profile = user.get_profile() profile.set_subscription_plan(plan_id, result.subscription.id) else: transaction.rollback() request.flash['message'] = unicode(_("Could not create the subscription. %s.Please contact us.") % result.message) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('market_sell_signup')) #Store billing information billing = ShopBillingInfo( shop = shop, card_ending = cleaned_data['cc_number'][-4:], card_expire = card_expire, street = billing_street, city = billing_city, state = billing_state, zip = billing_zip, ) billing.save() request.flash['message'] = unicode(_("Shop successfully added.")) request.flash['severity'] = "success" return HttpResponseRedirect(reverse('market_sell_welcome', args=[shop.id]))
def done(self, request, form_list): user = request.user cleaned_data = {} [cleaned_data.update(form.cleaned_data) for form in form_list] plan_id = cleaned_data['plan_id'].plan_id #Update address profile = user.get_profile() profile.street_address = cleaned_data['street'] profile.city = cleaned_data['city'] profile.state = cleaned_data['state'] profile.zip = cleaned_data['zip'] profile.country = 'United States' profile.save() if cleaned_data.get('shop_address', False): billing_street = cleaned_data['street'].encode('ascii', 'ignore') billing_city = cleaned_data['city'].encode('ascii', 'ignore') billing_state = cleaned_data['state'].encode('ascii', 'ignore') billing_zip = cleaned_data['zip'].encode('ascii', 'ignore') else: billing_street = cleaned_data['billing_street'].encode( 'ascii', 'ignore') billing_city = cleaned_data['billing_city'].encode( 'ascii', 'ignore') billing_state = cleaned_data['billing_state'].encode( 'ascii', 'ignore') billing_zip = cleaned_data['billing_zip'].encode('ascii', 'ignore') date_str = "%s-%s" % (cleaned_data['cc_expiration_year'], cleaned_data['cc_expiration_month']) #card_expire = datetime.datetime.strptime(date_str, "%Y-%m") """ Create shop """ shop = Shop.objects.create(marketplace=request.marketplace, name=cleaned_data['shop_name'].lower(), admin=user, name_store=cleaned_data['name_store']) """ Braintree subscription """ #Create a new Customer with Financial data in braintree bt_gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) result = (form_list[2]).result customer_id = 'undefined' if result.is_success: customer_id = result.customer.id update = bt_gw.update_customer_shopname(customer_id, shop.id, shop.default_dns) if update.is_success: token = result.customer.credit_cards[0].token else: transaction.rollback() request.flash['message'] = unicode(_("%s" % update.message)) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('market_sell_signup')) else: transaction.rollback() logging.error(result.errors.errors.data) logging.error(result.message) request.flash['message'] = unicode(_("%s" % result.message)) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('market_sell_signup')) #Create a Subscription in braintree linked to the customer created before result = bt_gw.create_subscription(plan_id, token) if result.is_success: profile = user.get_profile() profile.set_subscription_plan(plan_id, result.subscription.id) else: transaction.rollback() request.flash['message'] = unicode( _("Could not create the subscription. %s.Please contact us.") % result.message) request.flash['severity'] = "error" return HttpResponseRedirect(reverse('market_sell_signup')) #Store billing information billing = ShopBillingInfo( shop=shop, #card_ending = cleaned_data['cc_number'][-4:], #card_expire = card_expire, customer_id=customer_id, street=billing_street, city=billing_city, state=billing_state, zip=billing_zip, ) billing.save() request.flash['message'] = unicode(_("Shop successfully added.")) request.flash['severity'] = "success" return HttpResponseRedirect( reverse('market_sell_welcome', args=[shop.id]))
def clean(self): init_user = self.initial['user'] cleaned_data = self.cleaned_data # try: # a = self.initial.get("result") # logging.critical(a) # return cleaned_data # except Exception: # pass # # logging.critical("Trying to validate credit cards") if cleaned_data.has_key('cc_expiration_year') and cleaned_data.has_key('cc_expiration_month'): date_str = "%s-%s" % (cleaned_data['cc_expiration_year'], cleaned_data['cc_expiration_month']) card_expire = datetime.datetime.strptime(date_str, "%Y-%m") if card_expire < datetime.datetime.now(): msg = u"Card expired." self._errors["cc_expiration_year"] = self.error_class([msg]) self._errors["cc_expiration_month"] = self.error_class([msg]) # These fields are no longer valid. Remove them from the # cleaned data. del cleaned_data["cc_expiration_year"] del cleaned_data["cc_expiration_month"] bt_gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) first_name = init_user.first_name last_name = init_user.first_name email = init_user.email cc_number = cleaned_data.get("cc_number", None) if cc_number is None: self._errors["cc_number"] = self.error_class(["This field is required!"]) month = cleaned_data.get("cc_expiration_month", None) year = cleaned_data.get("cc_expiration_year", None) if month is None or year is None: raise forms.ValidationError(_("Expiration date invalid format.")) cc_expiration_date = "%s/%s" % (month, year) cc_security_number = cleaned_data.get("card_security_number", None) if cc_security_number is None: self._errors["card_security_number"] = self.error_class(["This field is required!"]) street = cleaned_data.get("billing_street", None) if street is None: self._errors["billing_street"] = self.error_class(["This field is required!"]) city = cleaned_data.get("billing_city", None) if city is None: self._errors["billing_city"] = self.error_class(["This field is required!"]) state = cleaned_data.get("billing_state", None) if state is None: self._errors["billing_state"] = self.error_class(["This field is required!"]) zip = cleaned_data.get("billing_zip", None) if zip is None: forms.ValidationError(_("")) shop_name = "thisisafake.shop.com" shop_id = "-1" result = bt_gw.create_customer(first_name, last_name, email, cc_number, cc_expiration_date, cc_security_number, street, city, state, zip, shop_name, shop_id) if result.is_success: self.result = result self.initial["result"] = result else: raise forms.ValidationError(_(result.message)) return cleaned_data
def send_daily_invoice_notification(): today = datetime.datetime.today() #today = datetime.datetime(2010, 7, 15) gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) transactions = gw.get_daily_transactions(today) logging.info("%s transactions were found today %s" % (len(transactions), today)) for transaction in transactions: if transaction.subscription_id is not None: invoice = Invoice() invoice.cc_mask = '*' * 12 + transaction.credit_card_details.masked_number[ 12:] invoice.cc_type = transaction.credit_card_details.card_type invoice.charge = decimal.Decimal(transaction.amount) invoice.currency = transaction.currency_iso_code invoice.transaction_status_response = transaction.processor_response_text invoice.transaction_type = transaction.type.lower() invoice.transaction_id = transaction.id invoice.customer_name = "%s %s" % ( transaction.customer_details.first_name, transaction.customer_details.last_name) invoice.customer_email = transaction.customer_details.email invoice.customer_id = transaction.customer_details.id invoice.shop_dns = "<Unspecified Shop>" if transaction.customer_details.website is None else transaction.customer_details.website try: shop_id = None if transaction.vault_customer.custom_fields is '' else transaction.vault_customer.custom_fields.get( "shop_id", None) if shop_id is not None: try: shop = Shop.objects.get(id=shop_id) invoice.shop = shop invoice.market_place = shop.marketplace.name except Shop.DoesNotExist: logging.error("Shop ID = %s not exist for user %s" % (shop_id, invoice.customer_name)) pass else: logging.error( "User %s has not setted shop_id property in braintree" % invoice.customer_name) except Exception, e: logging.error(e) pass invoice.subscription_id = transaction.subscription_id subscription = gw.get_subscription_details(invoice.subscription_id) invoice.plan_id = subscription.plan_id invoice.valid_from = subscription.billing_period_start_date invoice.valid_up_to = subscription.billing_period_end_date invoice.next_billing_date = subscription.next_billing_date invoice.save() msg = invoice.to_text() logging.info("Sending email to %s. tx=%s, charge=%s, " % (invoice.customer_name, invoice.transaction_id, invoice.charge)) mail = EmailMessage(subject='%s | Notification Invoice' % invoice.market_place, body=msg, from_email=settings.EMAIL_FROM, to=[invoice.customer_email] + [mail for name, mail in settings.STAFF], headers={ 'X-SMTPAPI': '{\"category\": \"Notification Invoice\"}' }) mail.send(fail_silently=True)
def ajax_do_charge(request, feature): from payments.gateways.braintreegw import BraintreeGateway from subscriptions.models import FeaturesManager, FeaturePayment from django.conf import settings success = False shop = request.shop gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) #This is token asociated to the subscription, we will use it to charge the feature token = shop.subscription().extra_data()[7] #Try to charge the feature against braintree price = FeaturesManager.get_feature_price(shop, feature) result = gw.charge_purchase(token, price) admin_email = shop.marketplace.contact_email if result.is_success: status = result.transaction.status credit_card = "%s - ***********%s" % ( result.transaction.credit_card[u'card_type'], result.transaction.credit_card[u'last_4']) txn_id = result.transaction.id if status == 'authorized': logging.info("Transaction <id=%s> was successfully authorized!!" % (txn_id)) submit = gw.submit_for_settlement(txn_id) message = None if submit.is_success: message = "Shop: %s\nFeature: %s\nPrice: $ %s\nCredit Card: %s\nTransaction ID: %s\nTransaction Status: %s\n" % ( shop, feature, price, credit_card, txn_id, status) logging.info(message) else: message = "WARNING: Transaction<id=%s> was successfully authorized but could not be submited for settlement. Try it manually via braintree admin site" % txn_id logging.critical(message) mail = EmailMessage( subject="Featured Successfully Purchased!", body= "\nWe have enabled the %s feature in your %s shop.\n\nWe collected $%s from your %s credit card account.\n\nThanks, %s" % (feature, shop, price, credit_card, shop.marketplace), from_email=settings.EMAIL_FROM, to=[shop.admin.email], headers={ 'X-SMTPAPI': '{\"category\": \"Featured Purchased\"}' }) mail.send(fail_silently=True) # send_mail("Featured Successfully Purchased!", "\nWe have enabled the %s feature in your %s shop.\n\nWe collected $%s from your %s credit card account.\n\nThanks, %s" % (feature, shop, price, credit_card, shop.marketplace), settings.EMAIL_FROM, [shop.admin.email], True) mail = EmailMessage( subject="%s purchased the %s feature" % (shop, feature), body=message, from_email=settings.EMAIL_FROM, to=[mail for (name, mail) in settings.STAFF] + [admin_email], headers={ 'X-SMTPAPI': '{\"category\": \"Featured Purchased\"}' }) mail.send(fail_silently=True) # send_mail("%s purchased the %s feature" % (shop, feature), message, settings.EMAIL_FROM, [mail for (name, mail) in settings.STAFF]+[admin_email], True) else: logging.critical( "Transaction<id=%s> status is %s. Can't submit for settlement if status != authorized" % (txn_id, status)) success = True else: success = False if success: payment = FeaturePayment(shop=shop) payment.transaction_id = txn_id payment.price = price payment.feature = feature payment.save() FeaturesManager.set_feature_enabled(shop, feature) resp = {'status': 'success', 'txn_id': txn_id} return HttpResponse(simplejson.dumps(resp), mimetype="application/json") logging.critical("Feature could not be charged :(") for error in result.errors.deep_errors: logging.critical("Gateway Error Found > code=%s, msg=%s" % (error.code, error.message)) message = "" if status == "processor_declined": message = "Reason: Processor declined the transaction<id=%s>. Error code %s - %s" % ( result.transaction.id, result.transaction.processor_response_code, result.transaction.processor_response_text) elif status == "gateway_rejected": message = "Reason: Gateway rejected the transaction<id=%s>. Error on %s" % ( result.transaction.id, result.transaction.gateway_rejection_reason) else: message = "Reason: transaction<id=%s> status is %s!. We have no more info about this status. Please check braintree admin console." % ( status, result.transaction.id) logging.critical(message) mail = EmailMessage( subject="%s tried but failed to purchase the %s feature" % (shop, feature), body=message, from_email=settings.EMAIL_FROM, to=[mail for (name, mail) in settings.STAFF] + [admin_email], headers={'X-SMTPAPI': '{\"category\": \"Error\"}'}) mail.send(fail_silently=True) # send_mail("%s tried but failed to purchase the %s feature" % (shop, feature), message, settings.EMAIL_FROM, [mail for (name, mail) in settings.STAFF]+[admin_email], True) return HttpResponseServerError()
def refund(self): if self.payment.state_actual.state == 'PA': if self.is_manual_payment(): pass if self.is_paypal_payment(): from payments.gateways.paypal import PayPalGateway from payments.models import PayPalShopSettings, PayPalTransaction paypal_gw = PayPalGateway(username=settings.PAYPAL_USERNAME, password=settings.PAYPAL_PASSWORD, sign=settings.PAYPAL_SIGNATURE, debug=settings.PAYPAL_DEBUG) try: txn = PayPalTransaction.objects.filter(sell=self).get() paypal_gw.RefundTransaction( txn.transaction_id, 'Full', 'USD', self.total, "Programatic refund from shop admin") except PayPalTransaction.DoesNotExist: raise SellError( "PayPalTransaction not found. Refund can't be performed..." ) if self.is_google_checkout(): from payments.gateways.googlecheckout import GoogleCheckoutGateway, GoogleCheckoutOrder from payments.models import GoogleCheckoutShopSettings try: google_settings = GoogleCheckoutShopSettings.objects.filter( shop=self.shop).get() except GoogleCheckoutShopSettings.DoesNotExist: raise SellError( "Google Checkout Settings are disabled! Refund can't be performed" ) googlecheckout_gw = GoogleCheckoutGateway( google_settings.merchant_id, google_settings.merchant_key, debug=True) try: order = GoogleCheckoutOrder.objects.filter(sell=self).get() refund = googlecheckout_gw.refund_order( order.order_number, self.total, "Programatic refund from shop admin") except GoogleCheckoutOrder.DoesNotExist: raise SellError( "This sell it's not associated to any GoogleCheckoutOrder! Refund can't be performed" ) if self.is_braintree(): from payments.gateways.braintreegw import BraintreeGateway from payments.models import BrainTreeTransaction try: bt_txn = BrainTreeTransaction.objects.filter( sell=self).get() except BrainTreeTransaction.DoesNotExist: raise SellError( 'There is no Braintree transaction associated to this sell!' ) gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) refund = gw.refund_transaction(bt_txn.transaction_id) if not refund.is_success: message = "" if refund.transaction: code = refund.transaction.processor_response_code text = refund.transaction.processor_response_text message = "Refund Failed! %s.\[%s] %s" % ( refund.message, code, text) else: for error in refund.errors.deep_errors: txt = "attribute: %s, code: %s. %s" ( error.attribute, error.code, error.message) message += txt + "\n" raise SellError("Can't do refund. %s" % message) for item in self.sellitem_set.all(): # item.product.increase_qty(item.qty) item.product.activate() item.save() self.cancel = True self.save() self.payment.refunded() else: raise SellError( 'Can not refund this sell, your state is not paid.')
def checkout_confirm(request): from payments.gateways.googlecheckout import GoogleCheckoutGateway from payments.gateways.paypal import PayPalGateway from payments.gateways.braintreegw import BraintreeGateway from payments.models import GoogleCheckoutShopSettings, PayPalShopSettings, ManualPaymentShopSettings, BraintreeShopSettings #A list of payment method, each payment method know how to render as a link #payment_methods = request.shop.get_payment_methods() payment_buttons = [] #profile = request.user.get_profile() cart = request.cart shop = request.shop try: google_settings = GoogleCheckoutShopSettings.objects.filter(shop = shop).get() googlecheckout_gw = GoogleCheckoutGateway(google_settings.merchant_id, google_settings.merchant_key, debug=True) button = googlecheckout_gw.render_button(cart) payment_buttons.append(button) except GoogleCheckoutShopSettings.DoesNotExist: pass try: braintree_settings = BraintreeShopSettings.objects.filter(shop = shop).get() braintree_gw = BraintreeGateway(braintree_settings.merchant_id, braintree_settings.public_key, braintree_settings.private_key, ) button = braintree_gw.render_button(cart) payment_buttons.append(button) except BraintreeShopSettings.DoesNotExist: pass try: paypal_settings = PayPalShopSettings.objects.filter(shop = shop).get() paypal_gw = PayPalGateway(username=settings.PAYPAL_USERNAME, password=settings.PAYPAL_PASSWORD, sign=settings.PAYPAL_SIGNATURE, debug=settings.PAYPAL_DEBUG) button = paypal_gw.render_button() logging.critical(button) payment_buttons.append(button) except PayPalShopSettings.DoesNotExist: pass try: manual_payment_settings = ManualPaymentShopSettings.objects.filter(shop = shop) url = reverse("myshopping_checkout_manual_payment") if manual_payment_settings.count(): button = """ <div> <h3>Manual Payments</h3>\n <form name='manual_payment' action='%s' method='POST'>\n """ % url for idx, payment in enumerate(manual_payment_settings): input = '\t<input type="radio" name="manual_payment_id" checked="%d" value="%s"> %s </input><br/>\n' % (1 if idx == 0 else 0, payment.id, payment.name) button += input button += "<br/>" button += "<button class='primaryAction small awesome' type='submit'>Submit</button>\n" button += "</form>\n" button += "</div>" logging.debug(button) payment_buttons.append(button) except Exception, e: logging.error(e)
def send_past_due_notification(): gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) past_due_days = 2 subscriptions = gw.get_past_due_subscriptions(past_due_days) logging.info("%s subscriptions were found with status past due" % len(subscriptions)) for subscription in subscriptions: try: local_subscription = Subscription.objects.filter( subscription_id=subscription.id).get() #Send email to Site Admin msg = "We have found that Subscription (id=%s, plan=%s) for shop %s is past due. An email to shop owner will be sent to inform about this situation" % ( local_subscription.subscription_id, local_subscription.plan.name, local_subscription.owner.shop) logging.info(msg) mail = EmailMessage(subject='Past due Subscription', body=msg, from_email=settings.EMAIL_FROM, to=[b for (a, b) in settings.STAFF], headers={ 'X-SMTPAPI': '{\"category\": \"Past Due Subscription\"}' }) mail.send(fail_silently=True) # send_mail('Past due Subscription', msg, settings.EMAIL_FROM, [b for (a,b) in settings.STAFF], fail_silently=True) #Send email to shop owner msg = "We notice you that your subscription (%s) for shop %s is %s days past due." % ( local_subscription.plan.name, local_subscription.owner.shop, past_due_days) mail = EmailMessage(subject='Past due Subscription', body=msg, from_email=settings.EMAIL_FROM, to=[local_subscription.owner.user.email], headers={ 'X-SMTPAPI': '{\"category\": \"Past Due Subscription\"}' }) mail.send(fail_silently=True) # send_mail('Past due Suscription', msg, settings.EMAIL_FROM, [local_subscription.owner.user.email], fail_silently=True) except Subscription.DoesNotExist: error_msg = "Subscription<id%s> was not found. A past due subscription was found in braintree, but this subscription do not correspond with any in the system" % subscription.id logging.error(error_msg) mail = EmailMessage( subject='Subscription not found', body=error_msg, from_email=settings.EMAIL_FROM, to=[b for (a, b) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Error\"}'}) mail.send(fail_silently=True) # send_mail('Subscription not found', error_msg , settings.EMAIL_FROM, [b for (a,b) in settings.STAFF], fail_silently=True) except Exception, e: mail = EmailMessage( subject='Error when trying to check past due subscriptions', body=e, from_email=settings.EMAIL_FROM, to=[b for (a, b) in settings.STAFF], headers={'X-SMTPAPI': '{\"category\": \"Error\"}'}) mail.send(fail_silently=True)
def ajax_do_charge(request, feature): from payments.gateways.braintreegw import BraintreeGateway from subscriptions.models import FeaturesManager, FeaturePayment from django.conf import settings success = False shop = request.shop gw = BraintreeGateway(settings.MERCHANT_ID, settings.PUBLIC_KEY, settings.PRIVATE_KEY) #This is token asociated to the subscription, we will use it to charge the feature token = shop.subscription().extra_data()[7] #Try to charge the feature against braintree price = FeaturesManager.get_feature_price(shop, feature) result = gw.charge_purchase(token, price) admin_email = shop.marketplace.contact_email if result.is_success: status = result.transaction.status credit_card = "%s - %s******%s" % (result.transaction.credit_card[u'card_type'], result.transaction.credit_card[u'bin'], result.transaction.credit_card[u'last_4']) txn_id = result.transaction.id if status == 'authorized': logging.info("Transaction <id=%s> was successfully authorized!!" % (txn_id)) submit = gw.submit_for_settlement(txn_id) message = None if submit.is_success: message = "Shop: %s\nFeature: %s\nPrice: $ %s\nCredit Card: %s\nTransaction ID: %s\nTransaction Status: %s\n" % (shop, feature, price, credit_card, txn_id, status) logging.info(message) else: message = "WARNING: Transaction<id=%s> was successfully authorized but could not be submited for settlement. Try it manually via braintree admin site" % txn_id logging.critical(message) send_mail("Featured Successfully Purchased!", "\nWe have enabled the %s feature in your %s shop.\n\nWe collected $%s from your %s credit card account.\n\nThanks, %s" % (feature, shop, price, credit_card, shop.marketplace), settings.EMAIL_FROM, [shop.admin.email], True) send_mail("%s purchased the %s feature" % (shop, feature), message, settings.EMAIL_FROM, [mail for (name, mail) in settings.STAFF]+[admin_email], True) else: logging.critical("Transaction<id=%s> status is %s. Can't submit for settlement if status != authorized" % (txn_id, status)) success = True else: success = False if success: payment = FeaturePayment(shop=shop) payment.transaction_id = txn_id payment.price = price payment.feature = feature payment.save() FeaturesManager.set_feature_enabled(shop, feature) resp = { 'status': 'success', 'txn_id': txn_id } return HttpResponse(simplejson.dumps(resp), mimetype="application/json") logging.critical("Feature could not be charged :(") for error in result.errors.deep_errors: logging.critical("Gateway Error Found > code=%s, msg=%s" % (error.code, error.message)) message = "" if status == "processor_declined": message = "Reason: Processor declined the transaction<id=%s>. Error code %s - %s" % (result.transaction.id, result.transaction.processor_response_code, result.transaction.processor_response_text) elif status == "gateway_rejected": message = "Reason: Gateway rejected the transaction<id=%s>. Error on %s" % (result.transaction.id, result.transaction.gateway_rejection_reason) else: message = "Reason: transaction<id=%s> status is %s!. We have no more info about this status. Please check braintree admin console." % (status, result.transaction.id) logging.critical(message) send_mail("%s tried but failed to purchase the %s feature" % (shop, feature), message, settings.EMAIL_FROM, [mail for (name, mail) in settings.STAFF]+[admin_email], True) return HttpResponseServerError()