Example #1
0
def success(request):
    """
    The order has been succesfully processed.
    """

    session = SessionStore(session_key=request.POST.get("M_session"))
    transaction_id = request.POST.get("cartId")
    amount = request.POST.get("authAmount")
    request.session = session

    if request.POST.get("transStatus", "N") == "Y":
        order = Order.objects.get(pk=transaction_id)
        order.add_status(status="Processing",
                         notes=_("Paid through WorldPay."))
        request.user = order.contact.user
        record_payment(order,
                       payment_module,
                       amount=amount,
                       transaction_id=transaction_id)
        for cart in Cart.objects.filter(customer=order.contact):
            cart.empty()
        return generic_success(request,
                               template="checkout/worldpay/success.html")
    else:
        context = {"message": _("Your transaction was rejected.")}
        return render(request, "shop_404.html", context)
Example #2
0
    def process(self):
        # Execute the post to protx VSP DIRECT        
        if self.valid:
            if self.settings.SKIP_POST.value:
                log.info("TESTING MODE - Skipping post to server.  Would have posted %s?%s", self.url, self.postString)
                record_payment(self.order, self.settings, amount=self.order.balance, transaction_id="TESTING")
                return (True, 'OK', "TESTING MODE")

            else:
                self.log_extra("About to post to server: %s?%s", self.url, self.postString)
                conn = urllib2.Request(self.url, data=self.postString)
                try:
                    f = urllib2.urlopen(conn)
                    result = f.read()
                    self.log_extra('Process: url=%s\nPacket=%s\nResult=%s', self.url, self.packet, result)
                except urllib2.URLError, ue:
                    log.error("error opening %s\n%s", self.url, ue)
                    print ue
                    return (False, 'ERROR', 'Could not talk to Protx gateway')
                try:
                    self.response = dict([row.split('=', 1) for row in result.splitlines()])
                    status = self.response['Status']
                    success = (status == 'OK')
                    detail = self.response['StatusDetail']
                    if success:
                        log.info('Success on order #%i, recording payment', self.order.id)
                        record_payment(self.order, self.settings, amount=self.order.balance) #, transaction_id=transaction_id)
                    return (success, status, detail)
                except Exception, e:
                    log.info('Error submitting payment: %s', e)
                    return (False, 'ERROR', 'Invalid response from payment gateway')
Example #3
0
def one_step(request):
    # Check that items are in stock
    cart = Cart.objects.from_request(request)
    if cart.not_enough_stock():
        return HttpResponseRedirect(reverse("satchmo_cart"))

    payment_module = config_get_group("PAYMENT_AUTOSUCCESS")

    # First verify that the customer exists
    try:
        contact = Contact.objects.from_request(request, create=False)
    except Contact.DoesNotExist:
        url = lookup_url(payment_module, "satchmo_checkout-step1")
        return HttpResponseRedirect(url)
    # Verify we still have items in the cart
    if cart.numItems == 0:
        template = lookup_template(payment_module, "checkout/empty_cart.html")
        return render(request, template)

    # Create a new order
    newOrder = Order(contact=contact)
    pay_ship_save(newOrder, cart, contact, shipping="", discount="")

    request.session["orderID"] = newOrder.id

    newOrder.add_status(status="Pending", notes="Order successfully submitted")

    record_payment(newOrder, payment_module, amount=newOrder.balance)

    success = lookup_url(payment_module, "satchmo_checkout-success")
    return HttpResponseRedirect(success)
Example #4
0
def success(request):
    """
    The order has been succesfully processed.
    """

    session = SessionStore(session_key=request.POST.get('M_session'))
    transaction_id = request.POST.get('cartId')
    amount = request.POST.get('authAmount')
    request.session = session

    if request.POST.get('transStatus', 'N') == 'Y':
        order = Order.objects.get(pk=transaction_id)
        order.add_status(status='Processing',
                         notes=_("Paid through WorldPay."))
        request.user = order.contact.user
        record_payment(order,
                       payment_module,
                       amount=amount,
                       transaction_id=transaction_id)
        for cart in Cart.objects.filter(customer=order.contact):
            cart.empty()
        return generic_success(request,
                               template='checkout/worldpay/success.html')
    else:
        context = RequestContext(
            request, {'message': _('Your transaction was rejected.')})
        return render_to_response('shop_404.html', context)
