Paypal with Orchard?

Topics: General
Apr 9, 2011 at 4:38 PM

Has anyone integrated Paypal into an Orchard site?

If so, do you have any tips and/or tricks to share?

Thanks.

Apr 9, 2011 at 5:12 PM

I did an MVC3 PayPal integration just recently but not in Orchard. I was thinking of making a module from it soon but I need to finish up a few other things before I start anything new :)

One thing to be aware of, is I ended up having to support both callback methods (PDT and IPN). PDT will work instantly if the user clicks the "return to website" button at the end of their transaction. But if they just close the browser, IPN will at some point wire a message through to your site to notify you it got completed. I think it's supposed to stand for Instant Payment Notification but sometimes it's far from instant :)  So yeah, for optimal user experience you need both.

Also I don't know if you're aware of the PayPal Sandbox but it's a developer playground that lets you easily simulate live orders and accounts for testing purposes.

Are you looking to release this as a module? I could perhaps dig out my controller / view code to share...

Apr 9, 2011 at 5:31 PM

BTW I'm going out soon so I don't think I could get you any code today (need to just go through and strip out anything specific to the website I wrote it for). But it's basically a working and tested implementation, I think all you'd need to add would be Orchard specifics like parts and settings.

Apr 9, 2011 at 6:18 PM

Thanks for the information and yes, I always like to look at code ;-)

I have a client that will be running a website with training videos available to members only. They want to be able to have users signup for a period of time and then handle renewals. Oviously this involves more that just Paypal integration, but one needs to start somewhere.

I rather suspect that this type of paid membership management with "members only" pages will be a common use case and hopefully in the future there will be a module (or perhaps rolled into the core) that handles it.

Right now I am just trying to get started for this client.

Apr 9, 2011 at 6:38 PM

I can't really imagine that ending up in core - not enough of a general case scenario. Perhaps a much more generalised "payment providers" would be more likely; but even then, that's not really where Orchard is coming from - it's primarily a CMS and core features are just focused around that and extensibility.

But, it'd be nice to see an extensible payment providers system as a third party module, that different gateways could then be plugged into.

Anyway; the code I've got handles all the PayPal callback integration which is the main tricky bit, and it's all MVC actions so you could more or less copy and paste with a bit of tweaking.

Seeing what you're using it for it'd be harder to implement cleanly as a generic "PayPal payments" module - I was thinking more of the shopping cart case where you could have a PayPal part you add to a product content type. You could still try and work it that way so customers are basically buying a Membership product.

What I guarantee will be tricky is the "members only" pages as the current permissions model won't support this, you'll need to write your own controller and apply permissions there.

One of the other things I started working on is a Moderations module to try and achieve situations like per-item access permissions but there are some changes needed in core before I can do that effectively.

Now, when you say "hopefully in the future there will be a module", perhaps you could consider implementing your membership system as a module and releasing that yourself? ;)

Apr 11, 2011 at 12:55 AM

OK, lets see if it is possible to simplify what I want to do. Basically I just want to be able to let someone subscribe for a fixed period of time for a fixed price. To handle the initial part of the transaction I should be able to do this with a static HTML button on the website, correct? Something like "to subscribe for 1 year at $19.95 click here".

By default, I could simply have PayPal send me an email confirming that the user has paid. Of course I would like something better, one step up if you will. That is why I would want PDT and/or IPN, also correct?

Now since I can handle a slight delay, say an hour, before the user gets a confirming email from me and access to the site, will IPN be fast enough?

What I want to do when PayPal tells me the user paid is update a database and send an email. I don't need to display anything on a webpage at that point. Because of this does it seem appropriate to handle the IPN notification independent of Orchard?

Finally I ran across this article http://www.west-wind.com/presentations/paypalintegration/paypalintegration.asp describing how to to deal with PayPal (including IPN) in classic ASP.Net. Does the portion of the code that handles IPN look reasonable to you?

Thanks again for all your help.

Apr 11, 2011 at 1:48 AM

With a normal static HTML button you'll get an email from PayPal anyway when someone pays. But yeah you really want to have your website automatically notified of this so you can handle it in your application without having to go and do it manually yourself every time.

With IPN, you give PayPal a "callback URL" so it can ping your website with confirmation of the transaction.

So you need to set up that URL. The standard way to do such a thing in MVC / Orchard is with a controller action.

The Rick Strahl article looks reasonable but actually I'm not sure how he's receiving the callback and it looks perhaps a lot more complicated that it needs to. MVC actions are pretty easy.

Now, why do I say PDT is also necessary?

Well, when your user has completed the payment they get a button saying "return to the website" or something like that. At this point they're redirected back to a page on your website that will say something like "your transaction has been completed, please wait for an email confirmation".

The problem with just doing this is that:

- The user gets no immediate feedback that everything has gone OK

