예제 #1
0
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))
예제 #2
0
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)
예제 #5
0
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))
예제 #6
0
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'))
예제 #7
0
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)
예제 #9
0
 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
     ]
예제 #10
0
 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
     ]
예제 #11
0
 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)        
예제 #12
0
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)
예제 #13
0
 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)
예제 #14
0
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)
예제 #18
0
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)
예제 #19
0
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'))
예제 #20
0
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)
예제 #21
0
 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.')
예제 #22
0
    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
예제 #23
0
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)
예제 #24
0
    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]))
예제 #25
0
    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]))
예제 #26
0
    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
예제 #27
0
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)
예제 #28
0
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()
예제 #29
0
    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.')
예제 #30
0
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)
예제 #32
0
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()