Paypal Express Checkout with C# using Paypal web services

This is one of the common problems where while building an e-commerce portal we need to provide paypal payment support. In this post we will look into how we can do the express checkout using a paypal checkout button and then taking the user to paypal to authenticate the payment and then processing the payment followed by its notification.

This is one of the common problems where while building an e-commerce portal we need to provide paypal payment support. In this post we will look into how we can do the express checkout using a paypal checkout button and then taking the user to paypal to authenticate the payment and then processing the payment followed by its notification. All the code will be in C# and its a working and tested code on Sandbox.

Visit https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECGettingStarted to know what will be achieved as the outcome of this exercise.

Following are the steps to be followed in the Paypal payment development:

1) Sandbox Account creation and setup

2) Choosing one of the Paypal API interaction way, In this case its using SOAP services.

3) C# code and ASP.NET page code to initiate and complete the process.

 

We will now look closely into what I mean with each of these:

1) Sandbox Account Creation and Setup

Visit https://developer.paypal.com and create an account which will be your developer account using which we will create account simulators or role play users.

Once this is done, log into https://developer.paypal.com and start creating Test Accounts using Pre-Configured account. Provide the details asked and create Buyer, Seller and Pro accounts so that we can test it by playing these roles.

Accounts are now set and we can proceed with the coding and executing it.

 

2) The API interaction way we chose here is SOAP service. Since VS has a very good WSDL parser hence went through with this way and in your solution or web project add a reference to https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl and give it some name like PaypalSandboxService

We are now ready to consume it on our page and see it working.

3) Coding and using it on our page:

Here is aspx page with Checkout button:

<asp:ImageButton runat="server" ID="btnPaypal" AlternateText="checkout with paypal" ImageUrl="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" />

This will show the checkout with Paypal button on the page. Below is the onClick event handler code:


void btnPaypal_Click(object sender, ImageClickEventArgs e)
        {
            
            CustomSecurityHeaderType type = new CustomSecurityHeaderType();
            type.Credentials = new UserIdPasswordType()
            {
                Username = "xxxxx_123123123_biz_api1.gmail.com",
                Password = "--------",
                Signature = "AFcWxV21C7fd0v3bYYYRCpSSRl31A65G85Y3c.28ROij7FUFefzBgM02"
            };
            
            SetExpressCheckoutRequestDetailsType sdt = new SetExpressCheckoutRequestDetailsType();
            sdt.NoShipping = "1";
            PaymentDetailsType pdt = new PaymentDetailsType()
            {
                OrderDescription = "Payment Details Sushant",
                OrderTotal = new BasicAmountType()
                {
                    currencyID = CurrencyCodeType.USD,
                    Value = "100.00"
                }
            };

            sdt.PaymentDetails = new PaymentDetailsType[] { pdt };
            sdt.CancelURL = "http://localhost:56980/Default.aspx";
            sdt.ReturnURL = "http://localhost:56980/ExpressCheckoutSuccess.aspx";

            SetExpressCheckoutReq req = new SetExpressCheckoutReq()
            {
                SetExpressCheckoutRequest = new SetExpressCheckoutRequestType()
                {
                    SetExpressCheckoutRequestDetails = sdt,
                    Version = "60.0"
                }
            };

            var resp = paypalAAInt.SetExpressCheckout(ref type, req);
            if (resp.Errors != null && resp.Errors.Length > 0)
            {
                // errors occured
                throw new Exception("Exception(s) occured when calling PayPal. First exception: " +
                    resp.Errors[0].LongMessage);
            }

            Response.Redirect(string.Format("{0}?cmd=_express-checkout&token={1}",
                ConfigurationManager.AppSettings["PayPalSubmitUrl"], resp.Token));
            
        }



here paypal submit url looks like: <add key="PayPalSubmitUrl" value="https://www.sandbox.paypal.com/cgi-bin/webscr"/> in the web.config appsettings.

The ExpressCheckoutSuccess page is when the authentication at Paypal is successful and we want the user to do a final review and click on the Finish to get the actual transaction take place. For this we will show below the code of Express Checkout success page:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ExpressCheckoutSuccess.aspx.cs" Inherits="RYOARS.Web.ExpressCheckoutSuccess" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
        <br />
        <br />
        <asp:Button ID="finishTransactionButton" runat="server" 
            Text="Finish transaction!" onclick="finishTransactionButton_Click" />
    </div>
    </form>