- There could actually have been a problem with payment, like their card failing. In this instance the user has no obvious way to try paying again; they'll simply wait for the email at which point they have to go back onto your site and go through the process again. This isn't totally user-friendly and it'd be better to have a proper handling page that tells them if everything has gone through, and if not gives them an option to try again.

PDT works by letting your website ping PayPal itself to see if the order was processed. So this can happen at the time the user lands back on your site.

Of course it's possible they just closed the browser instead of clicking "return to the website" so you still need IPN to handle that instance.

IPN is sometimes instant but can sometimes take while (minutes up to hours).

So it's up to you how much of this you implement but it's not hard to do both; I did the majority of it in an afternoon. And I'm offering you almost the entire code to achieve this so that should make it practically trivial? ...

Developer
Apr 17, 2011 at 2:23 PM

Hi!

Pete, could I ask for the pieces of code you wrote too?:)

I have to write a PayPal integration module for my Orchard-based project, but I'm not much into the PayPal-related stuff (and I'm very short on time...) so would be great to see how you did that. I'd wrap that in a module (and publish in the Gallery with appropriate credits ofc:). Have you been working with the PayPal Helpers library for MVC3 maybe?

About writing a generic payment provider's infrastructure - it would be very cool thing to have. I guess I'll end up with sth like this in couple of weeks. I'm currently in the process of building a commercial project with quick payments capability (by couple of local, Polish payment providers).

Btw - Thanks John for pointing me to this discussion thread:)

Cheers, Piotr

Apr 17, 2011 at 4:24 PM

Perhaps we could get this going on codeplex as an open source project?

I suspect that as time goes on there will be lots of interest in using Orchard for e-commerce and donations.

Developer
Apr 17, 2011 at 5:25 PM
Edited Apr 17, 2011 at 5:33 PM

Sounds like a great idea!

Apr 17, 2011 at 5:39 PM

I'd be happy to do this as a codeplex project. Amusingly when I started going thru the code there was a comment saying "TODO: Wrap this up in a module!" (that was from before I started using Orchard)

I wasn't using the paypal helpers; I based it off an example at codeproject and rewrote as a controller - it wasn't too hard, just a couple of actions. I'm a bit tied up at the moment but I'll try and extract the code and get it you as soon as I can.

Apr 18, 2011 at 4:34 PM
Edited Apr 18, 2011 at 4:37 PM

@pszmyd - sent it to your email. @Jonny - contact me thru codeplex and I'll email it you as well. I don't know which of you wants to set up the codeplex project :)

Developer
Apr 18, 2011 at 5:50 PM

Thanks, got it! Gonna check the code later today and wrap it up in a module. I'll try to do something more generic, so other payment providers would be easy to add as well. I will setup the project on Codeplex and add you guys as admins, ofc.

Cheers

Apr 18, 2011 at 5:55 PM

Cool! Would be great to have something like a ProductPart or PricePart which you can add to content, and then separately choose which payment providers you install.

It can then be extended in other ways e.g. product variations, stock module, related items (this would be pretty easy with my relationships module). 

Developer
Apr 18, 2011 at 6:27 PM

Exactly! I thought about creating simple cart-based commerce module with parts like:

  • CartPart (as a base part for ShoppingCart type) for holding products selected by user (IDs or something) - as a container maybe. I guess persisting a user cart in DB would be a good idea and would fit perfectly into Orchard content-item-based architecture.
  • ProductPart - containing info about product - SKU, Price, Currency, DisplayName. It was implemented by Orchard Team for MIX11 (in Commerce module), so I'll grab that from the Gallery. For the simple implementation a single-currency product price is ok, I guess. If I find more time, I will implement a PriceField, so more prices (in different currencies) could be attached to a single product
  • PayablePart - it would attach a checkout button/link to content items (eg. to the ShoppingCart), which will point to the CheckoutController action.

The checkout controller would then render a payment method list based on the existing providers (eg. PayPal button).

