TrialPay Integration with IPN.NET

0

Posted by Cynic | Posted in C#, DotNetNuke, Online Marketing, Software, Solutions to Problems | Posted on 22-09-2011

Tags: , ,

TrialPayI’m slowly closing in on being able to release the new Photo Resizer Social Edition. It will feature 1-click photo uploading to Facebook, Flickr, and TwitPic/Twitter, but all that has been the easy stuff so far. The licensing and marketing side of it is where the real work is.

Building on how I integrated ILS and IPN.NET with DotNetNuke, I’m now adding in TrialPay to the licensing process. For those that don’t know TrialPay, it’s a fantastic idea from Alex Rampell, Terry Angelos and Eddie Lim who founded TrialPay in 2006. I first met them at SIC 2006 in Denver. (I think that was the last CoffeeCup party there as well.) I’d blogged about it here, and shortly thereafter got an email from Alex joking about how he was pissed that I was beating them in the search engines for “trialpay”. We got a kick out of that.

Anyways, TrialPay lets you present users with an option to purchase some product or service, and in return, give them a license for your software for free. It’s good for everyone all the way around. I’ve recommended it to other developers, and they’ve come back with positive stories about increased revenues.

TrialPay has a very good interface to integrate with different styles of licensing systems. As I’ve already got IPN.NET and ILS in place, it’s just a matter of hammering things around a bit to get things working right.

My last round of DNN/ILS/IPN.NET integration is running smoothly, and adding in TrialPay has had noadditional  impact on DNN, though it does have a significant impact on IPN.NET.

While I’ve tried to minimize the impact, I also need to spend my time wisely. As such, there’s a higher impact on IPN.NET than I would really like, but the time it has taken to do it wasn’t very much.

To integrate TrialPay with IPN.NET, there are a few things that need to be done. All of the integration-specific changes and set up from the TrialPay side are done on the “Product Delivery” page in the product configuration:

TrialPay Product Setup MenuOnce there, under “Activation Method”, choose the “Provide a unique key that I will generate” option. You need to have your IPN.NET URL ready for that as well.

TrialPay Activation Method - Unique Key I Generate

Most of the other settings are pretty straight forward, but you’ll want to make certain that you set up the parameters that TrialPay will POST to your IPN.NET instance. (Don’t use GET. That’s just a bad idea.) So, for example, you could have these parameters:

payer_email=%email%
first_name=%fname%
last_name=%lname%
item_number=ACME123

TrialPay gives you a huge amount of freedom to set up whatever you like. However, it is CRUCIAL that you pass a value for your item number (item_number) back to yourself. It MUST be the same as an existing item_number that’s already set up in IPN.NET. This will be the same as the item_number that you enter into License Tracker. (See my article on entering large numbers of products into License Tracker.)

The item_number is used by IPN.NET to create licenses, so, it’s just kind of a little bit important. ūüėČ However, see below for how to quickly hack this with the testing tool…

Once you have that set up, you can then move on to customizing your IPN.NET installation. You can get away with only 4 real changes:

  1. Add in a string member variable to contain the key for TrialPay
  2. Add in a ProcessPurchaseItem > ProcessTrialPayItem method
  3. Add in a SendNotificationEmail >SendTrialPayNotificationEmail method
  4. Add in some custom logic for TrialPay at the top of the Page_load method

IPN.NET has a huge amount of error checking, and even posts back to PayPal to verify license purchases. Now, you can work with this, but it’s a significant amount of effort, and has a massive impact on IPN.NET, so it might not be worth it to you. Instead, you can filter for TrialPay POSTs and then just run some custom logic and end there.

You can do that with minimal impact by adding that to the top of the Page_load event in IPN.NET. You can simply use an IpnData object to pull in the POST variables, but you’ll need to modify the IpnData class if you don’t use the same variable names. As such, it’s simpler to use the IPN.NET/PayPal variable in TrialPay, as you can see above.

The “ipn” IpnData variable is a member variable, so it has a global scope in Default.aspx.cs. You should set it something like this in the Page_load event:

ipn = new IpnData(Request.Form);

That then lets you reuse the “ipn” variable for TrialPay, and alleviates any need to rewrite basically everything.

