Wednesday, October 17, 2012

PayPal with ASP.NET MVC


PayPal with ASP.NET MVC

PayPal is a cheap and easy solution for taking payments and is quick to implement in ASP.NET MVC. We will look at a simple scenario of taking a user to a PayPal payment page to checkout. There is not much information on the PayPal website about using MVC, so hopefully this should get you started. This post deals with the express checkout, but the same principle applies to the normal checkout process.

Creating a PayPal Account

You will need a sandbox account to test your transactions. The sandbox account is separate from a regular account and is all you need to sign up to before you develop and test your code.

PayPal Account Settings

It's good practice to put things like account settings in the web.config. The code in this article will access these settings. You must change the sandbox setting to False when using regular account details:
<appSettings>  
   <add key="PayPal:Sandbox" value="True" />
   <add key="PayPal:Username" value="*" />
   <add key="PayPal:Password" value="*" />
   <add key="PayPal:Signature" value="*" />
   <add key="PayPal:ReturnUrl" value="http://www.superstarcoders.com" />
   <add key="PayPal:CancelUrl" value="http://www.superstarcoders.com" />
</appSettings>

PayPal Checkout Button

We won’t discuss the ins and outs of implementing the shopping cart functionality for adding/removing products, and will get straight onto the “buy” button. You will need to place a checkout or buy button on your page (you must use the ones PayPal provide).
Here’s how this should look in ASP.NET MVC using the Razor engine (which I’m a big fan of):
@using (Html.BeginForm("Pay", "Cart"))
{
   <input type='image' name='submit'
      src='https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif' />
}
The checkout button posts back to your controller and then you do a server side call to PayPal. This is the only API call you need to make to get the simplest of transactions going and in fact you don’t need to make this call if you're not using the express checkout, however, the nice part about doing this server side interaction is you get some feedback from PayPal which you can log (logging the interaction with a payment provider in this way for trouble shooting purposes is heavily advised) before taking the user to the PayPal website. The MVC redirect mechanism makes this quite easy in your controller. Once this redirect happens the user can pay and the transaction is complete.
public class CartController : Controller
{
   public ActionResult Index()
   {
      return View();
   }

   public ActionResult Pay()
   {
      PayPalRedirect redirect = PayPal.ExpressCheckout(new PayPalOrder { Amount = 50 });

      Session["token"] = redirect.Token;

      return new RedirectResult(redirect.Url);
   }
}
Here is the PayPal API code that you can include in your solution or a separate library:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections.Specialized;
using System.Net;
using System.IO;
using System.Globalization;

public class PayPal
{
   public static PayPalRedirect ExpressCheckout(PayPalOrder order)
   {
      NameValueCollection values = new NameValueCollection();

      values["METHOD"] = "SetExpressCheckout";
      values["RETURNURL"] = PayPalSettings.ReturnUrl;
      values["CANCELURL"] = PayPalSettings.CancelUrl;
      values["AMT"] = "";
      values["PAYMENTACTION"] = "Sale";
      values["CURRENCYCODE"] = "GBP";
      values["BUTTONSOURCE"] = "PP-ECWizard";
      values["USER"] = PayPalSettings.Username;
      values["PWD"] = PayPalSettings.Password;
      values["SIGNATURE"] = PayPalSettings.Signature;
      values["SUBJECT"] = "";
      values["VERSION"] = "2.3";
      values["AMT"] = order.Amount.ToString(CultureInfo.InvariantCulture);

      values = Submit(values);

      string ack = values["ACK"].ToLower();

      if (ack == "success" || ack == "successwithwarning")
      {
         return new PayPalRedirect
         {
            Token = values["TOKEN"],
            Url = String.Format("https://{0}/cgi-bin/webscr?cmd=_express-checkout&token={1}",
               PayPalSettings.CgiDomain, values["TOKEN"])
         };
      }
      else
      {
         throw new Exception(values["L_LONGMESSAGE0"]);
      }
   }

