PayPal Subscriptions Recently, I blogged about a PayPal Subscriptions project I was working on. This was a website where people could subscribe via PayPal for weekly religious lessons under one of three user categories. The previous post looked at the differences between the Web Site and Web Application Project models and what this meant when attempting to implement user profiles in conjunction with the membership system. Since I had previously created a few basic E-Commerce websites with regular Buy-Now buttons, I thought this would be a breeze... wrong :-|

As part of the project requirements, there would be separate, weekly messages displayed to the subscribers. The first message of a yearly subscription that would be displayed, would be tied to the original subscription date. No matter what kind of subscription system or periodical you are publishing, at some stage you will need to offer the correct issue number to a given subscriber. Since everyone will be subscribing at different times, this means keeping count! I decided to keep a tab of the week numbers. Bear in mind, that week calculations are done differently in different cultures and there is not a bug if you see week number 53!

using System.Globalization;

CultureInfo cultInfo = CultureInfo.CurrentCulture;
int weekNumNow = cultInfo.Calendar.GetWeekOfYear(DateTime.Now,
                                              cultInfo.DateTimeFormat.CalendarWeekRule,
                                              cultInfo.DateTimeFormat.FirstDayOfWeek);

 

For the task in hand, I used ASP.NET 2.0 and C# with VS 2005 and SQL Server 2005. It was built as a Web Application Project, which meant using the Web Profile Builder wrapper class to enable access to user profiles. I've heard of several people getting errors with this but it worked for me out of the box. I'm inclined to think that some may have overlooked a particular section of the documentation which I am going to repeat here:

"When your project has reloaded, you need to generate the web profile class and manually include it in your project. Use the solution explorer to do this. In the solution explorer, choose the “Show All Files” option and press the “Refresh” button two times. The first time will generate the profile class and WebProfileBuilder.user file. The second time will actually show the files now that they exist. To include the generated profile class, right-click on the generated profile class and choose “Include In Project”. Now you will be able to write code against the profile class."

The rest is pretty straightforward:

Web.Config Profile Section

 

public partial class MyClass : System.Web.UI.Page
{
    private WebProfile Profile
    {
        get
        {
            return new WebProfile(Context.Profile);
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        string subscriberID = Profile.subscriberID;
        string subscriberGroup = Profile.subscriberGroup;
    }
    
    ...
}

 

Of course, the glue that holds the entire application together is the IPN class. I had previously used the freely-available IPN class from XDev Software. Note that this class is designed for regular PayPal transactions. I had to customize it to handle PayPal subscriptions. All you really have to do is pare it down to handle only the subscription-related variables you are handling on the return handshake from PayPal. The following set of return variables worked for my particular scenario; you will set these as properties of your custom IPN class:

        string txn_type;
        string business;
        string item_name;
        string payment_gross;
        string payment_status;
        string receiver_email;
        string payer_email;
        string pending_reason;
        string payment_date;
        string subscribe_id;
        string first_name;
        string last_name;
        string custom;

 

Here's an overview of a typical subscription Web application life-cycle:

1) User subscribes on your site and is directed to the PayPal site where they pay
2) Your IPN class handshakes with PayPal and grabs the values returned by PayPal
3) Your IPN class updates your application database and generates an email to the subscriber with a return URL to register on your site
4) Your IPN class generates an email (backup) to the merchant with the subscription data
5) The subscriber creates a user account on your site and you set up any extra member info you want to store in their profile

protected void Createuserwizard1_CreatingUser(object sender, EventArgs e)
{
    WebProfile p = WebProfile.GetProfile(CreateUserWizard1.UserName, true);
    p.Initialize(CreateUserWizard1.UserName, true);
            
    p.subscriberID = ViewState["SubscriberID"].ToString();
    p.subscriberGroup = ViewState["Group"].ToString();
            
    p.Save();
}

 

Some Gotchas:

Do not use a return URL from PayPal
Do not mix IPN and PDT. IPN is all you need
Do not forget the Save() method when creating the profile :-S

kick it on DotNetKicks.com   PHP, ASP, .NET, JSP Resources, Reviews




Cool Dude Programmer I have just begun working on an application, a website which offers people paid subscriptions via PayPal to a weekly message, which they can view on the site after logging in. I had the site designed, including the CSS and two separate master pages. The site was up on staging as an ASP.NET 2.0 Web Application Project written in C#, and I had just started looking to the required functionality when I got an unexpected lesson in the differences between the two ASP.NET development models; that is, the "Web Site" and the "Web Application Project" models.

