Introduction
PayPal is a web-based billing platform that provides api for online payment. In this article we will try to learn how to integrate in-context checkout in ASP.NET MVC application. It consists two part first creating developer sandbox account (for merchant and buyer) and second is using this sandbox account we integrate the PayPal Payment gateway. In this article we will concentrate on only on second part. Let's see how can we integrate it.
After integration you will see the following screens:
What is In-Context Checkout
In-Context checkout is a express checkout in which user can login to the paypal without leaving the current website. So, you can provide better experience to the user without leaving the website.
Requirement
You have to create developer account (Sandbox test account) and so that you can use API credential UserName, Password and Signature in the integration. ASP.NET MVC 5.0
How to Integate in-context checkout
- API Credential
- Create PayPalSettings class
- Create PayPal model class (core implementation)
- Create Cart Controller and respected views
i) API Credential
Add the follwing key into the web.config as:
<add key="PayPal:Sandbox" value="True" />
<add key="PayPal:Username" value="<UserName from mechant account>" />
<add key="PayPal:Password" value="<Password from merchange account>" />
<add key="PayPal:Signature" value="<signature from merchant account>" />
<add key="PayPal:ReturnUrl" value="https://localhost:1588/Cart/CheckoutReview" />
<add key="PayPal:CancelUrl" value="https://localhost:1588/Cart/CheckoutReview" />
<add key="PayPal:MerchantAccountID" value="<MechantaccountID from merchant account" />
<!--sandbox/production-->
<add key="PayPal:Environment" value="sandbox" />
In above returnurl and cancelurl change account to your port and put the api credential here.
ii) Create PayPalSettings class
It is use to get access the setting from the config file. create class as:
using System;
using System.Configuration;
using System.ComponentModel;
using System.Globalization;
namespace MvcApplication1.Models
{
public 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");
}
}
public static string MerchantAccountID
{
get
{
return Setting<string>("PayPal:MerchantAccountID");
}
}
public static string Environment
{
get
{
return Setting<string>("PayPal:Environment");
}
}
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);
}
}
}
iii) Create PayPal model class (core implementation)
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;
using System.Text;
namespace MvcApplication1.Models
{
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["PAYMENTACTION"] = "SALE";
values["CURRENCYCODE"] = "USD";
values["BUTTONSOURCE"] = "PP-ECWizard";
values["USER"] = PayPalSettings.Username;
values["PWD"] = PayPalSettings.Password;
values["SIGNATURE"] = PayPalSettings.Signature;
values["SUBJECT"] = "";
values["VERSION"] = "93";
values["BRANDNAME"] = "BRANDNAME1";
values["AMT"] = order.Amount.ToString();
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, values[key])));
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("https://{0}/nvp", PayPalSettings.ApiDomain));
request.Method ="POST";
request.KeepAlive =false;
byte[] byteArray = Encoding.UTF8.GetBytes(data);
request.ContentType ="application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()))
{
return HttpUtility.ParseQueryString(reader.ReadToEnd());
}
}
public static bool GetCheckoutDetails(string token, ref string PayerID, ref string retMsg)
{
NameValueCollection values = new NameValueCollection();
values["METHOD"] = "GetExpressCheckoutDetails";
values["TOKEN"] = token;
values["USER"] = PayPalSettings.Username;
values["PWD"] = PayPalSettings.Password;
values["SIGNATURE"] = PayPalSettings.Signature;
values["SUBJECT"] = "";
values["VERSION"] = "93";
values = Submit(values);
string ack = values["ACK"].ToLower();
if (ack == "success" || ack == "successwithwarning")
{
PayerID = values["PayerID"];
return true;
}
else
{
retMsg ="ErrorCode=" + values["L_ERRORCODE0"] + "&" +
"Desc=" + values["L_SHORTMESSAGE0"] + "&" +
"Desc2=" + values["L_LONGMESSAGE0"];
return false;
}
}
public static bool DoCheckoutPayment(string finalPaymentAmount, string token, string PayerID, ref string retMsg)
{
NameValueCollection values = new NameValueCollection();
values["METHOD"] = "DoExpressCheckoutPayment";
values["TOKEN"] = token;
values["PAYERID"] = PayerID;
values["PAYMENTREQUEST_0_AMT"] = finalPaymentAmount;
values["PAYMENTREQUEST_0_CURRENCYCODE"] = "USD";
values["PAYMENTREQUEST_0_PAYMENTACTION"] = "Sale";
values["USER"] = PayPalSettings.Username;
values["PWD"] = PayPalSettings.Password;
values["SIGNATURE"] = PayPalSettings.Signature;
values["SUBJECT"] = "";
values["VERSION"] = "93";
values = Submit(values);
string ack = values["ACK"].ToLower();
if (ack == "success" || ack == "successwithwarning")
{
retMsg = values["PAYMENTINFO_0_TRANSACTIONID"].ToString(); ;
return true;
}
else
{
retMsg ="ErrorCode=" + values["L_ERRORCODE0"] + "&" +
"Desc=" + values["L_SHORTMESSAGE0"] + "&" +
"Desc2=" + values["L_LONGMESSAGE0"];
return false;
}
}
}
public class PayPalOrder
{
public decimal? Amount { get; set; }
public string OrderId { get; set; }
public string ReturnUrl { get; set; }
public string CancelUrl { get; set; }
}
public class PayPalRedirect
{
public string Url { get; set; }
public string Token { get; set; }
}
}
iv) Create Cart Controller and respected views
Cart Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class CartController : Controller
{
[HttpGet]
public JsonResult PayPaltoken()
{
string strGUID = (Session["TicketLockedId"] != null ? Session["TicketLockedId"].ToString() : "");
PayPalOrder objPay = new PayPalOrder();
objPay.Amount = 10;
objPay.OrderId ="OT122";
PayPalRedirect redirect = PayPal.ExpressCheckout(objPay);
return Json(redirect.Token, JsonRequestBehavior.AllowGet);
}
public ActionResult ProductOrder()
{
return View();
}
public ActionResult CheckoutReview(string token, string PayerID)
{
string retMsg = "";
string PayerID1 = "";
PayPal.GetCheckoutDetails(token, ref PayerID1, ref retMsg);
ViewData["ReturnMessage"] = retMsg;
ViewData["token"] = token;
ViewData["PayerID"] = PayerID1;
return View();
}
public ActionResult DoCheckoutPayment(string token, string PayerID)
{
string retMsg = "";
PayPal.DoCheckoutPayment("10", token, PayerID, ref retMsg);
ViewData["ReturnMessage"] = retMsg;
return View();
}
}
}
ProductOrder view:
@{
ViewBag.Title ="ProductOrder";
Layout ="~/Views/Shared/_Layout.cshtml";
}
<script src="//www.paypalobjects.com/api/checkout.js" async></script>
<h2>ProductOrder</h2>
@using (Html.BeginForm())
{
<button name="btPaypal" id="btPaypal" type="button">Express Check Out</button>
}
<script type="text/javascript">
window.paypalCheckoutReady =function () {
paypal.checkout.setup("@MvcApplication1.Models.PayPalSettings.MerchantAccountID", {
environment:'@MvcApplication1.Models.PayPalSettings.Environment',
click:function (event) {
event.preventDefault();
paypal.checkout.initXO();
$.support.cors =true;
$.ajax({
type:"GET",
async:true,
crossDomain:true,
//Load the minibrowser with the redirection url in the success handler
success:function (token) {
var url = paypal.checkout.urlPrefix + token;
//Loading Mini browser with redirect url, true for async AJAX calls
paypal.checkout.startFlow(url);
},
error:function (responseData, textStatus, errorThrown) {
alert("Something going wrong ");
//Gracefully Close the minibrowser in case of AJAX errors
paypal.checkout.closeFlow();
}
});
},
button: ['btPaypal']
});
}
</script>
CheckoutReview View:
@{
ViewBag.Title ="CheckoutReview";
Layout ="~/Views/Shared/_Layout.cshtml";
}
<h2>CheckoutReview</h2>
@ViewData["ReturnMessage"]
<a href="@Url.Action("DoCheckoutPayment","Cart",new {token=ViewData["token"],PayerID=ViewData["PayerID"] })">Confirm Payment</a>
DoCheckoutPayment:
@{
ViewBag.Title ="DoCheckoutPayment";
Layout ="~/Views/Shared/_Layout.cshtml";
}
<h2>DoCheckoutPayment</h2>
@ViewData["ReturnMessage"]
_Layout View:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
</head>
<body>
@RenderBody()
</body>
</html>
Debug and test the application
Now your test application is ready to test in-context checkout. Now run visual studio in debug mode. open the url /Cart/ProductOrder. You can see the following screen as:
Now click on the Express Checkout button. A popup window open as:
Put the buyer account credential here and click continue. Now you can see the next window review window as:
Now you can cofirm to final payment. After confirm button click final payment will be done. Now you can check the test account for respected change.
Conclusion
In the above discusion we try to understand how to integrate in-context checkout in ASP.NET MVC. I hope it will help you.
Priya
12-Apr-2016 at 19:44