   private static NameValueCollection Submit(NameValueCollection values)
   {
      string data = String.Join("&", values.Cast<string>()
        .Select(key => String.Format("{0}={1}", key, HttpUtility.UrlEncode(values[key]))));

      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
         String.Format("https://{0}/nvp",PayPalSettings.ApiDomain));
      
      request.Method = "POST";
      request.ContentLength = data.Length;

      using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
      {
         writer.Write(data);
      }

      using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()))
      {
         return HttpUtility.ParseQueryString(reader.ReadToEnd());
      }
   }
}
The PayPal order class (which has some details left for you to fill in):
public class PayPalOrder
{
 public decimal Amount { get; set; }
}
The PayPal redirect result class:
public class PayPalRedirect
{
 public string Url { get; set; }
 public string Token { get; set; }
}
Here’s the wrapper around the ASP.NET application settings used by the PayPal API code:
using System;
using System.Configuration;
using System.ComponentModel;
using System.Globalization;

public static class PayPalSettings
{
   public static string ApiDomain
   {
      get
      {
         return Setting<bool>("PayPal:Sandbox") ? "api-3t.sandbox.paypal.com" 
            : "api-3t.paypal.com";
      }
   }

   public static string CgiDomain
   {
      get
      {
         return Setting<bool>("PayPal:Sandbox") ? "www.sandbox.paypal.com" : "www.paypal.com";
      }
   }

   public static string Signature
   {
      get
      {
         return Setting<string>("PayPal:Signature");
      }
   }

   public static string Username
   {
      get
      {
         return Setting<string>("PayPal:Username");
      }
   }

   public static string Password
   {
      get
      {
         return Setting<string>("PayPal:Password");
      }
   }
 
   public static string ReturnUrl
   {
      get
      {
         return Setting<string>("PayPal:ReturnUrl");
      }
   }
 
   public static string CancelUrl
   {
      get
      {
         return Setting<string>("PayPal:CancelUrl");
      }
   }

   private static T Setting<T>(string name)
   {
      string value = ConfigurationManager.AppSettings[name];

      if (value == null)
      {
         throw new Exception(String.Format("Could not find setting '{0}',", name));
      }

      return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
   }
}

3 comments:

  1. Hi,
    I am trying to doing the same,

    please help me..

    thanks.

    ReplyDelete
  2. how to create payment using access token in paypal Rest api ?

    how to make below code in c# ?

    code :

    https://api.paypal.com/v1/payments/payment

    curl -v https://api.sandbox.paypal.com/v1/payments/payment \
    -H "Content-Type:application/json" \
    -H "Authorization:Bearer EMxItHE7Zl4cMdkvMg-f7c63GQgYZU8FjyPWKQlpsqQP" \
    -d '{
    "intent":"sale",
    "payer":{
    "payment_method":"credit_card",
    "funding_instruments":[
    {
    "credit_card":{
    "number":"4417119669820331",
    "type":"visa",
    "expire_month":11,
    "expire_year":2018,
    "cvv2":"874",
    "first_name":"Joe",
    "last_name":"Shopper",
    "billing_address":{
    "line1":"52 N Main ST",
    "city":"Johnstown",
    "country_code":"US",
    "postal_code":"43210",
    "state":"OH"
    }
    }
    }
    ]
    },
    "transactions":[
    {
    "amount":{
    "total":"7.47",
    "currency":"USD",
    "details":{
    "subtotal":"7.41",
    "tax":"0.03",
    "shipping":"0.03"
    }
    },
    "description":"This is the payment transaction description."
    }
    ]
    }'

    ReplyDelete
  3. For the latest solution of PayPal checkout in ASP.NET, test the demo on: https://techtolia.com/PayPal/
    Receive payments from PayPal, PayPal Credit, credit or debit cards, Bancontact, BLIK, eps, giropay, iDEAL, MyBank, Przelewy24, SEPA-Lastschrift, Sofort, Venmo via PayPal.

    ReplyDelete