Example #1
0
    def post(self, request, *args, **kwargs):
        """
        Place an order.

        We fetch the txn details again and then proceed with oscar's standard
        payment details view for placing the order.
        """
        if buyer_pays_on_paypal():
            return HttpResponseBadRequest(
            )  # we don't expect any user here if we let users buy on PayPal

        try:
            self.payer_id = request.POST['payer_id']
            self.token = request.POST['token']
        except KeyError:
            # Probably suspicious manipulation if we get here
            messages.error(self.request, self.error_message)
            return redirect('basket:summary')

        try:
            self.txn = fetch_transaction_details(self.token)
        except PayPalError:
            # Unable to fetch txn details from PayPal - we have to bail out
            messages.error(self.request, self.error_message)
            return redirect('basket:summary')

        # Reload frozen basket which is specified in the URL
        basket = self.load_frozen_basket(kwargs['basket_id'])
        if not basket:
            messages.error(self.request, self.error_message)
            return redirect('basket:summary')

        submission = self.build_submission(basket=basket)
        return self.submit(**submission)
Example #2
0
    def get(self, request, *args, **kwargs):
        """
        Fetch details about the successful transaction from PayPal.
        We use these details to show a preview of the order with a 'submit' button to place it.
        The preview step can be skipped with `PAYPAL_BUYER_PAYS_ON_PAYPAL=True` inside settings.
        """
        try:
            self.payer_id = request.GET['PayerID']
            self.token = request.GET['token']
        except KeyError:
            # Manipulation - redirect to basket page with warning message
            logger.warning("Missing GET params on success response page")
            messages.error(self.request,
                           _("Unable to determine PayPal transaction details"))
            return redirect('basket:summary')

        try:
            self.txn = fetch_transaction_details(self.token)
        except PayPalError as e:
            logger.warning(
                "Unable to fetch transaction details for token %s: %s",
                self.token, e)
            messages.error(self.request, self.error_message)
            return redirect('basket:summary')

        # Reload frozen basket which is specified in the URL
        kwargs['basket'] = self.load_frozen_basket(kwargs['basket_id'])
        if not kwargs['basket']:
            logger.warning("Unable to load frozen basket with ID %s",
                           kwargs['basket_id'])
            messages.error(
                self.request,
                _("No basket was found that corresponds to your PayPal transaction"
                  ))
            return redirect('basket:summary')

        if buyer_pays_on_paypal():
            return self.submit(**self.build_submission(
                basket=kwargs['basket']))

        logger.info(
            "Basket #%s - showing preview with payer ID %s and token %s",
            kwargs['basket'].id, self.payer_id, self.token)

        return super(SuccessResponseView, self).get(request, *args, **kwargs)
Example #3
0
def get_paypal_url(basket,
                   shipping_methods,
                   user=None,
                   shipping_address=None,
                   shipping_method=None,
                   host=None,
                   scheme=None,
                   paypal_params=None,
                   ccard=False):
    """
    Return the URL for a PayPal Express transaction.

    This involves registering the txn with PayPal to get a one-time
    URL.  If a shipping method and shipping address are passed, then these are
    given to PayPal directly - this is used within when using PayPal as a
    payment method.
    """
    if basket.currency:
        currency = basket.currency
    else:
        currency = getattr(settings, 'PAYPAL_CURRENCY', 'GBP')
    if host is None:
        host = Site.objects.get_current().domain
    if scheme is None:
        use_https = getattr(settings, 'PAYPAL_CALLBACK_HTTPS', True)
        scheme = 'https' if use_https else 'http'

    response_view_name = 'paypal-handle-order' if buyer_pays_on_paypal(
    ) else 'paypal-success-response'
    return_url = '%s://%s%s' % (scheme, host,
                                reverse(response_view_name,
                                        kwargs={'basket_id': basket.id}))
    cancel_url = '%s://%s%s' % (scheme, host,
                                reverse('paypal-cancel-response',
                                        kwargs={'basket_id': basket.id}))

    # URL for updating shipping methods - we only use this if we have a set of
    # shipping methods to choose between.
    update_url = None
    if shipping_methods:
        update_url = '%s://%s%s' % (scheme, host,
                                    reverse('paypal-shipping-options',
                                            kwargs={'basket_id': basket.id}))

    # Determine whether a shipping address is required
    no_shipping = False
    if not basket.is_shipping_required():
        no_shipping = True

    # Pass a default billing address is there is one.  This means PayPal can
    # pre-fill the registration form.
    address = None
    if user:
        addresses = user.addresses.all().order_by('-is_default_for_billing')
        if len(addresses):
            address = addresses[0]

    return set_txn(basket=basket,
                   shipping_methods=shipping_methods,
                   currency=currency,
                   return_url=return_url,
                   cancel_url=cancel_url,
                   update_url=update_url,
                   action=_get_payment_action(),
                   shipping_method=shipping_method,
                   shipping_address=shipping_address,
                   user=user,
                   user_address=address,
                   no_shipping=no_shipping,
                   paypal_params=paypal_params,
                   ccard=ccard)
Example #4
0
        name='paypal-cancel-response'),
    # Callback for getting shipping options for a specific basket
    url(r'^shipping-options/(?P<basket_id>\d+)/(?P<country_code>\w+)?',
        csrf_exempt(views.ShippingOptionsView.as_view()),
        name='paypal-shipping-options'),
    # View for using PayPal as a payment method
    url(r'^payment/',
        views.RedirectView.as_view(as_payment_method=True),
        name='paypal-direct-payment'),
]

buyer_pays_on_paypal_patterns = [
    url(r'^handle-order/(?P<basket_id>\d+)/$',
        views.SuccessResponseView.as_view(preview=True),
        name='paypal-handle-order'),
]

buyer_pays_on_website_patterns = [
    url(r'^place-order/(?P<basket_id>\d+)/$',
        views.SuccessResponseView.as_view(),
        name='paypal-place-order'),
    url(r'^preview/(?P<basket_id>\d+)/$',
        views.SuccessResponseView.as_view(preview=True),
        name='paypal-success-response'),
]

if buyer_pays_on_paypal():
    urlpatterns = base_patterns + buyer_pays_on_paypal_patterns
else:
    urlpatterns = base_patterns + buyer_pays_on_website_patterns