Before I throw them under the bus completely, let me first point out the positives about PayPal. First, it is a great way for new businesses who are maybe testing out the waters of their business model and don’t want to get locked into all of the hassle of setting up a merchant account through their banks. Second, they do provide a great number of applications that do cater to many of the different scnenarios many online businesses need such as Recurring Payments, Calculation of Shipping based on Area, and plenty more. So for the most part, PayPal is a “good” option for many online businesses.
Why PayPal Needs a Quality Assurance Wakeup Call
I spent literally 4 whole days going back and forth from blog to blog, developer forum to developer forum looking for the answer to this seemingly simple scenario. Create a recurring payment and charge a single payment for items in the same transaction. According to PayPal, this is a piece of cake. Not so young Skywalker.
I started by going to PayPal’s website and discovered their old Express Checkout site had changed quite a bit and some of the familiar code snippets they had available before to perform tasks such as this were gone. I wasn’t that concerned and proceeded to their Express Checkout area which, again according to PayPal, was an easy and great way to perform the tasks I wanted to complete.
PayPal’s Code Wizard…Merlin’s Red-Headed Step Child
Ok so here’s the point of the blog post. This code wizard of PayPal. Now most wizards are pretty friendly. They are supposed to walk you through the basic features of what you’re trying to accomplish and give you a base to start from so you can then maybe go into the advanced features and adjust your code accordingly.  Theirs is completely a mind-screw and you’ll just love what I found out.
Help for You Fellow Coders in ASP.net
If you found this article because you got the “Token is Invalid”, or “Timeout Error”, or “Amount is Undefined”, dude…I feel your frustration. You also probably spotted a few articles where these other devs said, all you have to do is call the SetExpressCheckout, change your version to 42 or higher, etc. What they failed to mention was in the PayPal’s own generated code wizard, the version number is not a NVP (Name-Value-Pair) you put into your code…it’s in the .CS code itself way down at the bottom of the friggin’ class.
How I Solved the Issue
Go into the PayPalFunctions.cs the wizard generates for you and scroll down to the buildCredentialsNVPString(). Change the following code from:
codec["VERSION"] = “2.6″;
to:
codec["VERSION"] = “54.0″;
You can see they were off by just a few versions. Now while I understand that the wizard is not made for recurring payments, it would have been nice for them to mention that in maybe the final screen. I would also imagine that this change of version will work for the Express Checkout regardless of whether you’re doing recurring payments or not, but maybe not.
Other Items I Had to Solve
Other things they don’t really point out to you are the things you should include in the NVP for the SetExpressCheckout:
NVPCodec encoder = new NVPCodec();
encoder["METHOD"] = “SetExpressCheckout”;
encoder["AMT"] = “45.00″; //amt;
encoder["RETURNURL"] = returnURL;
encoder["CANCELURL"] = cancelURL;
encoder["PAYMENTACTION"] = “Sale”;
encoder["L_DESC0"] = “12 Month Subscription to Your Store”; // THIS MUST MATCH THE BILLING AGREEMENTDESCRIPTION
encoder["L_BILLINGTYPE0"] = “RecurringPayments”;
encoder["L_BILLINGAGREEMENTDESCRIPTION0"] = “12 Month Subscription to Your Store”;Â // THIS MUST MATCH YOUR L_DESCn FIELD…IN MY EXAMPLE THE L_DESC0
encoder["L_NAME1"] = “Item Number 1″;
encoder["L_NUMBER1"] = “XY1238″;
encoder["L_DESC1"] = “Some Description”;
encoder["L_AMT1"] = “15.00″;
encoder["L_QTY1"] = “3″;
You’ll notice there’s a few things they exclude in their version that is code generated and such. Now in a separate function I called DoRecurring, I have the following NVP:
NVPCodec encoder = new NVPCodec();
encoder["METHOD"] = “CreateRecurringPaymentsProfile”;
encoder["TOKEN"] = token;
encoder["DESC"] = “12 Month Subscription to Your Store”; //YEP ADD THIS AGAIN
encoder["PROFILESTARTDATE"] = “2009-03-16T13:00:00Z”; //MAKE SURE THIS IS GMT FORMAT
encoder["BILLINGPERIOD"] = “Month”;Â //Month, Year, etc.
encoder["BILLINGFREQUENCY"] = “1″;Â // This is the “cycle” so each month the customer will be billed once
encoder["AMT"] = “25.00″;
encoder["L_BILLINGTYPE0"] = “RecurringPayments”; //Has to be this for recurring to work
encoder["L_BILLINGAGREEMENTDESCRIPTION0"] = “12 Month Subscription to Your Store”;Â //YEP HAS TO MATCH
So there ya go. Now if you’re still a bit confused at the way PayPal’s Code Wizard said things like insert this on your billing and confirmation pages, etc. Don’t let that bother you. Here’s a simple version to do what I was trying to accomplish. Hopefully this helps make it a bit clearer for you:
- Take the image they put in a form and make it an Image Button.
- On click of this image, in your code behind, insert the SetExpressCheckout code to setup your transaction and send the user to paypal to either enter their credit card or log into their PP account.
- After they do this they will be returned to a return URL you specified in the Wizard. Create something called checkout.aspx and in the .cs file in the page load save the token and payerid into session variables.
- Put another button on this page and say something like “Finalize Payment”. (Above this you’d put something like a list of the items or subscriptions they’ll be purchasing….just so they’re really sure about purchasing.
- On the click of that button put in the call to the CreateRecurringProfile function by copying the call as the FinalizeCheckout does.
Hopefully that helps you out a bit. If you have any questions please email me at info[-at-]justicesolutionsllc.com or simply comment below. I’ll really try to respond and help as much as I can because this was really frustrating. I hope a PayPal developer reads this and rather than criticizing the hell out of my code which may not be perfect, really takes this back to PayPal and does a real QA on their code wizard and their manuals. Because there are critical pieces and better explanations needed.