Example #5
0
def one_step(request):
    payment_module = config_get_group('PAYMENT_AUTOSUCCESS')

    #First verify that the customer exists
    try:
        contact = Contact.objects.from_request(request, create=False)
    except Contact.DoesNotExist:
        url = lookup_url(payment_module, 'satchmo_checkout-step1')
        return HttpResponseRedirect(url)
    #Verify we still have items in the cart
    tempCart = Cart.objects.from_request(request)
    if tempCart.numItems == 0:
        template = lookup_template(payment_module, 'checkout/empty_cart.html')
        return render_to_response(template, RequestContext(request))
            
    # Create a new order
    newOrder = Order(contact=contact)
    pay_ship_save(newOrder, tempCart, contact,
        shipping="", discount="")
        
    request.session['orderID'] = newOrder.id
        
    newOrder.add_status(status='Pending', notes = "Order successfully submitted")

    record_payment(newOrder, payment_module, amount=newOrder.balance)
    
    tempCart.empty()
    success = lookup_url(payment_module, 'satchmo_checkout-success')
    return HttpResponseRedirect(success)
Example #6
0
    def process(self):
        """
        Purchase Orders are always successful.
        """

        reason_code = "0"
        response_text = _("Success")
        
        record_payment(self.order, self.settings, amount=self.order.balance)
        
        return (True, reason_code, response_text)
Example #7
0
    def process(self):
        """
        Purchase Orders are always successful.
        """

        reason_code = "0"
        response_text = _("Success")

        record_payment(self.order, self.settings, amount=self.order.balance)

        return (True, reason_code, response_text)
Example #8
0
 def process_recurring_subscriptions(self, recurlist, testing=False):
     """Post all subscription requests."""    
     
     for recur in recurlist:
         success, reason, response, subscription_id = self.process_recurring_subscription(recur, testing=testing)
         if success:
             if not testing:
                 record_payment(self.order, self.settings, amount=recur['charged_today'], transaction_id=subscription_id)
         else:
             self.log.info("Failed to process recurring subscription, %s: %s", reason, response)
             break
     
     return success, reason, response
Example #9
0
 def process(self):
     # process the transaction through tclink
     result = tclink.send(self.transactionData)
     status = result ['status']
     if status == 'approved':
         record_payment(self.order, self.settings, amount=self.order.balance)
         return (True, status, result)
     if status == 'decline':
         msg = _(u'Transaction was declined.  Reason: %s' % result['declinetype'])
         return (False, status, msg)
     if status == 'baddata':
         msg = _(u'Improperly formatted data. Offending fields: %s' % result['offenders'])
         return (False, status, msg)
     else:
         msg = _(u'An error occurred: %s' % result['errortype'])
         return (False, status, msg)
Example #10
0
    def process_recurring_subscriptions(self, recurlist, testing=False):
        """Post all subscription requests."""

        for recur in recurlist:
            success, reason, response, subscription_id = self.process_recurring_subscription(
                recur, testing=testing)
            if success:
                if not testing:
                    record_payment(self.order,
                                   self.settings,
                                   amount=recur['charged_today'],
                                   transaction_id=subscription_id)
            else:
                self.log.info(
                    "Failed to process recurring subscription, %s: %s", reason,
                    response)
                break

        return success, reason, response
Example #11
0
 def process(self):
     # process the transaction through tclink
     result = tclink.send(self.transactionData)
     status = result['status']
     if status == 'approved':
         record_payment(self.order,
                        self.settings,
                        amount=self.order.balance)
         return (True, status, result)
     if status == 'decline':
         msg = _(u'Transaction was declined.  Reason: %s' %
                 result['declinetype'])
         return (False, status, msg)
     if status == 'baddata':
         msg = _(u'Improperly formatted data. Offending fields: %s' %
                 result['offenders'])
         return (False, status, msg)
     else:
         msg = _(u'An error occurred: %s' % result['errortype'])
         return (False, status, msg)
Example #12
0
    def apply_to_order(self, order):
        """Apply up to the full amount of the balance of this cert to the order.

        Returns new balance.
        """
        amount = min(order.balance, self.balance)
        log.info('applying %s from giftcert #%i [%s] to order #%i [%s]',
                 money_format(amount), self.id, money_format(self.balance),
                 order.id, money_format(order.balance))
        config = config_get_group('PAYMENT_GIFTCERTIFICATE')
        orderpayment = record_payment(order, config, amount)
        return self.use(amount, orderpayment=orderpayment)
Example #13
0
def success(request):
    """
    The order has been succesfully processed.
    """

    session = SessionStore(session_key=request.POST.get('M_session'))
    transaction_id = request.POST.get('cartId')
    amount = request.POST.get('authAmount')
    request.session = session

    if request.POST.get('transStatus', 'N') == 'Y':
        order = Order.objects.get(pk=transaction_id)
        order.add_status(status='Processing', notes=_("Paid through WorldPay."))
        request.user = order.contact.user
        record_payment(order, payment_module, amount=amount, transaction_id=transaction_id)
        for cart in Cart.objects.filter(customer=order.contact):
            cart.empty()
        return generic_success(request, template='checkout/worldpay/success.html')
    else:
        context = RequestContext(request,
                                 {'message': _('Your transaction was rejected.')})
        return render_to_response('shop_404.html', context)
