PayPalMerchantSDK, integrate paypal into your mvc 4 website

The following outlines some of the things that I have learned whilst trying to integrate a PayPal payment gateway into the MVC 4.0 website.

Installation

After much reading I determined that I easiest way was to use the PayPaylMerchantSDK.
This is implemented using the PayPal classic API which is the only API available in Australia @ the time of writing.
The easiest way to add this to your application is to use NuGet in Visual Studio (Tools ->> Library Package Manager ->> Manage NuGet Packages for Visual Studio) and search for PayPal.
Click on the PayPalMerchantSDK and choose Install. This will download the dependencies including log4net and the “PayPal Core SDK for .Net”

Code Samples

You should download and use the “Merchant” solution in the .net code samples that can be found here.
Classic API .Net code samples

App.Config

The code samples have an App.Config file that contains the base configuration for working with the API.
It contains the log4net and PayPal configuration section. You should copy these configuration sections into your web.config file.

Access the paypal settings section in the web.config

When coding I want to access some of the PayPal settings that I just copied into my web.config file, for example “paypalUrl” could be used when attempting to send a request for express checkout.

To access the paypal configuration settings that are in the web.config use the following code:

[csharp]
string url = PayPal.Manager.ConfigManager.Instance.GetProperties()["paypalUrl"];
[/csharp]

IPN Testing

IPN Simulator

I thought that it was dangerous opening port 80 through the firewall to get to my development server, so I was clever and used an unusual port number. This worked fine for most things but the IPN testing would not work with my special port number.

You have to use port 80 to allow the IPN test to work.

Core .SDK

The old way of implementing the IPN callback has been integrated into the PayPal .Core SDK.
IPNMessage.cs

This can now be implemented in 3 lines of code.

Put this inside your controller page

[csharp]
public ActionResult IPN()
{
byte[] bytes = Request.BinaryRead(Request.ContentLength);

PayPal.IPNMessage message = new PayPal.IPNMessage(bytes);
if (message.Validate())
{
// message returned VERIFIED
}
else
{
// There was a problem
}

return null;
}
[/csharp]

Note I then created a PayPalTransaction Class to simplify access to the PayPal.IPNMessage object.