Quick note on naming conventions: I always use the single-word version, "website"; personal choice. Microsoft refers to the ASP.NET template as "Web Site", as in FILE -> New Web Site. Still, if you look at the Drop Down Menu names in Visual Studio after opting to go with a "Web Site", you will see "Website". Worse still, try googling this! Consistency aside, this is one dumb-ass naming choice which is right up there with MOSS "Features", another joy to Google... end of rant ;-)

I normally use the Web Application Project model because it is what I am used to and it makes sense to me. I have always viewed the Web Site model as something to use for demonstration purposes and the like. Truthfully, when Microsoft initially brought out only the Web Site template with VS 2005 and then did the turnaround to also include the Web Application Project template in SP1, I believe that at this point they should have dropped the Web Site model completely. To this day, it leads to nothing but confusion among developers of all levels.

The differences between the two models have been pretty well covered, or at least so I thought. This article is not going to delve into the details of these templates, so for the benefit of those new to ASP.NET, here are some informative references on the two models:

* Comparing Web Site Projects and Web Application Projects
* Visual Studio 2005 Web Application Project Option
* ASP.NET 2.0 - Web Site vs Web Application
* Converting a Web Site Project to a Web Application Project
* Add a Reference to a Visual Studio Project in a Web Site

 With a two-week deadline, I wanted as much out-of-the-box functionality as I could leverage from ASP.NET.

Surprise #1: Profiles only Work Out-of-the-Box with the Web Site Template
In order to implement the logic for the application described above, I planned on using User Profiles to store some extra information for each subscriber such as the date they subscribed along with the type of subscription. Profiles allow you to store some extra information per user when using the ASP.NET membership system. In this case, I was using SQL Server 2005 to store membership details. Profiles are stored in the database automatically and all we have to do is add this extra information to our web.config file. We don't need to know anything about how this data is stored or retrieved.

What they don't tell you is that Profiles only work out-of-the-box with the Web Site option. I discovered this while reading the comments on Scott Guthrie's great blog posting on this topic. There is a workaround available and you can find out more about that here. The problem stems from the fact the Web Application Project does not have the Profile object automatically added to each page as with the Web Site project, so we cannot get strongly-typed programmatic access to the profile properties defined in our web.config file.

The Web Project workaround did not appeal to me because this is an E-Commerce site for a client and I did not like the idea of having to resort to an add-in. I had no way of knowing how stable this was or what other issues might have arisen within my short project time-frame. You can code your own custom profile class if you choose.

The real kicker here is that Profiles are still not available out-of-the-box with the VS 2008 ASP.NET 3.5 Web Application Project template. A mysterious omission...

Surprise #2: Where is the Web Content Form in the Web Site Project?
As already mentioned, I was using two separate master pages and every page in my site is based off one of these master pages. When I went to add a Web Content Form in the Web Site "project", there was none! At first I hand-coded the page tag, then I noticed the "Select master page" checkbox. The images below show the Web Content Form when using a Web Application Project and the lack of one when using the Web Site "Project".

Web Application Project - Web Content Form

 

Web Site Project - No Web Content Form

 

Surprise #3: Where have all the Namespaces Gone?
No namespaces are used for classes anywhere in the App_Code folder. Now, most of us already know that the application automagically finds classes placed in this folder. But, for someone like me who is so used to working with the project model, this didn't strike me right off the bat! So, presumably name conflicts are not a cause for concern here? This is confirmation that Microsoft never intended the Web Site "Project" template for enterprise work, if anyone was ever in any doubt.

My own project will have a user control which is referenced from a master page. On reading this post by Rick Strahl, I see that there are all kinds of difficulties when accessing user controls with the Web Site model - read through the comments. Now I'm thinking that I may revert to the Web Application Project and use the Web Profile Builder to solve my Profile issues after all! At least I won't have grapple with trying to dynamically load a user control from a different assembly... are you getting the bad code smell yet?

kick it on DotNetKicks.com   PHP, ASP, .NET, JSP Resources, Reviews




Windows Live SkyDrive I just noticed a new link when checking my hotmail this morning, to "Windows SkyDrive". Microsoft are offering 5GB worth of free online storage. It works with Windows or Mac with Firefox or Internet Explorer.

There are personal, shared and world folder options. File transfers are SSL-protected. What I found particularly interesting is that you can use the shared folders to colloborate with colleagues and set permissions for each person on a folder level. Nice angle :-)

I'm getting tired of emailing stuff between work and home. I'm also tired of getting down under my desk fumbling with a flash stick, so I think I'll give this a test drive for a while.

You can learn more here.

kick it on DotNetKicks.com