Example #14
0
    def apply_to_order(self, order):
        """Apply up to the full amount of the balance of this cert to the order.

        Returns new balance.
        """
        amount = min(order.balance, self.balance)
        log.info('applying %s from giftcert #%i [%s] to order #%i [%s]', 
            money_format(amount), 
            self.id, 
            money_format(self.balance), 
            order.id, 
            money_format(order.balance))
        config = config_get_group('PAYMENT_GIFTCERTIFICATE')
        orderpayment = record_payment(order, config, amount)
        return self.use(amount, orderpayment=orderpayment)
Example #15
0
    def process(self):
        """
        Process the transaction and return a tuple:
            (success/failure, reason code, response text)

        Example:
        >>> from django.conf import settings
        >>> from satchmo.payment.modules.dummy.processor import PaymentProcessor
        >>> processor = PaymentProcessor(settings)
        # If using a normal payment module, data should be an Order object.
        >>> data = {}
        >>> processor.prepareData(data)
        >>> processor.process()
        (True, '0', u'Success')
        """
        
        orderpayment = record_payment(self.order, self.settings, amount=self.order.balance)

        reason_code = "0"
        response_text = _("Success")

        return (True, reason_code, response_text)
Example #16
0
    def process(self):
        """
        Process the transaction and return a tuple:
            (success/failure, reason code, response text)

        Example:
        >>> from django.conf import settings
        >>> from satchmo.payment.modules.dummy.processor import PaymentProcessor
        >>> processor = PaymentProcessor(settings)
        # If using a normal payment module, data should be an Order object.
        >>> data = {}
        >>> processor.prepareData(data)
        >>> processor.process()
        (True, '0', u'Success')
        """

        orderpayment = record_payment(self.order,
                                      self.settings,
                                      amount=self.order.balance)

        reason_code = "0"
        response_text = _("Success")

        return (True, reason_code, response_text)
Example #17
0
            all_results = f.read()
            self.log_extra('Authorize response: %s', all_results)
        except urllib2.URLError, ue:
            self.log.error("error opening %s\n%s", data['connection'], ue)
            return (False, 'ERROR', _('Could not talk to Authorize.net gateway'))
            
        parsed_results = all_results.split(data['configuration']['x_delim_char'])
        response_code = parsed_results[0]
        reason_code = parsed_results[1]
        response_text = parsed_results[3]
        transaction_id = parsed_results[6]
        success = response_code == '1'
        
        if success and not testing:
            self.log_extra('Success, recording payment')
            record_payment(self.order, self.settings, amount=data['amount'], transaction_id=transaction_id)
                
        self.log_extra("Returning success=%s, reason=%s, response_text=%s", success, reason_code, response_text)
        return(success, reason_code, response_text)

if __name__ == "__main__":
    """
    This is for testing - enabling you to run from the command line and make
    sure everything is ok
    """
    import os
    from satchmo.configuration import config_get_group
    import config

    # Set up some dummy classes to mimic classes being passed through Satchmo
    class testContact(object):
Example #18
0
def ipn(request):
    """PayPal IPN (Instant Payment Notification)
    Cornfirms that payment has been completed and marks invoice as paid.
    Adapted from IPN cgi script provided at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/456361"""
    payment_module = config_get_group('PAYMENT_PAYPAL')
    if payment_module.LIVE.value:
        log.debug("Live IPN on %s", payment_module.KEY.value)
        url = payment_module.POST_URL.value
        account = payment_module.BUSINESS.value
    else:
        log.debug("Test IPN on %s", payment_module.KEY.value)
        url = payment_module.POST_TEST_URL.value
        account = payment_module.BUSINESS_TEST.value
    PP_URL = url

    try:
        data = request.POST
        log.debug("PayPal IPN data: " + repr(data))
        if not confirm_ipn_data(data, PP_URL):
            return HttpResponse()

        if not 'payment_status' in data or not data['payment_status'] == "Completed":
            # We want to respond to anything that isn't a payment - but we won't insert into our database.
             log.info("Ignoring IPN data for non-completed payment.")
             return HttpResponse()

        try:
            invoice = data['invoice']
        except:
            invoice = data['item_number']

        gross = data['mc_gross']
        txn_id = data['txn_id']

        if not OrderPayment.objects.filter(transaction_id=txn_id).count():
            # If the payment hasn't already been processed:
            order = Order.objects.get(pk=invoice)
            
            order.add_status(status='Pending', notes=_("Paid through PayPal."))
            payment_module = config_get_group('PAYMENT_PAYPAL')
            record_payment(order, payment_module, amount=gross, transaction_id=txn_id)
            
            if 'memo' in data:
                if order.notes:
                    notes = order.notes + "\n"
                else:
                    notes = ""
                
                order.notes = notes + _('---Comment via Paypal IPN---') + u'\n' + data['memo']
                order.save()
                log.debug("Saved order notes from Paypal")
            
            for item in order.orderitem_set.filter(product__subscriptionproduct__recurring=True, completed=False):
                item.completed = True
                item.save()
            for cart in Cart.objects.filter(customer=order.contact):
                cart.empty()
                
    except:
        log.exception(''.join(format_exception(*exc_info())))

    return HttpResponse()