Now, you’ll probably want to rewrite/tweak the ProcessPurchaseItem() and the¬†SendNotificationEmail() methods. The “log” variable is a member variable as well, and you’ll need to do a lot of rewriting if you want to use it. If you want to work with License Tracker for TrialPay purchases, then you’ll need to do a lot of that work as the log creates a logfile that gets emailed to you in IPN.NET normally. However, if you cut out the logging, it won’t get created, and you won’t be able to import it from Outlook with License Tracker. Yuck. That’s pretty complicated. So… Might as well take the quick and easy route…

Notably, IPN.NET does a POST back to PayPal for verification, and you can’t do that while using TrialPay. This happens in the Page_load event just before the¬†ProcessPayment() method call. The¬†ProcessPayment() call contains the¬†ProcessShoppingCartItems() and ProcessSinglePurchaseItem() method calls, which is where the actual licensing “work” gets done.

For TrialPay, I’m only interested in selling 1 license at a time, so I’m only concerned with the¬†ProcessSinglePurchaseItem() method. It contains the¬†ProcessPurchaseItem() method call, which as I’ve mentioned above, I’ve tweaked for TrialPay.

So, I’ve simply created a¬†ProcessTrialPayItem() and a¬†SendTrialPayNotificationEmail() method from the 2 mentioned above, then tweaked them for what I need, i.e. to send people their licenses and send me a quick and dirty email notification. You can open up the source code to see inside them. From what I’ve written here, it should be very simple for you to modify them similarly to what I have, or perhaps even more extensively, depending on your requirements.

Modifications for the¬†ProcessTrialPayItem() method basically boil down to commenting out the log calls, and the tweaks I’d previously made to integrate IPN.NET into DNN. Actually, this entire block can be deleted:

if (item.IsUpgrade)
{ … }
else if (!CartHasPrerequisiteItems(item))
{ … }
else if (BlockCustomerEmail())
{ … }

However, it doesn’t matter whether you delete it or not. None of those conditions will ever be satisfied except possible the BlockCustomerEmail() method call. However, there I would strongly recommend either deleting the entire contents of that file, or very carefully editing it. If you’re selling consumer level or professional level software, the chances are VERY high that many of your customers will have email address that would get blocked there. Not good.

Modifications for the¬†SendTrialPayNotificationEmail() method boil down to nothing. There’s a log check to see if it is null, but that can stay in.

Now, if you want to hack things up while testing with the Infralution IPN Test Tool, just set the product item_number something like this:

item.ItemNumber = “ACME123”;

You can add in some logic that draws on data from the TrialPay POST (if you have more than 1 product pointing to the same IPN.NET instance), but that’s not very hard to figure out. You just need to keep it straight with the Infralution IPN Testing Tool.

The issue there is that you can end up with “item_number1” when you’re expecting “item_number”. It can be remedied, but I’m quite frankly too busy/lazy to get on top of that one when I have zero reason to right now.

I can’t post much code as that is not a part of what I am allowed to do according to my Infralution source code license, but I can post a little bit. The following is some very brief logic for what you want to stick up at the top of your IPN.NET Page_load event:

// If we have a Trial Pay sale...
if (isTrialPay)
{
    // Recycle the "ipn" member variable:
    ipn = new IpnData(Request.Form);
    // Create an item for the TrialPay "purchase"
    PurchaseItem tpItem = new PurchaseItem();
    // Hack/fix the item number for the InfralutionIPN Testing Tool
    tpItem.ItemNumber = "ACME123"; // Used below
    // Now, get the item from your existing IPN.NET settings:
    tpItem = GetPurchaseItem(tpItem.ItemNumber);
    // Call the tweaked method to process the "purchase":
    ProcessTrialPayItem(tpItem, 1);
    // Send the license email to the customer:
    SendTrialPayNotificationEmail();
    // Clear the HTML body response but not the headers (should be 200):
    Response.ClearContent();
    // You must return the key to TrialPay in the HTML body.
    // "tpKeys" is a member variable that you set in the ProcessTrialPayItem() method above:
    Response.Write(tpKeys);
    // HTML markup is not valid for the response to TrialPay, so end the response and send it back:
    Response.End();
    return;
}

Now, you’ll need to figure out how you want to verify a TrialPay POST, as I’m not going to do that here. Just read their documentation and you’ll figure it out quickly enough.