</body>
</html>



and the C# code behind will look like in this case:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using RYOARS.Web.PaypalSandboxService;

namespace RYOARS.Web
{
    public partial class ExpressCheckoutSuccess : System.Web.UI.Page
    {
        PayPalAPIAAInterfaceClient client = new PayPalAPIAAInterfaceClient();

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                string token = Request.QueryString["token"];
                

                CustomSecurityHeaderType type = new CustomSecurityHeaderType();
                type.Credentials = new UserIdPasswordType()
                {
                    Username = "xxxxx_123123123_biz_api1.gmail.com",
                    Password = "---------",
                    Signature = "AFcWxV21C7fd0v3bYYYRCpSSRl31A65G85Y3c.28ROij7FUFefzBgM02"
                };

                // build getdetails request
                GetExpressCheckoutDetailsReq req = new GetExpressCheckoutDetailsReq()
                {
                    GetExpressCheckoutDetailsRequest = new GetExpressCheckoutDetailsRequestType()
                    {
                        Version = "60.0",
                        Token = token
                    }
                };

                // query PayPal for transaction details
                GetExpressCheckoutDetailsResponseType resp =
                    client.GetExpressCheckoutDetails(ref type, req);
                //UtilPayPalAPI.HandleError(resp);
                if (resp.Errors != null && resp.Errors.Length > 0)
                {
                    // errors occured
                    throw new Exception("Exception(s) occured when calling PayPal. First exception: " +
                        resp.Errors[0].LongMessage);
                }

                GetExpressCheckoutDetailsResponseDetailsType respDetails = resp.GetExpressCheckoutDetailsResponseDetails;


                // setup UI and save transaction details to session
                Label1.Text = string.Format(
                    "Dear {0} {1}, everything is set for {2} {3} transaction to take place. Click on button below to commit transaction",
                    respDetails.PayerInfo.PayerName.FirstName,
                    respDetails.PayerInfo.PayerName.LastName,
                    respDetails.PaymentDetails[0].OrderTotal.Value,
                    respDetails.PaymentDetails[0].OrderTotal.currencyID
                );

                Session["CheckoutDetails"] = resp;
            }
        }

        protected void finishTransactionButton_Click(object sender, EventArgs e)
        {
            // get transaction details
            GetExpressCheckoutDetailsResponseType resp = Session["CheckoutDetails"] as GetExpressCheckoutDetailsResponseType;

            CustomSecurityHeaderType type = new CustomSecurityHeaderType();
            type.Credentials = new UserIdPasswordType()
            {
                Username = "xxxxx_123123123_biz_api1.gmail.com",
                Password = "--------",
                Signature = "AFcWxV21C7fd0v3bYYYRCpSSRl31A65G85Y3c.28ROij7FUFefzBgM02"
            };

            // prepare for commiting transaction
            DoExpressCheckoutPaymentReq payReq = new DoExpressCheckoutPaymentReq()
            {
                DoExpressCheckoutPaymentRequest = new DoExpressCheckoutPaymentRequestType()
                {
                    Version = "60.0",
                    DoExpressCheckoutPaymentRequestDetails = new DoExpressCheckoutPaymentRequestDetailsType()
                    {
                        Token = resp.GetExpressCheckoutDetailsResponseDetails.Token,
                        PaymentAction = PaymentActionCodeType.Sale,
                        PaymentActionSpecified = true,
                        PayerID = resp.GetExpressCheckoutDetailsResponseDetails.PayerInfo.PayerID,
                        PaymentDetails = new PaymentDetailsType[] {
                            new PaymentDetailsType()
                            {
                                OrderTotal = new BasicAmountType()
                                {
                                    currencyID = CurrencyCodeType.USD,
                                    Value = "100.0"
                                }
                            }
                        }
                    }
                }
            };

            // commit transaction and display results to user
            DoExpressCheckoutPaymentResponseType doResponse =
                client.DoExpressCheckoutPayment(ref type, payReq);

            if (doResponse.Errors != null && doResponse.Errors.Length > 0)
            {
                // errors occured
                throw new Exception("Exception(s) occured when calling PayPal. First exception: " +
                    doResponse.Errors[0].LongMessage);
            }

            Label1.Text = "Payment was successfully processed!";
            finishTransactionButton.Visible = false;
        }
    }
}