Example #19
0
def process(request):
    """`Direct HTTP server-to-server request` processing.

    Details returned according to https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/e-commerce/transaction-feedback#feedbackparameters
    These can be customised, but we will assume that these ones are available.

    ACCEPTANCE Acceptance code returned by the acquirer
    AMOUNT Order amount (not multiplied by 100)
    BRAND Card brand (our system derives this from the card number)
    CARDNO Masked card number
    CN Cardholder/customer name
    CURRENCY Order currency
    ED Expiry date
    NCERROR Error code
    orderID Your order reference
    PAYID Payment reference in our system
    PM Payment method
    SHASIGN SHA signature calculated by our system (if SHA-OUT configured)
    STATUS Transaction status (see Status overview)
    TRXDATE Transaction date
    """
    logger.debug("Process: %s", request.POST)
    post_data = CaseInsensitiveReadOnlyDict(request.POST)
    if request.method == "POST":
        shasign = post_data.get("SHASIGN")
        # Verify the Shasign
        if verify_shasign(shasign, post_data):
            try:
                order = Order.objects.get(id=post_data.get("orderID"))
            except Order.DoesNotExist:
                raise Http404()

            amount = Decimal(post_data.get("AMOUNT"))
            transaction_id = post_data.get("ACCEPTANCE")

            if order.notes is None:
                order.notes = ""
            order.notes += "\n------------------ {now} ------------------\n\n".format(
                now=timezone.now())

            if "STATUS" in post_data:
                status = TRANSACTION_STATUS[int(post_data["STATUS"])]["NAME"]
            else:
                status = "Unknown"

            notes = """
Status: {status}
Transaction date: {transaction_date}
Transaction ID: {acceptance}
Ingenico ID: {ingenico_id}
Amount: {amount}
Currency: {currency}

NC Error: {nc_error}
Payment method: {pm}
Cardholder name: {cn}
Card no: {cardno}
Brand: {brand}
Expiry date: {ed}
            """.format(
                status=status,
                transaction_date=post_data.get("TRXDATE"),
                acceptance=transaction_id,
                ingenico_id=post_data.get("PAYID"),
                amount=post_data.get("amount"),
                currency=post_data.get("CURRENCY"),
                nc_error=post_data.get("NCERROR"),
                pm=post_data.get("PM"),
                cn=post_data.get("CN"),
                cardno=post_data.get("CARDNO"),
                brand=post_data.get("BRAND"),
                ed=post_data.get("ED"),
            )
            order.notes += notes
            order.save()

            # Ensure the status is ok before recording payment
            # https://payment-services.ingenico.com/int/en/ogone/support/guides/user%20guides/statuses-and-errors
            if "STATUS" in post_data:
                status = int(post_data["STATUS"])
                if status == 9:  # Payment requested, ok to send package
                    record_payment(
                        order,
                        payment_module,
                        amount=amount,
                        transaction_id=transaction_id,
                    )
                    complete_order(order)
                    order.add_status(status="Processing",
                                     notes=_("Payment complete."))
                elif status == 1:  # Cancelled by customer
                    if order.frozen is False:
                        order.freeze()
                    restock_order(order)
                    order.save()
                    order.add_status(status="Cancelled", notes=_(""))
                elif status == 7 or status == 8:  # Payment Deleted or Refunded
                    if order.frozen is False:
                        order.freeze()
                    order.save()
                    order.add_status(status="Refunded", notes=_(""))
                    OrderRefund.objects.create(
                        order=order,
                        amount=amount,
                        exchange_rate=order.exchange_rate,
                        transaction_id=transaction_id,
                    )
                elif status == 2:  # Authorisation refused
                    if order.frozen is False:
                        order.freeze()
                    restock_order(order)
                    order.save()
                    order.add_status(
                        status="Authorisation refused",
                        notes=_("Please contact your bank or card issuer."),
                    )
            return HttpResponse()
        else:
            logger.warning("Verification failed: %s",
                           pprint.pformat(post_data.items()))
            return HttpResponsePaymentRequired()
    else:
        return HttpResponseMethodNotAllowed()