These are just my thoughts - if you have your own ideas (or I'm maybe missing something), please post them:)

Cheers!

 

Apr 18, 2011 at 7:34 PM

Multiple currencies could be tricky; the simplest way would be to have a table of conversion rates and automatically convert the prices depending which country the users selects (possibly tied in with localization?)

Then there's issues like postage which get more complicated :)

I'm thinking a ShoppingCartWidget would  be a nice feature to display a summary of items with a checkout button in whatever zone.

One possible gotcha with implementing the ShoppingCart as a Content Item like you describe is that it creates a security hole; anyone can view any content with the current permissions model, so you could find other people's baskets just by randomly trying Id numbers. Might be better to just have the cart as a separate table and implement proper security on the controller. Gives us tighter control over it as well; you don't really want people sporadically adding parts to the shopping cart - I mean, why would you want a BodyPart or Ratings on your ShoppingCart for instance?

Instead we can simply generate a ShoppingCart shape in the controller, and that does the display work; then it's easy for payment providers to hook in (thru shape table etc.) and add their own buttons. So you can have each payment provider adding its own view to the checkout page, and they pull in the price and list of items from the ShoppingCart shape. Been digging around in the shape code and trust me it will work ;)

Developer
Apr 18, 2011 at 11:04 PM
  1. Multiple payments - I agree. This could be implemented as a content part as well. Such part would provide the price in appropriate currency based on a given exchange rates table. Automatic conversion - I'd rather (or in addition) give the user an option to choose the currency.
  2. Cart - right, I agree that this would create a security issue. The better option would be to weld the CartPart onto User type, so that each user would have his own, persisted shopping cart (at this point implementing multiple carts isn't a showstopper). Next, I'd add a CartWidgetPart, which would render the current user's basket in a widget (so there would be no option to hijack other users' baskets). It would be the easiest way to do that, I guess.
  3. Yes, the technique you wrote about is nice:) Maybe each provider should have a Shape property? In the checkout controller we'd be able to merge all those given shapes with some other shape responsible for displaying the checkout screen and display the merged result. But I wonder if it's not an overcomplication?

Cheers!

 

Apr 18, 2011 at 11:54 PM

1. Yes it'd be nice to have both options. I've seen a lot of business scenarios where people have slightly different prices in different countries; but I think for someone who just wants to set up a simple web shop they'll only want to enter prices in their own currency, and automatic conversion would be a nice added bonus that they wouldn't have to spend time setting up for each and every product.

2. It'd be convenient having the cart attached to the User; but this means that an unauthenticated user can't have a cart - the User object is null until you're logged in. Forcing someone to register isn't such a good idea :)

