Integrating PayPal with ASP.NET

This tutorial will take you through many of the steps you would need to add PayPal payments to an ASP.NET web application. It does not however link the transactions with database - something you would need to do for a completed system.

You can see further examples within the PayPal REST API reference (be sure to set the language to C#) and the Sample code for creating a PayPal payment using ASP.NET.

Pre-requisites

To complete this tutorial, you need to have registered with PayPal and setup a developer account, as well as having created a 'REST API app' in the developer dashboard. You will need a Client ID and Secret for the Sandbox. You must use the Sandbox for this tutorial, otherwise you could end up making real payments

You will also need test buyer accounts for the sandbox which will give you an email address as password to use when testing payments

Building the order page

  1. Start by creating an empty ASP.NET 4.6 application, adding references for Web Forms
  2. Add a home page (named default.aspx) and add the following code (Start by adding a label, dropdown list and button and then configure the elements to save typing):
    <h2>Purchase past exam questions</h2>
    <asp:Label ID="lblQuantity" runat="server" Text="Quantity at £10 each" AssociatedControlID="ddlExamQuantity"></asp:Label>
    <asp:DropDownList ID="ddlExamQuantity" runat="server">
        <asp:ListItem>1</asp:ListItem>
        <asp:ListItem>2</asp:ListItem>
        <asp:ListItem>3</asp:ListItem>
    </asp:DropDownList>
    <p>Postage and packaging charges of £3.95 will be applied to your order</p>
    <asp:Button ID="btnPurchaseExamQuestions" runat="server" Text="Buy Now" />
    
  3. Double Click on the button to add and event handler. You will be taken into the default.aspx.cs file.
  4. At the top of the button handler method that the cursor has been placed in, add the following code to pre-set the price of the exam papers and postage and packaging (usually this data would be derived from entries in a sites database):
    protected void btnPurchaseExamQuestions_Click(object sender, EventArgs e)
    {
        decimal postagePackingCost = 3.95m;
        decimal examPaperPrice = 10.00m;
        int quantityOfExamPapers = int.Parse(ddlExamQuantity.SelectedValue);
        decimal subtotal = (quantityOfExamPapers * examPaperPrice);
        decimal total = subtotal + postagePackingCost;
    }

Adding the PayPal Code

In order to use PayPal, we need to add the PayPal API to our project. We can do this in one step by using the NuGet Package Manager.

Configuration

  1. Click on Tools > NuGet Package Manager > Package Manager Console. A command window will open in Visual Studio with the prompt PM>
  2. At the prompt, type install-package PayPal and press enter. Some text will appear in the window, and once it is finished the message Successfully installed 'PayPal 1.8.0' to <<Your Project Name>> will appear (note that the version may change)
  3. Next we need to add some configuration to the web.config file in the project. Open this file and inside the <configuration> section add the following code, amending the clientId and clientSecret values to those from your PayPal Sandbox API credentials:
    <configSections>
        <section name="paypal" type="PayPal.SDKConfigHandler, PayPal" />
    </configSections>
    <paypal>
        <settings>
            <add name="mode" value="sandbox" />
            <add name="clientId" value="YOUR_CLIENT_ID" />
            <add name="clientSecret" value="YOUR_CLIENT_SECRET" />
        </settings>
    </paypal>
  4. Return to the Default.aspx.cs file, and at the top, under the existing using statement, add the following line of code:
    using PayPal.Api;
  5. Next return to the button handler and add this code beneath your existing code to authenticate with PayPal and get an APIContext object (which you will use later to create a Payment):
    // Authenticate with PayPal
     var config = ConfigManager.Instance.GetProperties();
     var accessToken = new OAuthTokenCredential(config).GetAccessToken();
     //Get APIContext Object
     var apiContext = new APIContext(accessToken);

Items, Transactions and Payment objects

  1. The next step is to create an 'Item' which will refer to a particular product to be purchased, along with its price, currency, quantity and SKU (Stock Keeping Unit, for example a manufacturer code or model number). Because the data will be sent as a standard HTTP request, numeric values need to be converted to strings. In this example we are only creating one item, but it would be possible to have multiple items in the transaction

    Add the following code to create the Item:
    var examPaperItem = new Item();
    examPaperItem.name = "Past Exam Paper";
    examPaperItem.currency = "GBP";
    examPaperItem.price = examPaperPrice.ToString();
    examPaperItem.sku = "PEPCO5027m15"; //sku is stock keeping unit - e.g. manufacturer code
    examPaperItem.quantity = quantityOfExamPapers.ToString();
  2. As well as items, each transaction needs details relating to the breakdown of the transactions total price into the amount paid for products (subtotal) and the amount constituting VAT (tax) and postage and packaging (shipping). Set these values with the following code:
    var transactionDetails = new Details();
    transactionDetails.tax = "0";
    transactionDetails.shipping = postagePackingCost.ToString();
    transactionDetails.subtotal = subtotal.ToString("0.00");
  3. We also need to specify an amount object comprising the total amount, currency and the details specified previously. Add this code to do that:
    var transactionAmount = new Amount();
    transactionAmount.currency = "GBP";           
    transactionAmount.total = total.ToString("0.00");
    transactionAmount.details = transactionDetails;
  4. Next we create the transaction object itself, as well as setting the amount object we created earlier and any items, we also provide a description for the transaction and an invoice number (in the example we generate a unique random identifier for the invoice, but normally this would correspond to an order id from a database record):
    var transaction = new Transaction();
     transaction.description = "Your order of Past Exam papers";
     transaction.invoice_number = Guid.NewGuid().ToString(); //this should ideally be the id of a record storing the order
     transaction.amount = transactionAmount;
     transaction.item_list = new ItemList
     {
         items = new List<Item> { examPaperItem }
     };
  5. Next we must specify a payer object - the only value you need to specify for the payer is its payment method, which unsurprisingly is PayPal! (It is possible to specify credit card here, however this would require us to collect the user's credit card and specify further information which is outside the scope of this tutorial):
    var payer = new Payer();
    payer.payment_method = "paypal";
  6. Once the user has clicked has been directed to PayPal, depending on whether they choose to continue or cancel the transaction, they will eventually be redirected back to our site. The pages they are directed to are specified in a RedirectUrls object. Add the following code and create appropriately named pages in your project so redirected users do not see a 404 error:
    var redirectUrls = new RedirectUrls();
    redirectUrls.cancel_url = "http://localhost:2506/Cancel.aspx";
    redirectUrls.return_url = "http://localhost:2506/CompletePurchase.aspx";
  7. Finally we put all the objects together to create a Payment object as follows:
    var payment = Payment.Create(apiContext, new Payment
    {
        intent = "sale",
        payer = payer,
        transactions = new List<Transaction> { transaction },
        redirect_urls = redirectUrls
    });
  8. In order to make the payment, the user will transfer to PayPal, input their credentials, and then confirm the purchase back on our site. In order to do that we need to keep track of the id of the Payment object. We can use Session to do this (This stores variables related to the user while the user still has an active session - long enough for them to visit the PayPal site and return):
    Session["paymentId"] = payment.id;
  9. The final part of this process is to find the URL to sent the user to from the links in the payment object. The process of providing navigation links in objects return from a REST call is known as Hypermedia as the Engine of Application State or HATEOAS. We do this with the following code:
    foreach (var link in payment.links)
    {
        if (link.rel.ToLower().Trim().Equals("approval_url"))
        {
            //found the appropriate link, send the user there
            Response.Redirect(link.href);
        }
    }
  10. At this stage it should be possible to click the Buy Now button and you will be sent to PayPal - which you should test. However as we have not yet implemented the CompletePurchase.aspx page logic the payment cannot yet be completed.

Implementing the complete payment page

  1. Open the CompletePurchase.aspx page and add the following code:
    <h2>Complete Your Purchase</h2>
    <asp:Button ID="btnConfirmPurchase" runat="server" Text="Confirm" />
    <asp:Literal ID="litInformation" runat="server"></asp:Literal>
  2. In split or design view, double click on the button to create an event handler. This will be used to confirm the payment
  3. Before adding code to the event handler we just created, we need to add a using statement (as we did in default.aspx) so that the PayPal API can be used, add this at the top of the file, under the existing using statements:
    using PayPal.Api;
  4. Return to the button event handler ad add code to authenticate with PayPal and get the ApiContext object (as you did earlier):
    var config = ConfigManager.Instance.GetProperties();
    var accessToken = new OAuthTokenCredential(config).GetAccessToken();
    var apiContext = new APIContext(accessToken);
  5. Next we will retrieve the PaymentId value from the session:
    var paymentId = Session["paymentId"].ToString();
  6. Assuming that we have been able to retrieve the paymentId value, we can create a new payment:
    if (!String.IsNullOrEmpty(paymentId))
    {
        //create a payment object with the paymentId from session
        var payment = new Payment() { id = paymentId };
    }
  7. We can now retrieve the payerId (this is passed to us by PayPal in the URL) and use it to create a payment execution object. With this and the Payment object, we can now execute the payment. Add the following code, inside the if statement:
    //retrieve the payerId from the querystring and use it to create a new payment execution object
    var payerId = Request.QueryString["PayerID"].ToString();
    var paymentExecution = new PaymentExecution() { payer_id = payerId };
    
    //execute the payment
    var executedPayment = payment.Execute(apiContext, paymentExecution);
    
    //inform the user
    litInformation.Text = "<p>Your order has been completed</p>";
    btnConfirmPurchase.Visible = false;
  8. You should now be able to test the whole process through to completion. Usually at payment completion, the order record would be updated to indicate that an order has been paid for and can now be shipped.
  9. The final stage would be to implement the cancel.aspx page, simply informing the user that their payment was cancelled.