Now, you code is ready to go and work fine. We have tested this with our test account and it works just smoothly. So, its very easy to integrate paypal express checkout in your page.

We will also look into Direct payment where your code behind or C# need to directly need to charge a customer based on its information and when certain condition is met. We will look into this in the next post on the same line.

Till then, try this one!!

- bye for now

Posted by: sushant.pandey

Categories: ASP.NET, C#, Paypal

Tags: , , , ,

Comments (26) -

Mike Netherlands

December 27. 2011 05:03

Mike
Thanks for this article, this is really helpful.
I have one question however, "paypalAAInt" doesn't seem to exist within the API?
The only thing I can find that remotely seems familiar is "PayPalAPIAAInterface"...

Am I doing something wrong here?

John Canada

January 26. 2012 09:07

John
I am able to submit a basic order without any problems, if I include a number of items and an order total.
I am now trying to list tax and/or shipping separately on the PayPal screen, and no matter what I do I get the error "Order total does not match the items in the cart" I have simplified the code to the following:

            reqDetails.OrderTotal = new BasicAmountType();
            reqDetails.OrderTotal.currencyID = CurrencyCodeType.USD;
            reqDetails.OrderTotal.Value = "349.00";

            reqDetails.PaymentAction = PaymentActionCodeType.Sale;
            reqDetails.PaymentActionSpecified = true;

            PaymentDetailsType paymentDetails = new PaymentDetailsType();
            paymentDetails.ShippingTotal = new BasicAmountType();
            paymentDetails.ShippingTotal.currencyID = CurrencyCodeType.USD;
            paymentDetails.ShippingTotal.Value = "10.00";

            paymentDetails.TaxTotal = new BasicAmountType();
            paymentDetails.TaxTotal.currencyID = CurrencyCodeType.USD;
            paymentDetails.TaxTotal.Value = "39.00";

            PaymentDetailsItemType item1 = new PaymentDetailsItemType();
            item1.Amount = new BasicAmountType();
            item1.Amount.currencyID = CurrencyCodeType.USD;
            item1.Amount.Value = "100.00";
            item1.Name = "Jewelry Store Order #1";
            item1.Number = "ABC001";
            item1.Quantity = "1";
            item1.Description = "Thing 1";
            item1.Tax = new BasicAmountType();
            item1.Tax.currencyID = CurrencyCodeType.USD;
            item1.Tax.Value = "13.00";

            PaymentDetailsItemType item2 = new PaymentDetailsItemType();
            item2.Amount = new BasicAmountType();
            item2.Amount.currencyID = CurrencyCodeType.USD;
            item2.Amount.Value = "200.00";
            item2.Name = "Jewelry Store Order #1";
            item2.Number = "DEF007";
            item2.Quantity = "1";
            item2.Description = "Thing 2";
            item2.Tax = new BasicAmountType();
            item2.Tax.currencyID = CurrencyCodeType.USD;
            item2.Tax.Value = "26.00";

I have tried with every combination of shipping only, item tax only, total tax only, and adjusted the total to everything I can think of, IT NEVER WORKS! I get no other feedback other than the error, so its very difficult to trouble-shoot. Can someone please suggest what I might be doing wrong?

target21 United States

March 8. 2012 00:04

target21
I get a timeout exception when I call SetExpressCheckout:

{"Timeout processing request"}

Any ideas?

Elferone Canada

May 2. 2012 06:36

Elferone
@Mike => There is a line missing at the beginning of the method:
PayPalAPIAAInterfaceClient paypalAAInt = new PayPalAPIAAInterfaceClient()

@John => Specify the ItemTotal property if specifying ShippingTotal or other.. This should solve your problem.

Hope this helps!

mandar India

May 9. 2012 07:45

mandar
I Get Version not supported error on final page.

sachin United States

June 29. 2012 05:57

sachin
Hello, i refer you code of void btnPaypal_Click in my class library

where  i am calling method ............ end of process it shows success full & gives token to me .. but whn i am checking it in seller & buyer account the amount is not credited or debited ... i am using sandbox account ... is their any time limit to credit / debit amount