You will also likely want to add in a bit more error checking and whatnot. I’ve cut things down there to the very basics as described above.

That’s about all there is to it though. I hope that serves as a good starting point for anyone that wants to integrate TrialPay sales into their Infralution IPN.NET system.

Cheers,

Ryan

P.S. If you want to find out more about TrialPay, click the button:

TrialPay Referral Program

The Licensing Experience with Infralution and DotNetNuke

0

Posted by Cynic | Posted in .NET, C#, Databases, DotNetNuke, Online Marketing, Software, Solutions to Problems, Super Simple, Web Sites | Posted on 20-09-2011

Tags: ,

I don’t think that I’ve ever done a licensing or purchasing flow exactly the same way twice. Well, a couple times, but mostly I experiment with both major changes and minor tweaks.

This time around for the Super Simple Photo Resizer Social Edition, I’m doing things more or less right. There are a few things that still could be improved, and a few things that I’m not really all that happy with, but like my friend Nick Longo says, “Release at 80%.”

However, overall, I think the current functional set that I’ve got mapped out for Photo Resizer Social Edition are pretty good, and will deliver a solid user experience. My goals on the user-experience side are:

  1. Make it easy to purchase
  2. Make it easy to get and enter the license
  3. Make it easy to get a lost license back

Each of those has a real upside for users, and an upside for me as well (respectively):

  1. I make more money
  2. Fewer support emails
  3. Fewer support emails

But I also have some other goals.

  1. Cut down on piracy
  2. Cut down on piracy
  3. Cut down on piracy

For a little guy like me, piracy hurts. Badly. It also hurts users, because it removes the financial incentive to continue development. You’d be surprised at just how many people like to get paid for their work, and how much they enjoy having food on the table and paying their bills. ūüėČ

I recently got an email from someone who purchased some other software that I write. This is part of that email:

I could have pirated the software if I wished as it is easy to crack which is something you need to work on, but I thought the software is so good that I would pay you the money for a genuine copy and support its future development.

I’m glad he bought a copy! It quite literally puts food on the table.

However, I don’t want to get into piracy here. Instead, I’d like to go over some of the things I’m doing with the new licensing scheme…

The flow looks something like this (click to zoom):

Super Simple Photo Resizer Social Edition Licensing Flow
Now, I’m leaving out a lot there because it would just be boring details, but that’s the basic flow.

The user gets 2 emails:

  1. PayPal receipt
  2. License email with account information

Now, in the past I’ve done licensing manually, which has been in many ways pretty easy, but it’s not been without its pain as well.

I’ve previously mentioned that I’m using the Infralution toolchain for licensing, but nothing is perfect “out of the box”, so I’ve done a good amount of customization. Having been burnt very badly in the past, I tend to purchase source code licenses whenever I can afford to. This leaves me the freedom to get down into things and tweak, fix, or just pimp-out stuff. Infralution offers source code along with their various products, which is another reason why I strongly recommend them to people whenever the topic of software licensing or payment integration arises.