3. It's probably simpler than that. The controller just has to build a shape; for instance we'll call it CartCheckout. That's just a simple call to the shape factory. Then anyone and anything can hook into the various shape table events to add additional shapes or alter the existing ones. We can create an abstract base class, very similar to ContentPartDriver - and we should probably follow that naming scheme and call it PaymentGatewayDriver for example - this abstract class will have an override method where either you return DriverResult objects, or maybe just have access to a ShapeDisplayContext. We can add helper methods making it easy to build shapes geared towards the payment stuff but it's all pretty easy anyway and follows the ContentPartDriver concepts that people are used to. Like I say I've been looking into this because I want to use this kind of system in other stuff I'm doing. Orchard makes it easy, and of course you get all the additional free extras like Placement and Shape Tracing (well ... some things are still somewhat confusing there but I'm gradually understanding it all!). So the important thing is you don't actually need Parts to compose shapes and templates; Parts are just a default mechanism for adding stuff to Content Item shapes but there are lots of other ways that shapes can be played with ... and I haven't even started looking yet at what might be possible with Clay behaviors :)

Jun 3, 2011 at 6:46 PM

I had a question...can paypal be placed into Orchard?

I am new to all of this CSM, and building a website for a nonprofit organization. The organization is afterschool program.

With their web site, they want to have a paypal so people can visit, make donations, and have parents pay fees.

I was just curious before I begin using Orchard.

Developer
Jun 3, 2011 at 7:01 PM

Integrating a PayPal button (eg. donations) can be pretty easy. Just create your own button on PayPal site and display it eg. using Html Widget. If you are thinking about more complex solution - paying via PayPal for some orders and keep track of them - it's more challenging as you'd have to implement the whole workflow. I'm going to create a payments module for such scenarios in next two/three weeks.

Jan 17, 2012 at 4:23 AM

Hey pszmyd, did you ever get around to doing the above ^ . Cheers Dyr

Feb 21, 2012 at 9:02 PM

Hi pszmyd, did you manage to create the payment module using paypal?

Developer
Feb 22, 2012 at 2:26 AM

Unfortunately, I haven't. I'm still planning it, but don't really have time for that now...

Coordinator
Feb 22, 2012 at 2:30 AM

I'm looking at it right now actually as part of a commerce module I'm building for my own needs. I already have Google Checkout running, and I'll add PayPal eventually. I'll release the module with Orchard 1.4 at the end of this month, but it may not have PayPal at launch.

Jun 6, 2012 at 8:48 AM
Edited Jun 6, 2012 at 8:52 AM

Hi Bertrand, do you still plan to implement Paypal or some kind of payment provider ? I just installed nwazet commerce and planning to use it for my own site. I looked at Rob Conery's Paypal implementation in MVC Storefront and thought I could start from here to put my hands on creating a module.

Pierre

Coordinator
Jun 8, 2012 at 6:47 AM
Edited Jun 8, 2012 at 6:48 AM

Yes, but I don't know when so if you want to contribute it, I'll gladly take it. But you are confusing me when you say "or some kind of payment provider": the module already supports one, Google Checkout.

Jun 8, 2012 at 10:35 AM

Yes, in the context I meant a payment provider as an Orchard component that would allow the admin to choose several payment methods, to let the final user select one from them.

Idealy I should be able to develop a payment module as an extension of nwazet commerce from a "Sample payment module" which implements a few interfaces. ( as you have an IShippingMethod, there could be an IPaymentMethod...) The challenge is to provide a model that fits to any payment workflow.

Coordinator
Jun 9, 2012 at 5:51 AM

That's already in there.

Sep 22, 2012 at 1:01 AM

Just linking similar posts together.  I have the exact same need as this thread.

http://orchard.codeplex.com/discussions/396475

Sep 27, 2012 at 7:09 PM

Hello Everyone,

I built off of Nwazet.Commerce (thanks Bertrand) and added a module to accomplish a lot of what you need - including PayPal!  It includes PayPal Instant Payment Notification, a purchase History, and the ability to associate role assignment with a product - real nice for when you are selling access rights to content on your website.

https://orchardcommercehstry.codeplex.com/

I will be using this in a live site shortly and be keeping this module up to date - your feedback is welcome so it can be a great module.  Documentation will improve over time but if you can figure out Nwazet.Commerce should be all set with starting out with the above module.  When you find bugs (and you likely will), please let me know.

I will also start a new thread on this as I believe there will be interest (I am hoping) from others trying to make Orchard a great eCommerce solution.

 

Coordinator
Sep 28, 2012 at 6:00 AM

Sounds cool, but why didn't you contribute to Nwazet.Commerce?

Sep 28, 2012 at 11:34 AM

Hi Bertrand,

Ah, the continual tension, when should I add to a module versus extend an existing module - that is a full discussion on it's own.

You set up Nwazet.Commerce very well to be extended and I really wanted to see how well modules could work together even though they are independent of each other - surprisingly very well. The other consideration I always have is what if the current module developer does not want to pull in code from others. Seems that is not the case. I personally feel every one of the features wrapped up in my module being of value to anyone wanting a commerce solution (i.e. I feel they are core) and if you agree, I will drag all the features in under Nwazet.Commerce and do a pull request. Just did not want to clutter up your Commerce solution if what I have defined is too specific - look forward to your reply. I really want to see Orchard be great at eCommerce.

Coordinator
Sep 30, 2012 at 9:42 PM

Well, you could have created a fork of the module, on Bitbucket. That would not have required any permission from me, but it would have left the door open for integration of your changes into the main module, or it could have lived in that fork forever. It would also have made it easy for you to integrate changes from the main repo. In the end it's your choice, was just wondering if you considered that option. I'll be happy to consider your pull request, thanks!

Oct 17, 2012 at 6:24 PM

Yes, you are correct, forking is the way to go and I have migrated and grown my solution on this url: https://bitbucket.org/ems/nwazet.commerce

Here are the additional features I have added so far:

	Nwazet.History:
		Name: Nwazet History
                  Description: Provides order history tracking for Nwazet Commerce (for logged in users who purchase with PayPal)
		Category: Commerce
		Dependencies: Nwazet.Commerce, Orchard.Fields
	Nwazet.RoleAssignment:
		Name: Nwazet Role Assignment
		Description: Provides for the assignment of user roles based on confirmed purchases
		Category: Commerce
		Dependencies: Nwazet.Commerce
	Nwazet.PayPal:
		Name: Nwazet PayPal
		Description: Provides PayPal order clearing and pushing to Nwazet History
		Category: Commerce
		Dependencies: Nwazet.Commerce
	Nwazet.Promotion:
		Name: Nwazet Promotion
		Description: Provides ability to offer promotions by Percentage Discount or Currency Discount
		Category: Commerce
		Dependencies: Nwazet.Commerce, Orchard.ArchiveLater

 In addition, I have expanded the core product set with the following:

  • A "MinimumOrderQuantity" requiring the user to purchase so many items.
  • A base "Discounts" support to the core Nwazet.Commerce to support extenstion points off of (such as the Nwazet.Promotion feature).
    • I suspect there will be a day when someone will want to provide a promotion based on a userID, this could easily extend off of the base "Discounts" to provide another feature (and leave Promotions as is).

The module I am working to improve right now is Nwazet.Promotion, the rest I have tested out and are working very well. My goal is to be able to provide promotions / discounts on the product level and the cart level, right now it is just cart level.

I have never done a pull request but will be trying it out in the future. My concern is that I should have been doing pull requests on one feature at a time to make it easier for you to incorporate as you see fit - guess that problem is on your plate if you want these being "core". If you have any advice on best practices (or a better place to document this stuff for future users of the commerce module) let me know.

Coordinator
Oct 17, 2012 at 6:36 PM

I may take things in myself bit by bit, yes. Probably starting with PayPal. Thanks!