Example #20
0
def process(request):
    """`Direct HTTP server-to-server request` processing.

    Details returned according to https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/e-commerce/transaction-feedback#feedbackparameters
    These can be customised, but we will assume that these ones are available.

    ACCEPTANCE Acceptance code returned by the acquirer
    AMOUNT Order amount (not multiplied by 100)
    BRAND Card brand (our system derives this from the card number)
    CARDNO Masked card number
    CN Cardholder/customer name
    CURRENCY Order currency
    ED Expiry date
    NCERROR Error code
    orderID Your order reference
    PAYID Payment reference in our system
    PM Payment method
    SHASIGN SHA signature calculated by our system (if SHA-OUT configured)
    STATUS Transaction status (see Status overview)
    TRXDATE Transaction date
    """
    logger.debug("Process: %s", request.POST)
    post_data = CaseInsensitiveReadOnlyDict(request.POST)
    if request.method == "POST":
        shasign = post_data.get("SHASIGN")
        # Verify the Shasign
        if verify_shasign(shasign, post_data):
            try:
                order = Order.objects.get(id=post_data.get("orderID"))
            except Order.DoesNotExist:
                raise Http404()

            amount = Decimal(post_data.get("AMOUNT"))
            transaction_id = post_data.get("ACCEPTANCE")

            if order.notes is None:
                order.notes = ""
            order.notes += "\n------------------ {now} ------------------\n\n".format(
                now=timezone.now()
            )

            if "STATUS" in post_data:
                status = TRANSACTION_STATUS[int(post_data["STATUS"])]["NAME"]
            else:
                status = "Unknown"

            notes = """
Status: {status}
Transaction date: {transaction_date}
Transaction ID: {acceptance}
Ingenico ID: {ingenico_id}
Amount: {amount}
Currency: {currency}

NC Error: {nc_error}
Payment method: {pm}
Cardholder name: {cn}
Card no: {cardno}
Brand: {brand}
Expiry date: {ed}
            """.format(
                status=status,
                transaction_date=post_data.get("TRXDATE"),
                acceptance=transaction_id,
                ingenico_id=post_data.get("PAYID"),
                amount=post_data.get("amount"),
                currency=post_data.get("CURRENCY"),
                nc_error=post_data.get("NCERROR"),
                pm=post_data.get("PM"),
                cn=post_data.get("CN"),
                cardno=post_data.get("CARDNO"),
                brand=post_data.get("BRAND"),
                ed=post_data.get("ED"),
            )
            order.notes += notes
            order.save()

            # Ensure the status is ok before recording payment
            # https://payment-services.ingenico.com/int/en/ogone/support/guides/user%20guides/statuses-and-errors
            if "STATUS" in post_data:
                status = int(post_data["STATUS"])
                if status == 9:  # Payment requested, ok to send package
                    record_payment(
                        order,
                        payment_module,
                        amount=amount,
                        transaction_id=transaction_id,
                    )
                    complete_order(order)
                    order.add_status(status="Processing", notes=_("Payment complete."))
                elif status == 1:  # Cancelled by customer
                    if order.frozen is False:
                        order.freeze()
                    restock_order(order)
                    order.save()
                    order.add_status(status="Cancelled", notes=_(""))
                elif status == 7 or status == 8:  # Payment Deleted or Refunded
                    if order.frozen is False:
                        order.freeze()
                    order.save()
                    order.add_status(status="Refunded", notes=_(""))
                    OrderRefund.objects.create(
                        order=order,
                        amount=amount,
                        exchange_rate=order.exchange_rate,
                        transaction_id=transaction_id,
                    )
                elif status == 2:  # Authorisation refused
                    if order.frozen is False:
                        order.freeze()
                    restock_order(order)
                    order.save()
                    order.add_status(
                        status="Authorisation refused",
                        notes=_("Please contact your bank or card issuer."),
                    )
            return HttpResponse()
        else:
            logger.warning("Verification failed: %s", post_data)
            return HttpResponsePaymentRequired()
    else:
        return HttpResponseMethodNotAllowed()
Example #21
0
            self.log.error("error opening %s\n%s", data['connection'], ue)
            return (False, 'ERROR',
                    _('Could not talk to Authorize.net gateway'))

        parsed_results = all_results.split(
            data['configuration']['x_delim_char'])
        response_code = parsed_results[0]
        reason_code = parsed_results[1]
        response_text = parsed_results[3]
        transaction_id = parsed_results[6]
        success = response_code == '1'

        if success and not testing:
            self.log_extra('Success, recording payment')
            record_payment(self.order,
                           self.settings,
                           amount=data['amount'],
                           transaction_id=transaction_id)

        self.log_extra("Returning success=%s, reason=%s, response_text=%s",
                       success, reason_code, response_text)
        return (success, reason_code, response_text)