I’ve also raved about how much I love DotNetNuke. It’s a fantastic CMS/portal written in ASP.NET (VB.NET in the past and now in C#), and comes with a BSDish license. However, I’ve been hesitant in the past to do much integration due to time constraints and other factors. However, this time around, I’m aiming to get things done more or less “right”.

Neither the Infralution ILS nor their IPN.NET integrate into DotNetNuke, so all of that is goodness that I need to take care of. Luckily, DotNetNuke is very well designed and integration isn’t really much of a problem. It’s really only a matter of getting it done and testing things out to make sure that they work. The trick is to try and make certain that I don’t step outside of the framework, and don’t create potential future issues for when I upgrade the DNN version. (Moving from DNN v2.1.2 to v3.x was a NIGHTMARE.)

ILS and IPN.NET take care of all the license generation and authentication, so the only thing needed is to get that into DNN. The relevant user-portion of the database is (click to zoom):

DotNetNuke Users Roles Database DiagramTo get ILS and IPN.NET working there, I needed to create 2 new entries in the database:

  • A Role for licensees
  • A ProfileProperty to store licenses

No new tables needed to be added, and no table modifications were needed. So, everything fits into DNN nice and cleanly.

A Note About the Database: When installing DNN, I would highly recommend using object qualifiers. These are prefixes for the database objects (tables, stored procedures, views), and will help to guarantee that well written modules that use them do not have conflicts. IPN.NET and ILS do not support object qualifiers, and have table names that could be used by other modules. As such, I’m very happy that I always stick with the wisdom of using object qualifiers because it’s made things much safer, and has allowed me the freedom to use the DNN database for the IPN.NET and ILS Authentication Server. Later on, this will let me create custom modules or do additional programming that let me access all user data in 1 place. The advantages here are never-ending.

When a user purchases a license through PayPal, PayPal then securely contacts my IPN.NET instance, and I then process the transaction by either updating the user’s existing profile, or creating a new user profile for the user and updating it with their new license information.

Since IPN.NET has no DNN integration, everything needs to work around that, and consequently, needs to be done at a low-level. Luckily,¬†the DNN community is quite large, and there’s a lot of code out there to help with very low-level stuff like this.

The first step to integration is to create a user, and there’s some existing code out there that helped me get jump started:

Creating a DotNetNuke User via SQL

So starting from there, I’ve got a new account for the user and it has their license securely stored.

Next, there’s a password problem there… I certainly don’t want to use a known password, so that needs to change. Again, thanks to the DNN community, I’ve got the solution:

Updating a DotNetNuke User Password via SQL

However, what password do I create? What I wanted to do initially was to create a pass phrase instead of a password. However, being the grammar-Nazi that I am, and being constitutionally incapable of generating icky passphrases, I realized after some investigation that any decent passphrase generator would take me far longer than I was prepared to spend. So… Thank you again to the .NET community, I have a ready-made password generator that creates strong passwords of an arbitrary length:

Strong Passwords in C#

So that problem is also solved, in more detail that I’d care to bother with too! It creates passwords that look like these:

  • a+7P9A*rp6F&
  • So5={9WsM+g7
  • Ax8$+3JwD=a2
  • Ky8-i?H6Dw3&9%sS$rX54Q!f{2eLPp_7

The nice things about that password generator are that it

  • Leaves out ambiguous characters, e.g. I vs. | vs. l vs. 1 or 0 vs. o vs. O
  • Lets you choose the length of the password
  • Mixes in upper and lower case letters, numbers, and symbols

As far as being able to remember them? Bah! Not going to happen. Which is why I wanted to have a pass phrase generator, but, you do what you can with the time you have.

Now, code-wise, there are a few points where things need to get done:

  1. MS SQL Server stored procedures
  2. The IPN.NET project
    1. Default.aspx.cs
    2. Add in the RandomPassword.cs class
    3. Add in the “DnnLicenseIssuer.cs” class
    4. Modify the “Keys.htm” file

The MS SQL Server stored procedures won’t have any impact on DNN if done right. The prerequisite PropertyDefinitions and Roles need to be there, but that’s simple enough.

The RandomPassword.cs and DnnLicenseIssuer.cs classes won’t have any impact on the IPN.NET installation, so there’s a lot of freedom there.

However, changes to the Default.aspx.cs file will break across IPN.NET upgrades unless care is taken to migrate those changes to any new IPN.NET version. Luckily, everything that needs to be done can be done in this method:

private void ProcessPurchaseItem(PurchaseItem item, int quantity)

However, if you’ve actually sold a license, and the payment is successful, there’s only 1 spot that you need to modify, which will look something like this:

DnnLicenseIssuer dnnLi = new DnnLicenseIssuer(ipn, item, keys, false);
if (dnnLi.HasExistingAccount)
{
// Do stuff for license email
}
else
{
// Do stuff for license email
}

So you can easily minimize the impact there and make future upgrades very easily.

The “Do stuff” part contains customizations that I’ve written for the license email. If users have an existing account, then they get a different email than users that I’ve created an account for.

Of course it is possible to go further, and create users irrespective of whether the license payment succeeded or failed, and follow up later, however, it’s not one of my requirements at the moment.

The End Game

There’s a plan behind all this though. I’m not going to spill the beans quite yet, and it won’t get done for some time yet. However, all of this has a forward-looking purpose, and when I finally make it to that stage, I’ll post back on what I’m doing and the results.

Until then, check back at Super Simple over the next few weeks as the new Photo Resizer Social Edition is coming out very soon.

Cheers,

Ryan

Starting More DotNetNuke Development

0

Posted by Cynic | Posted in C#, DotNetNuke, Software, Web Sites | Posted on 22-07-2011

Tags:

DNNWell, I had a bit of a false start. It’s been a long time since I’ve done much DNN module development, so I’ve gone back to basics for DNN 6, which was just released as final at 6.0.0 a couple days ago.

But, I’ve been watching these videos, and they didn’t line up with my development environment. Well, it turns out that I’d used an older template for DNN 3. Ouch. Oh well, back on track with the proper template and things are looking much better now.

 

DotNetNuke 6 is SEXY!

0

Posted by Cynic | Posted in DotNetNuke, Software, Web Sites | Posted on 18-07-2011

Tags:

In a word, SEXY! The new DotNetNuke 6 is just flat out gorgeous. It sports a new skin, DarkKnight, that is simply beautiful. But that’s just the start.

DotNetNuke 6 default install

The new management interface is slick. Very slick. New “Manage” buttons are in the modules. You simply hover over them to see something like this:

DotNetNuke Manage UI

Edit an HTML module, and wow… Super-sexy-swinging stuff! A lightbox pops up with this:

Super Sexy Swinging Stuff Lightbox

Yummy! It’s gorgeous! But it’s more than just fluff. The RTE (Rich Text Editor) has some nice little tweaks like this for quickly adding links:

RTE add links easier

The default installation also comes with some default pages that you’ll likely end up using:

Default pages with demos

They’re fun as well. Here’s one of the fun parts:

MASSIVE RECALL, WE GOOFED

Well guys, last week the Bureau of Temporal Stability stopped by our offices. Unfortunately, it turns out that there are some legal restrictions when it comes to passing out time machines. Let me tell you, they were awfully angry about the results of our first few sales, though personally I have no problems with our new Dinosaur Overlords.

Good stuff!

Changing the default HTML editor is a snap too. No more farting around in web.config!

DNN HTML editor configuration

It couldn’t be simpler.

As you can see from the dropdown above, the default editor has changed, and there’s no option for FCK Editor, but oh well. It all still looks pretty good.

On a side note, I plan on checking out DNNCKEditor to see how it is with DNN. Even better yet, it looks like CKEditor is DNN 6 ready!

There’s more in there as well, but man… This is really looking good.

You’ll want to have .NET 4 running though, as some things require it. But that shouldn’t be a problem. Most likely you’re running .NET 4 already.

I’m very much looking forward to getting to work with some of this.

Cheers,

Ryan

 

 

An Excellent DotNetNuke Tutorial

0

Posted by Cynic | Posted in C#, DotNetNuke, Software, Solutions to Problems | Posted on 03-07-2011

DotNetNukeI’m back in DotNetNuke mode and while doing some refresher reading and whatnot I came across this tutorial. It’s quite good. Much better written and presented than many tutorials I’ve seen on the topic.

During the setup portion of the tutorial, it says:

To make the designer work correctly with DotNetNuke controls we will have to help it find them. Select the Web tab to the left.

Check the radio button Use Local IIS Web server. Enter the URL to the folder where your module code is in your local DotNetNuke installation.

Make sure Override applicationroot URL checkbox is checked and enter the URL to your local DotNetNuke website under it.

(an illustration here)

You can now close the properties tab.

From the Edit menu, select Find and Replace > Replace in Files. Enter “YourCompany” in the Find what field, and “SipidCode” in Replace with. Expand Find options and make sure Look at these file types is set to “*.*”.

Click Replace All.

I sped through a bit quickly, and things broke (because I’m still in the process of setting up this machine for some kinds of development, but that’s another story).

Well, a quick look into it reveals that the order there is REALLY important. ¬†If you replace before you setup the module inside of the web site as described, some DotNetNuke controls get replaced by some System.Web.UI.UserControls. i.e. Not good. You can simply go back and replace the problem areas with the proper controls, which is easy enough to get by starting a new DNN project in Visual Studio if you aren’t sure what they should be.

So, that’s easy enough to fix if you end up getting a bit eager and jumping ahead.

Cheers,

Ryan