Great write-up Jeremy, thanks a lot for sharing that.

The art rebellion site looks great too!


On Wed, Apr 16, 2014 at 10:27 AM, Jeremy Epstein <jazepst...@gmail.com>wrote:

> I've published a more detailed write-up of the process I went through,
> you can find it here:
>
>
> http://greenash.net.au/thoughts/2014/03/using-paypal-wps-with-cartridge-mezzanine-django/
>
> Luc, looking forward to reading more details about how you went about
> it too. And I'm sure other devs would also appreciate it - then
> they'll have several options to choose from, for implementing PayPal
> WPS with Cartridge.
>
> I think that both approaches have their disadvantages. With mine,
> there's code repetition - I copied the code from Cartridge's order
> complete method and modified it. With yours, Luc, there's a fake
> request object being used.
>
> Ideally, the architecture of Cartridge's order completion system will
> be modified for the better, such that (a) it can be called easily from
> an external code snippet like a PayPal IPN callback, and (b) it's
> de-coupled from the request, and there's no need to use a fake request
> object. That way, both of our hacks / solutions will become
> unnecessary.
>
> Cheers,
> Jeremy.
>
> On Mon, Jan 27, 2014 at 6:49 PM, Luc Milland <l...@hekenet.com> wrote:
> > Hello,
> > awesome, I eventually ended with something *very* similar.
> > I was planning to expose my solution after the shop I am working on is
> > finished (I am very late on this project).
> > I made a lot of other changes and will have some suggestion to improve
> > Cartridge.
> >
> > Regarding, the external payment stuff, we basically made the *same
> > thing* : using signal in my_app/models.py, retrieve order through ipn
> > stuff (I used order_uuid alone since I don't really now if it's a good
> > idea to let session keys travel through requests) and close the order.
> > to close the order, I did not mimic order.complete() code, but I call
> > the original code through a fake request. It's something like :
> >
> > fake_request = HttpRequest()
> > fake_request.session = session
> > fake_request.cart = cart
> > order.complete(fake_request)
> > session.save()
> >
> > I tried to implement some kind of IPN order status handling to complete
> > order only when status == "Completed" and not "Pending", and to trap
> > error to (for now, any other IPN status than completed or pending leads
> > to cancel the order).
> >
> > E-mails are sent on order complete or cancel.
> >
> > Besides, I use signals on order status transitions to have mail sent
> > automatically.
> >
> > Finally, I wrote a little app to handle shipping services but I will
> > expose this later, since it's a whole subject and would require some
> > more code to be really usefull (basically, I would need another checkout
> > step to handle shipping service choice).
> > This is called ponyexpress and it allows to define shipping services
> > through admin. Each shipping service is associated to destination zones
> > (countries, for now) which are bound to price ranges depending on
> > weight.
> > Adding a weight field to ProductVariation then allow to calculate
> > shipping cost automatically for the chosen service, depending on
> > customer country.
> > While no order is made, the customer country is guessed from IP so an
> > estimated shipping cost can be provided in the shopping cart.
> > I find this pretty cool :)
> >
> > I will publish this code and discuss it as soon as I have finish the
> > shop I am working on.
> >
> > hope that will help too !
> >
> > Luc
> >
> > Le dimanche 26 janvier 2014 à 19:04 -0800, Jeremy Epstein a écrit :
> >> Hi,
> >>
> >> I've just finished building a site powered by Mezzanine / Cartridge, and
> >> I've managed to integrate it with PayPal WPS (i.e. after completing
> >> checkout, user is redirected to PayPal for payment, no SSL cert needed
> on
> >> the site).
> >>
> >> I'm going to do a more detailed write-up when I get the chance - but for
> >> now, here's roughly what I did to cover the all-import "final missing
> step"
> >> that's being discussed in this thread:
> >>
> >> 1. Install cartridge-payments and django-paypal, make sure they're
> enabled:
> >>
> >> INSTALLED_APPS = [
> >>     # ...
> >>     "payments.multipayments",
> >>     "paypal.standard.ipn",
> >>     # ...
> >> ]
> >>
> >> (follow other steps in the install instructions for these apps, I'm not
> >> going to go through it all here).
> >>
> >> 2. Make sure you set PAYPAL_IPN_URL as follows:
> >>
> >> PAYPAL_IPN_URL = lambda cart, uuid, order_form:
> >> ('paypal.standard.ipn.views.ipn', None, {})
> >>
> >> 3. Place the following code somewhere in your codebase (per the
> >> django-paypal docs, I placed it in the models.py file for one of my
> apps):
> >>
> >> # ...
> >>
> >> from importlib import import_module
> >>
> >> from mezzanine.conf import settings
> >>
> >> from cartridge.shop.models import Cart, Order, ProductVariation,
> >> DiscountCode
> >> from paypal.standard.ipn.signals import payment_was_successful
> >>
> >> # ...
> >>
> >>
> >> def payment_complete(sender, **kwargs):
> >>     """Performs the same logic as the code in
> >> cartridge.shop.models.Order.complete(), but fetches the session, order,
> and
> >> cart objects from storage, rather than relying on the request object
> being
> >> passed in (which it isn't, since this is triggered on PayPal IPN
> >> callback)."""
> >>
> >>     ipn_obj = sender
> >>
> >>     if ipn_obj.custom and ipn_obj.invoice:
> >>         s_key, cart_pk = ipn_obj.custom.split(',')
> >>         SessionStore =
> import_module(settings.SESSION_ENGINE).SessionStore
> >>         session = SessionStore(s_key)
> >>
> >>         try:
> >>             cart = Cart.objects.get(id=cart_pk)
> >>             try:
> >>                 order =
> Order.objects.get(transaction_id=ipn_obj.invoice)
> >>                 for field in order.session_fields:
> >>                     if field in session:
> >>                         del session[field]
> >>                 try:
> >>                     del session["order"]
> >>                 except KeyError:
> >>                     pass
> >>
> >>                 # Since we're manually changing session data outside of
> >>                 # a normal request, need to force the session object to
> >>                 # save after modifying its data.
> >>                 session.save()
> >>
> >>                 for item in cart:
> >>                     try:
> >>                         variation =
> >> ProductVariation.objects.get(sku=item.sku)
> >>                     except ProductVariation.DoesNotExist:
> >>                         pass
> >>                     else:
> >>                         variation.update_stock(item.quantity * -1)
> >>                         variation.product.actions.purchased()
> >>
> >>                 code = session.get('discount_code')
> >>                 if code:
> >>
> DiscountCode.objects.active().filter(code=code).update(
> >>                         uses_remaining=F('uses_remaining') - 1)
> >>                 cart.delete()
> >>             except Order.DoesNotExist:
> >>                 pass
> >>         except Cart.DoesNotExist:
> >>             pass
> >>
> >> payment_was_successful.connect(payment_complete)
> >>
> >> 4. Apply some hacks to cartridge-payments and django-paypal:
> >>
> >> a) lib/python2.7/site-packages/payments/multipayments/forms/paypal.py
> >> modify per diff at:
> >>
> >>
> https://github.com/django-mezzanine-paypal/cartridge-payments/commit/6446f09832135e10ebae5cf10c573cafd3607b9b
> >>
> >> b) src/django-paypal/paypal/standard/forms.py modify per:
> >>
> >> http://stackoverflow.com/a/16804992/2066849
> >>
> >> I think that's about it - will test more thoroughly and will re-create
> when
> >> I do a better write-up. But basically, with this, the PayPal IPN
> callback
> >> does everything that cartridge.shop.models.Order.complete() would
> usually
> >> do, if it got called (which it doesn't if you're using PayPal WPS, and I
> >> believe also PayPal EC).
> >>
> >> Hope that helps you guys for now.
> >>
> >> Jeremy.
> >>
> >> On Thursday, November 14, 2013 2:08:30 AM UTC+11, Luc Milland wrote:
> >> >
> >> > Hello,
> >> > I am trying to make a shop with cartridge but I don't want to deal
> with
> >> > credit cards.
> >> > That's why I want to use cartridge-payment with Paypal express
> checkout
> >> > (payment part only, if I understand well).
> >> > Using sandbox paypals accounts and cartridge-payment readme, I can
> make
> >> > an order, pay it and be sent back to the shop at
> >> > shop/checkout/complete .
> >> > But there is my problem : the order is registred, but not completed. I
> >> > mean that it looks as the final checkout step did not apply (I guess
> it
> >> > is because the checkout form is sent to paypal and to our good old
> >> > checkout_step view, right ?) and as order.complete(request) was never
> >> > called.
> >> > As a result, cart is not empty, etc...
> >> > Does anybody had already been there ? Did I miss something ? Is there
> a
> >> > way to jump back in the checkout workflow, maybe with Paypal IPN ?
> >> >
> >> > thanks for your ideas and many thanks to all who build this awesome
> >> > piece of code that mezzanine/cartridge is.
> >> >
> >> > Luc
> >> >
> >> >
> >> On Thursday, November 14, 2013 2:08:30 AM UTC+11, Luc Milland wrote:
> >> >
> >> > Hello,
> >> > I am trying to make a shop with cartridge but I don't want to deal
> with
> >> > credit cards.
> >> > That's why I want to use cartridge-payment with Paypal express
> checkout
> >> > (payment part only, if I understand well).
> >> > Using sandbox paypals accounts and cartridge-payment readme, I can
> make
> >> > an order, pay it and be sent back to the shop at
> >> > shop/checkout/complete .
> >> > But there is my problem : the order is registred, but not completed. I
> >> > mean that it looks as the final checkout step did not apply (I guess
> it
> >> > is because the checkout form is sent to paypal and to our good old
> >> > checkout_step view, right ?) and as order.complete(request) was never
> >> > called.
> >> > As a result, cart is not empty, etc...
> >> > Does anybody had already been there ? Did I miss something ? Is there
> a
> >> > way to jump back in the checkout workflow, maybe with Paypal IPN ?
> >> >
> >> > thanks for your ideas and many thanks to all who build this awesome
> >> > piece of code that mezzanine/cartridge is.
> >> >
> >> > Luc
> >> >
> >> >
> >>
> >
> >
> > --
> > You received this message because you are subscribed to a topic in the
> Google Groups "Mezzanine Users" group.
> > To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/mezzanine-users/n2d6SODIF1o/unsubscribe.
> > To unsubscribe from this group and all its topics, send an email to
> mezzanine-users+unsubscr...@googlegroups.com.
> > For more options, visit https://groups.google.com/groups/opt_out.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Mezzanine Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to mezzanine-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
Stephen McDonald
http://jupo.org

-- 
You received this message because you are subscribed to the Google Groups 
"Mezzanine Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mezzanine-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to