if __name__ == "__main__":
    """
    This is for testing - enabling you to run from the command line and make
    sure everything is ok
    """
    import os
    from satchmo.configuration import config_get_group
    import config
Example #22
0
class PaymentProcessor(object):
    """
    Cybersource payment processing module
    You must have an account with Cybersource in order to use this module
    
    """
    def __init__(self, settings):
        self.settings = settings
        self.contents = ''
        if settings.LIVE.value:
            self.testflag = 'FALSE'
            self.connection = settings.CONNECTION.value
        else:
            self.testflag = 'TRUE'
            self.connection = settings.CONNECTION_TEST.value
            
        self.configuration = {
            'merchantID' : settings.MERCHANT_ID.value,
            'password' : settings.TRANKEY.value,
            }

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

        self.order = data

    def process(self):
        """
        Creates and sends XML representation of transaction to Cybersource
        
        """
        # XML format is very simple, using ElementTree for generation would be overkill
        t = loader.get_template('checkout/cybersource/request.xml')
        c = Context({
            'config' : self.configuration,
            'merchantReferenceCode' : self.order.id,
            'billTo' : self.bill_to,
            'purchaseTotals' : self.purchase_totals,
            'card' : self.card,
        })
        request = t.render(c)
        conn = urllib2.Request(url=self.connection, data=request)
        try:
            f = urllib2.urlopen(conn)
        except urllib2.HTTPError, e:
            # we probably didn't authenticate properly
            # make sure the 'v' in your account number is lowercase
            return(False, '999', 'Problem parsing results')
        f = urllib2.urlopen(conn)
        all_results = f.read()
        tree = fromstring(all_results)
        parsed_results = tree.getiterator('{urn:schemas-cybersource-com:transaction-data-1.26}reasonCode')
        try:
            reason_code = parsed_results[0].text
        except KeyError:
            return(False, '999', 'Problem parsing results')
        # Response codes available at:
        # http://apps.cybersource.com/library/documentation/sbc/api_guide/SB_API.pdf
        response_text_dict = {
            '100' : 'Successful transaction.',
            '101' : 'The request is missing one or more required fields.',
            '102' : 'One or more fields in the request contains invalid data.',
            '104' : 'The merchantReferenceCode sent with this authorization request matches the merchantReferenceCode of another authorization request that you sent in the last 15 minutes.',
            '150' : 'Error: General system failure. ',
            '151' : 'Error: The request was received but there was a server timeout. This error does not include timeouts between the client and the server.',
            '152' : 'Error: The request was received, but a service did not finish running in time.',
            '201' : 'The issuing bank has questions about the request. You do not receive an authorization code in the reply message, but you might receive one verbally by calling the processor.',
            '202' : 'Expired card. You might also receive this if the expiration date you provided does not match the date the issuing bank has on file.',
            '203' : 'General decline of the card. No other information provided by the issuing bank.',
            '204' : 'Insufficient funds in the account.',
            '205' : 'Stolen or lost card.',
            '207' : 'Issuing bank unavailable.',
            '208' : 'Inactive card or card not authorized for card-not-present transactions.',
            '210' : 'The card has reached the credit limit. ',
            '211' : 'Invalid card verification number.',
            '221' : 'The customer matched an entry on the processor\'s negative file.',
            '231' : 'Invalid account number.',
            '232' : 'The card type is not accepted by the payment processor.',
            '233' : 'General decline by the processor.',
            '234' : 'There is a problem with your CyberSource merchant configuration.',
            '235' : 'The requested amount exceeds the originally authorized amount. Occurs, for example, if you try to capture an amount larger than the original authorization amount. This reason code only applies if you are processing a capture through the API.',
            '236' : 'Processor Failure',
            '238' : 'The authorization has already been captured. This reason code only applies if you are processing a capture through the API.',
            '239' : 'The requested transaction amount must match the previous transaction amount. This reason code only applies if you are processing a capture or credit through the API.',
            '240' : 'The card type sent is invalid or does not correlate with the credit card number.',
            '241' : 'The request ID is invalid. This reason code only applies when you are processing a capture or credit through the API.',
            '242' : 'You requested a capture through the API, but there is no corresponding, unused authorization record. Occurs if there was not a previously successful authorization request or if the previously successful authorization has already been used by another capture request. This reason code only applies when you are processing a capture through the API.',
            '243' : 'The transaction has already been settled or reversed.',
            '246' : 'The capture or credit is not voidable because the capture or credit information has already been submitted to your processor. Or, you requested a void for a type of transaction that cannot be voided. This reason code applies only if you are processing a void through the API.',
            '247' : 'You requested a credit for a capture that was previously voided. This reason code applies only if you are processing a void through the API.',
            '250' : 'Error: The request was received, but there was a timeout at the payment processor.',
            '520' : 'The authorization request was approved by the issuing bank but declined by CyberSource based on your Smart Authorization settings.',
        }
        if response_text_dict.has_key(reason_code):
            response_text = response_text_dict[reason_code]
        else:
            response_text = 'Unknown failure'
        if reason_code == '100':
            record_payment(self.order, self.settings, amount=self.order.balance)
            return(True, reason_code, response_text)
        else:
            return(False, reason_code, response_text)