It looked something like this.
[csharp]
public class PayPalTransaction
{

#region Constants

private const string KEY_ADDRESSSTATE = "address_state";
private const string KEY_TXNID = "txn_id";
private const string KEY_LASTNAME = "last_name";
private const string KEY_CURRENCY = "mc_currency";
private const string KEY_PAYERSTATUS = "payer_status";
private const string KEY_ADDRESSSTATUS = "address_status";
private const string KEY_TAX = "tax";
private const string KEY_INVOICE = "invoice";
private const string KEY_PAYEREMAIL = "payer_email";
private const string KEY_FIRSTNAME = "first_name";
private const string KEY_BUSINESS = "business";
private const string KEY_VERIFYSIGN = "verify_sign";
private const string KEY_PAYERID = "payer_id";
private const string KEY_PAYMENTDATE = "payment_date";
private const string KEY_PAYMENTSTATUS = "payment_status";
private const string KEY_RECEIVEREMAIL = "receiver_email";
private const string KEY_PAYMENTTYPE = "payment_type";
private const string KEY_ADDRESSNAME = "address_name";
private const string KEY_ADDRESSSTREET = "address_street";
private const string KEY_ADDRESSZIP = "address_zip";
private const string KEY_ADDRESSCITY = "address_city";
private const string KEY_ADDRESSCOUNTRY = "address_country";
private const string KEY_ADDRESSCOUNTRYCODE = "address_country_code";
private const string KEY_SHIPPING = "mc_shipping";
private const string KEY_ITEMNUMBER1 = "item_number1";
private const string KEY_SHIPPING1 = "mc_shipping1";
private const string KEY_ITEMNAME1 = "item_name1";
private const string KEY_HANDLING1 = "mc_handling1";
private const string KEY_GROSS1 = "mc_gross1";
private const string KEY_GROSS = "mc_gross";
private const string KEY_FEE = "mc_fee";
private const string KEY_RESIDENCECOUNTRY = "residence_country";
private const string KEY_NOTIFYVERSION = "notify_version";
private const string KEY_RECEIVERID = "receiver_id";
private const string KEY_HANDLING = "mc_handling";
private const string KEY_TXNTYPE = "txn_type";
private const string KEY_CUSTOM = "custom";
private const string KEY_TESTIPN = "test_ipn";

private const string KEY_IPNTRACKID = "ipn_track_id";
private const string KEY_PROTECTION_ELIGIBILITY = "protection_eligibility";

private const string KEY_QUANTITY = "quantity";
private const string KEY_RESEND = "resend";
private const string KEY_NOTIFY_VERSION = "notify_version";

#endregion

#region Constructor

public PayPalTransaction()
{
}

public PayPalTransaction(PayPal.IPNMessage message)
{
this.TransactionId = message.IpnValue(KEY_TXNID);
this.TransactionType = message.IpnValue(KEY_TXNTYPE);
this.PayerId = message.IpnValue(KEY_PAYERID);
this.Currency = message.IpnValue(KEY_CURRENCY);
this.Custom = message.IpnValue(KEY_CUSTOM);
this.HandlingAmount = GetAsDecimal(message, KEY_HANDLING);
this.FirstName = message.IpnValue(KEY_FIRSTNAME);
this.IpnTrackId = message.IpnValue(KEY_IPNTRACKID);
this.LastName = message.IpnValue(KEY_LASTNAME);
this.PayerStatus = message.IpnValue(KEY_PAYERSTATUS);
this.PaymentDate = GetAsDate(message, KEY_PAYMENTDATE);
this.PaymentStatus = message.IpnValue(KEY_PAYMENTSTATUS);
this.ProtectionEligibility = message.IpnValue(KEY_PROTECTION_ELIGIBILITY);
this.ShippingAmount = GetAsDecimal(message, KEY_SHIPPING);
this.GrossAmount = GetAsDecimal(message, KEY_GROSS);
this.FeeAmount = GetAsDecimal(message, KEY_FEE);

this.Quantity = GetAsInt(message, KEY_QUANTITY);
this.Resend = GetAsBool(message, KEY_RESEND);
this.PaymentType = message.IpnValue(KEY_PAYMENTTYPE);
this.NotifyVersion = message.IpnValue(KEY_NOTIFY_VERSION);
this.PayerEmail = message.IpnValue(KEY_PAYEREMAIL);
this.TaxAmount = GetAsDecimal(message, KEY_TAX);
this.ResidenceCountry = message.IpnValue(KEY_RESIDENCECOUNTRY);

this.ItemNumber1 = message.IpnValue(KEY_ITEMNUMBER1);
this.ItemName1 = message.IpnValue(KEY_ITEMNAME1);
this.ShippingAmount1 = GetAsDecimal(message, KEY_SHIPPING1);
this.HandlingAmount1 = GetAsDecimal(message, KEY_HANDLING1);
this.GrossAmount1 = GetAsDecimal(message, KEY_GROSS1);

this.AddressCity = message.IpnValue(KEY_ADDRESSCITY);
this.AddressCountryCode = message.IpnValue(KEY_ADDRESSCOUNTRYCODE);
this.AddressCountry = message.IpnValue(KEY_ADDRESSCOUNTRY);
this.AddressName = message.IpnValue(KEY_ADDRESSNAME);
this.AddressStreet = message.IpnValue(KEY_ADDRESSSTREET);
this.AddressZip = message.IpnValue(KEY_ADDRESSZIP);

}

#endregion

#region Private Helpers

private int GetAsInt(PayPal.IPNMessage m, string key)
{
int value = Convert.ToInt32(m.IpnValue(key));
return value;
}

private bool GetAsBool(PayPal.IPNMessage m, string key)
{
bool bln = false;
string value = m.IpnValue(key);
if (value != null)
{
bln = (value.ToLower().Trim() == "true");
}
return bln;
}

private decimal GetAsDecimal(PayPal.IPNMessage m, string key)
{
decimal value = Convert.ToDecimal(m.IpnValue(key));
return value;
}

private DateTime GetAsDate(PayPal.IPNMessage m, string key)
{
string value = m.IpnValue(key);
value = HttpUtility.HtmlDecode(value);

int iPos = value.LastIndexOf(" ");
string timezone = value.Substring(iPos+1);
TimeZoneInfo tzSource = null;

value = value.Substring(0, iPos);

switch (timezone)
{
case "PST":
case "PDT":
tzSource = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
break;
}

DateTime date = Convert.ToDateTime(value);
date = TimeZoneInfo.ConvertTimeToUtc(date, tzSource);
date = TimeZoneInfo.ConvertTimeFromUtc(date, TimeZoneInfo.Local);

return date;
}

#endregion

#region Properties

public int Id { get; set; }

/// <summary>
/// The transaction Id of the PayPal Transaction
/// </summary>
public string TransactionId { get; private set; }

public string TransactionType { get; private set; }

public string PayerId { get; private set; }

public string IpnTrackId { get; private set; }

public string Currency { get; private set; }

public string Custom { get; private set; }

public string FirstName { get; private set; }

public decimal HandlingAmount { get; private set; }

public string LastName { get; private set; }

public string ProtectionEligibility { get; private set; }

public string PayerStatus { get; private set; }

public DateTime PaymentDate { get; private set; }

public string PaymentStatus { get; private set; }

public int Quantity { get; private set; }

public bool Resend { get; private set; }

public string PaymentType { get; private set; }

public string NotifyVersion { get; private set; }

public string PayerEmail { get; private set; }

public string ResidenceCountry { get; private set; }

public string AddressName { get; private set; }

public string AddressStreet { get; private set; }

public string AddressZip { get; private set; }

public string AddressCity { get; private set; }

public string AddressCountry { get; private set; }

public string AddressCountryCode { get; private set; }

public decimal ShippingAmount { get; private set; }

public decimal GrossAmount { get; private set; }

public decimal FeeAmount { get; private set; }

public decimal TaxAmount { get; private set; }

public decimal ShippingAmount1 { get; private set; }

public decimal GrossAmount1 { get; private set; }

public decimal HandlingAmount1 { get; private set; }

public string ItemNumber1 { get; private set; }

public string ItemName1 { get; private set; }

#endregion

#region Virtual Properites

public virtual bool IsComplete
{
get
{
bool value = (this.PaymentStatus.ToLower().Trim() == "completed");
return value;
}
}
#endregion

}
[/csharp]

[csharp][/csharp]

Links

2 thoughts on “PayPalMerchantSDK, integrate paypal into your mvc 4 website

  1. Thank you very much for writing this up. I’ve Book Marked this page, this was the help I was badly looking for… for the past week. Do you by any chance have a working MVC project using the SDK ? I finally found the samples using the link on here. Wasn’t able to find them before.

    Do you have a working sample of a MVC site using the sdk(s) ?

    1. Sorry no working sample, I have a MVC website with a paypal integration working, so it is possible. I am playing around with creating my own assembly to wrap up the SDK functionality to allow it to be easily added to other websites but that is still in the pipeline.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.