Ritesh Jaiswal India

July 2. 2012 00:12

Ritesh Jaiswal
Hi Sachin

There is no time limit to credit / debit amount. Actually when the authentication at Paypal is successful and you get token then your page is redirect to successful page where you to do a final review and click on the Finish to get the actual transaction take place. For the code of successful page  go to the ExpressCheckoutSuccess page code which is mention above or  go to  this link : blogs.effectlabs.com/.../...ypal-web-services.aspx

Roberto Torres Puerto Rico

August 21. 2012 22:51

Roberto Torres
Hi,

I'm trying to implement this tutorial on my web project. I've been trying to do so for about 3 days. The problem I'm having is that the response object always return null. For example:

var resp = paypalAAInt.SetExpressCheckout(ref type, req);
if (resp.Errors != null && resp.Errors.Length > 0)
{
    // errors occured
    throw new Exception("Exception(s) occured when calling PayPal. First exception: " +
    resp.Errors[0].LongMessage);
}

Response.Redirect(string.Format("{0}?cmd=_express-checkout&token={1}", ConfigurationManager.AppSettings["PayPalSubmitUrl"], resp.Token));


In this example resp.Token is always null. I've done multiple searches in google but nothing came up. Please let me know how to solve this.

Thanks.

Roberto Torres Puerto Rico

August 22. 2012 07:54

Roberto Torres
Hi,

I'm having trouble implementing this in my web project. I did everything posted here but the response never parse into the corresponding object, making the object properties null. For example:

     var resp = paypalAAInt.SetExpressCheckout(ref type, req);
            if (resp.Errors != null && resp.Errors.Length > 0)
            {
                // errors occured
                throw new Exception("Exception(s) occured when calling PayPal. First exception: " +
                    resp.Errors[0].LongMessage);
            }

            Response.Redirect(string.Format("{0}?cmd=_express-checkout&token={1}",
                ConfigurationManager.AppSettings["PayPalSubmitUrl"], resp.Token));


In the example above the object property resp.Token is always null. Any ideas why this is happening? This also happen in the GetExpressCheckoutDetails method.

Thanks

Anuj India

August 23. 2012 07:10

Anuj
I got an error when it redirected to sandbox.paypal.com.
i just browsed the first page.

"This transaction is invalid. Please return to the recipient's website to complete your transaction using their regular checkout flow." : on Sandbox.

Chhatrapati India

October 17. 2012 05:47

Chhatrapati

Hi,

same problem i am facing
token is avail in res.Any.InnerText but res.Token is null

I'm having trouble implementing this in my web project. I did everything posted here but the response never parse into the corresponding object, making the object properties null. For example:

     var resp = paypalAAInt.SetExpressCheckout(ref type, req);
            if (resp.Errors != null && resp.Errors.Length > 0)
            {
                // errors occured
                throw new Exception("Exception(s) occured when calling PayPal. First exception: " +
                    resp.Errors[0].LongMessage);
            }

            Response.Redirect(string.Format("{0}?cmd=_express-checkout&token={1}",
                ConfigurationManager.AppSettings["PayPalSubmitUrl"], resp.Token));

In the example above the object property resp.Token is always null. Any ideas why this is happening? This also happen in the GetExpressCheckoutDetails method.

Thanks

Brotin India

October 31. 2012 02:21

Brotin
In the folder for PayPal Web Reference open the Reference.cs file in a text editor and search for "System.Xml.XmlElement Any"

You will notice code like:
[System.Xml.Serialization.XmlElementAttribute(Order=6)]
        public System.Xml.XmlElement Any {
            get {
                return this.anyField;
            }
            set {
                this.anyField = value;
                this.RaisePropertyChanged("Any");
            }
        }

Now replace [System.Xml.Serialization.XmlElementAttribute(Order=6)] with [System.Xml.Serialization.XmlIgnoreAttribute()] and run your application after recompiling.

You will now see resp.Token as populated with the required value Smile

Rui Portugal

December 20. 2012 02:07

Rui
Hi everyone.

In my code i have a exception like this setExpressCheckout and SSL/TLS error abort why?

Tushar India

December 20. 2012 06:47

Tushar
I got an error an "doesn't exists namespace RYOARS.Web" so how can i get this namespace ....? please help me  it's urgent..........