def paypal_express_pay(request):
    """Process the real payment on PayPal Express Checkout with DoExpressCheckoutPayment"""

    try:
        order = Order.objects.from_request(request)
    except Order.DoesNotExist:
        url = lookup_url(payment_module, 'satchmo_checkout-step1')
        return HttpResponseRedirect(url)

    tempCart = Cart.objects.from_request(request)
    if tempCart.numItems == 0:
        template = lookup_template(payment_module, 'checkout/empty_cart.html')
        return render_to_response(template, RequestContext(request))

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

    payment_module = config_get_group('PAYMENT_PAYPAL_EXPRESS')
    #amount = '%.2f' % (order.total)
    paypal = PayPal(payment_module)
    
    shipping_amount = order.shipping_cost
    shipping_discount = order.shipping_discount
    

    
    if 'paypal_express_token' in request.session:
        paypal_express_token = request.session['paypal_express_token']
        response_getDetails = paypal.GetExpressCheckoutDetails(paypal_express_token, return_all=True)
        params = {
            'PAYERID' : response_getDetails["PAYERID"][0],
            'CURRENCYCODE' : 'USD',
            'AMT' : '%.2f' % order.total,
            'ITEMAMT' : '%.2f' % order.sub_total,
            'SHIPPINGAMT' : '%.2f' % order.shipping_cost,
            'SHIPPINGDISCOUNT' : '%.2f' % order.shipping_discount,
            'TAXAMT' : '%.2f' % (order.tax - order.discount),
            'TOKEN' : paypal_express_token,
        }
        
        # This function does the payment
        data = paypal.DoExpressCheckoutPayment(params)
      

    #try:
    
    log.debug("PayPal Express Checkout data: " + repr(data))
    
    if not 'RESULT' in data or not data['RESULT'] == '0':
    #if not 'payment_status' in data or not data['payment_status'] == "Completed":
        # We want to respond to anything that isn't a payment - but we won't insert into our database.
        log.info("Ignoring IPN data for non-completed payment.")
         
        # I show a failed payment error
        template = lookup_template(payment_module, 'checkout/paypal_express/failed.html')

        # {'ACK': 'Failure', 'TIMESTAMP': '2009-02-28T13:48:55Z', 'L_SEVERITYCODE0': 'Error', 'L_SHORTMESSAGE0': 'Transaction cannot complete.', 'L_LONGMESSAGE0': 'The transaction cannot complete successfully.  Instruct the customer to use an alternative payment method.', 'VERSION': '53.0', 'BUILD': '845846', 'L_ERRORCODE0': '10417', 'CORRELATIONID': 'be804544f01'}

        ctx = RequestContext(request, {'order': order,
             'data': repr(data),
             'ack': data["RESPMSG"],
             #'severity_code': data["L_SEVERITYCODE0"],
             #'short_message': data["L_SHORTMESSAGE0"],
             #'long_message': data["L_LONGMESSAGE0"],
             #'error_code': data["L_ERRORCODE0"],
        })

        # Li aggiungo fuori perche se ne manca uno altrimenti restituisce un keyerror
        try:
            ctx["severity_code"]= data["RESULT"]
        except:
            pass

        try:
            ctx["short_message"]= data["RESPMSG"]
        except:
            pass

         
        try:
            ctx["long_message"]= data["RESPMSG"]
        except:
            pass

        try:
            ctx["error_code"]=data["RESULT"]
        except:
            pass
        
        return render_to_response(template, ctx)
        

    txn_id = data['PNREF']
    
    if not OrderPayment.objects.filter(transaction_id=txn_id).count():
        
    # If the payment hasn't already been processed:
        #order = Order.objects.get(pk=invoice)         
        order.add_status(status='Billed', notes=_("Paid through PayPal Express Checkout."))
        #orderstatus = order.status
        
        record_payment(order, payment_module, amount=order.total, transaction_id=txn_id)
        notes_changed = False
        if order.notes:
                notes = order.notes + "\n"
        else:
                notes = ""
                
        # Retrieving notes from paypal NOTE field
        if 'NOTE' in response_getDetails:
            notes_changed = True
	    
	    response_notes = response_getDetails['NOTE'][0] # If I get some problems, the error will include notes if I put it in a variable.
            notes = u"\n%s \n%s \n%s" % (notes, _('---Comment via Paypal EXPRESS CHECKOUT---') ,response_notes )
            log.debug("Saved order notes from Paypal Express Checkout")
        
        # Retrieving notes from confirmation page
        if (request.method == "POST") and ('note' in request.POST) and (request.POST['note'] != ""):
            notes_changed = True
            #notes = notes + u'\n\n'  + _('---Notes sent by confirm Order Form---') + u'\n' + request.POST['note']
            notes = u"%s \n\n%s \n %s" % (notes,  _('---Notes sent by confirm Order Form---'), request.POST['note'])
            log.debug("Saved order notes from Confirm Order Page")    
        
        # If I must add some notes to my order
        if notes_changed:
            order.notes = notes
            order.save()
        
        for item in order.orderitem_set.filter(product__subscriptionproduct__recurring=True, completed=False):
            item.completed = True
            item.save()


        for cart in Cart.objects.filter(customer=order.contact):
            cart.empty()

        # I remove the token from the session
        request.session['paypal_express_token']   
                
            #order.save()
                    
    #except:
    #        log.exception(''.join(format_exception(*exc_info())))
    #        assert False

    url = urlresolvers.reverse("PAYPAL_EXPRESS_satchmo_checkout-success")
    return HttpResponseRedirect(url)     