zeeshan India

December 20. 2012 07:01

zeeshan
@Tushar, it seems to be that you haven't adjusted the namespaces properly after pasting the code in your app.
if you have a keen look at the namespace in code, Ryoars.Web is the namespace of the application to which this code belongs.
if you do a Ctrl+F on this page and try to find out where "Ryoars.Web" is mentioned, then you will find 6 results, 3 being mentioned in the app, 1 being mentioned in your comment and 2 being mentioned in my comment.

Tiep Vietnam

December 21. 2012 19:42

Tiep
Hi everyone.
In my code i have a exception
"Could not establish secure channel for SSL/TLS with authority 'api-aa.sandbox.paypal.com'."
please help me

Carena Singapore

January 13. 2013 20:59

Carena
Hi Peeps,
I also encounter the same problem like "Could not establish secure channel for SSL/TLS with authority 'api-aa.sandbox.paypal.com".
But finally i can overcome by changing some lines in web.config :
<endpoint address="https://api-3t.sandbox.paypal.com/2.0/"; binding="basicHttpBinding"
                bindingConfiguration="PayPalAPISoapBinding" contract="PayPalSandboxService.PayPalAPIInterface"
                name="PayPalAPI" />
            <endpoint address="https://api-3t.sandbox.paypal.com/2.0/"; binding="basicHttpBinding"
                bindingConfiguration="PayPalAPIAASoapBinding" contract="PayPalSandboxService.PayPalAPIAAInterface"
                name="PayPalAPIAA" />

Hope it helps Smile

Anil India

January 16. 2013 23:38

Anil
Error  1  The type or namespace name 'PayPalAPIAAInterfaceClient' could not be found (are you missing a using directive or an assembly reference?)  D:\Anil\CheckOutTest\ExpressCheckoutSuccess.aspx.cs  9  7  D:\Anil\CheckOutTest\

Hi i gone through your code its very helpful for all.. but when run the application i am getting above error
please suggest me...

Shantanu Shukla India

January 22. 2013 07:26

Shantanu Shukla
@Anil: have you included the namespace
using YourProject.PaypalSandboxService;

Pieroni United Kingdom

January 24. 2013 05:54

Pieroni
Brotin's answer looks somewhat familiar to another post that I answered way back in 2010 on the PayPal developer forums.

www.x.com/.../paypal-api-aa-and-net-wcf-undeserialized-fields

Now I'm not saying this has been copied however it took me a solid week to debug and provide a solution for this problem.

The proposed solution to add [System.Xml.Serialization.XmlElementAttribute(Order=6)] may well work for the token property, however this is not a robust solution as the Any property is defined in a base class that is used by other response classes which may have more than 5 properties. This may result in other responses having null values or even worse failing to serialize at all. In the post (link above) the solution is to add [System.Xml.Serialization.XmlIgnoreAttribute()] to the Any property.

PR Bulgaria

February 18. 2013 13:45

PR
Hi,

I receive the same error "The type or namespace name 'PayPalAPIAAInterfaceClient' could not be found (are you missing a using directive or an assembly reference?)"
But I added this:
using YourProject.PaypalSandboxService;

Can you help me?
Thanks!

Naveed Hamid United Kingdom

September 13. 2013 05:49

Naveed Hamid
resp.Token is null because Visual Studio 2010 is storing this value in the incorrect node I got this to work by changing resp.Token to resp.Any.InnerText rather then changing the Reference.cs file

Puru Australia

January 30. 2014 17:28

Puru
Thank you very much for the code sample, you ended days of my search....

David Slovenia

February 6. 2014 06:00

David
Authentication works, I get valid token value, but it stops in function:

GetExpressCheckoutDetailsResponseType resp =
                    client.GetExpressCheckoutDetails(ref type, req);



with error: Invalid token.
Any idea?

David Slovenia

February 11. 2014 05:58

David
Error when finishing transaction:
Express Checkout PayerID is missing.
Any idea?

kinshuk India

February 21. 2014 03:32

kinshuk
Hello ,

I am getting PayPalAPIAAInterfaceClient  class , can you tell me about PayPalAPIAAInterfaceClient  call. and please provide me.

Pingbacks and trackbacks (1)+

Add comment

  Select your country

biuquote
  • Comment
  • Preview
Loading