Example #24
0
def ipn(request):
    """PayPal IPN (Instant Payment Notification)
    Cornfirms that payment has been completed and marks invoice as paid.
    Adapted from IPN cgi script provided at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/456361"""

    payment_module = config_get_group('PAYMENT_PAYPAL')
    if payment_module.LIVE.value:
        log.debug("PayPal IPN: Live IPN on %s", payment_module.KEY.value)
        url = payment_module.POST_URL.value
    else:
        log.debug("PayPal IPN: Test IPN on %s", payment_module.KEY.value)
        url = payment_module.POST_TEST_URL.value
    PP_URL = url

    try:
        data = request.POST
        log.debug("PayPal IPN: Data: " + repr(data))
        if not confirm_ipn_data(data, PP_URL):
            return HttpResponse()

        try:
            invoice = data['invoice']
        except KeyError:
            invoice = data['item_number']

        if 'payment_status' not in data or not data[
                'payment_status'] == "Completed":
            # We want to respond to anything that isn't a payment - but we won't insert into our database.
            order = Order.objects.get(pk=invoice)
            if data['payment_status'] == "Pending":
                notes = "Pending Reason: %s" % (data['pending_reason'])
            else:
                notes = ""
            order.add_status(status=data['payment_status'], notes=(notes))
            log.info(
                "PayPal IPN: Ignoring IPN data for non-completed payment.")
            return HttpResponse()

        gross = data['mc_gross']
        txn_id = data['txn_id']

        log.info("PayPal IPN: Set %s to Processing" % txn_id)
        if not OrderPayment.objects.filter(transaction_id=txn_id).count():
            # If the payment hasn't already been processed:
            order = Order.objects.get(pk=invoice)
            order.freeze()
            order.add_status(status='Processing',
                             notes=_("Paid through PayPal."))
            payment_module = config_get_group('PAYMENT_PAYPAL')
            record_payment(order,
                           payment_module,
                           amount=gross,
                           transaction_id=txn_id)

            # Track total sold for each product
            log.debug("PayPal IPN: Set quantities for %s" % txn_id)
            for item in order.orderitem_set.all():
                if item.stock_updated is False:
                    product = item.product
                    product.total_sold += item.quantity
                    product.items_in_stock -= item.quantity
                    product.save()

                    item.stock_updated = True
                    item.save()
                    log.debug("PayPal IPN: Set quantities for %s to %s" %
                              (product, product.items_in_stock))

            if 'memo' in data:
                if order.notes:
                    notes = order.notes + "\n"
                else:
                    notes = ""

                order.notes = notes + _(
                    '---Comment via Paypal IPN---') + u'\n' + data['memo']
                log.debug("PayPal IPN: Saved order notes from Paypal")

            for item in order.orderitem_set.filter(
                    product__subscriptionproduct__recurring=True,
                    completed=False):
                item.completed = True
                item.save()
            for cart in Cart.objects.filter(customer=order.contact):
                cart.empty()

            order.save()
    except:
        log.exception(''.join(format_exception(*exc_info())))

    return HttpResponse()