June 11, 2015

Sage Pay Server Integration using Microsoft.NET

Sage Pay is one of the leading payment gateways in the UK market. To offer more flexibility, it’s available in two integration forms, which are called “Form integration” and “Server Integration.” Both are PCI compliant.

This blog post will help Microsoft.NET developers to integrate the Sage Pay payment gateway (protocol v3.0) along with some of the integration problems and solutions that will be helpful in quickly integrating. Using the steps below, the developer can integrate iFrame solution of Server integration in their website though utilizing “SagePay.IntegrationKit.DotNet.dll” published by Sage Pay.

Sage Pay Server Integration talks directly to a client web server through an encrypted channel, exchanging digitally signed messages to register the transaction and notify about the authorisation result. No sensitive information is sent through the browser and the customer is redirected to Sage Pay to enter card details, etc. Therefore, the client website does not need to store these sensitive details.

Pre-requisites

The client website should be running on IIS with a fully qualified domain name or on a URL which is externally resolvable so that Sage Pay APIs will be able to send/receive requests to/from client. The client website will be either running on Port 80 in case of HTTP protocol or on 443 in case of HTTPS protocol.

It is recommended that the client website use the HTTPS protocol in LIVE environment.

You will need to have a Sage Pay test account to log in into the test website (https://test.sagepay.com/mysagepay/login.msp), and review the test transactions.

Steps to integrate Sage Pay using the ‘Dot Net Integration Kit’:

  1. Download and add reference of “SagePayLib” class library project in your web project. To download the class library project click here
  2. Add iFrame control on the .aspx page (as below), on which it is required to load Sage Pay iFrame

    <iframe id="ltrlIframe" runat="server" style="width: 700px; height: 600px"></iframe>
  3. Copy and paste the following method in .aspx.vb page and call it to load Sage Pay iFrame content to render
    Private Sub LoadSagePayIframe()
        	'Set billing and Shipping Address
     
        	Dim orderRequestDetails As New SagepayRequestEntity()
        	With orderRequestDetails
                .Billing.FirstNames = "FirstName" 'dummy entry
                .Billing.Surname = "Surname" 'dummy entry
                .Billing.Address1 = "Address1" 'dummy entry
                .Billing.Address2 = "" 'dummy entry
                .Billing.City = "City" 'dummy entry
                .Billing.PostCode = "W1A 1BL" 'dummy entry
                .Billing.Country = "GB" 'dummy entry
                .Billing.Phone = "44 (0)7933 000 000" 'dummy entry
                .Billing.Email = "customer@example.com" 'dummy entry
     
                .Shipping.FirstNames = .Billing.FirstNames 'dummy entry
                .Shipping.Surname = .Billing.Surname 'dummy entry
                .Shipping.Address1 = .Billing.Address1 'dummy entry
                .Shipping.Address2 = .Billing.Address2 'dummy entry
                .Shipping.City = .Billing.City 'dummy entry
          	  .Shipping.PostCode = .Billing.PostCode 'dummy entry
                .Shipping.Country = .Billing.Country 'dummy entry
                .Shipping.Phone = .Billing.Phone 'dummy entry
                .Shipping.Email = .Billing.Email 'dummy entry
     
                .Amount = 10 'dummy entry
                .ProductDescription = "Test Product" 'dummy entry
                .NotificationUrl = Response.ApplyAppPathModifier("SagePayNotification.aspx") ' & Server.UrlEncode(String.Format("?id={0}", Id)) (include any querystring if required)
     
        	End With
        	Dim requestGenerated As String = String.Empty
        	Dim responseGenerated As String = String.Empty
     
        	'get the iframe url
        	Dim url As String = (New IntegrationHelper()).GetIframeUrl(orderRequestDetails, requestGenerated, responseGenerated)
     
        	'WriteLogTrace(requestGenerated)
        	'WriteLogTrace(responseGenerated)
     
        	'load the iframe
            ltrlIframe.Attributes.Add("src", IIf(String.IsNullOrWhiteSpace(url), String.Empty, url))
    	End Sub
  4. Add new “SagePayNotification.aspx” page, then copy and paste the following code in code behind (replace Page_Load event code with following code)

     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        	Dim tranResp As New IntegrationHelper()
        	Dim sagePayResponse As SagepayResponseEntity = tranResp.GetTransactionResponse()
        	Dim postDetailsStatus As Boolean = False
        	If sagePayResponse IsNot Nothing Then
     
            	'WriteLogTrace(Request.QueryString.ToString())
            	'WriteLogTrace("sagePayResponse.TransactionStatus::" & sagePayResponse.TransactionStatus)
            	'WriteLogTrace("sagePayResponse.Status::" & sagePayResponse.Status)
            	If sagePayResponse.TransactionStatus = "OK" Then
                    'set the flag on successful transaction.
                    'Note that ASP.net session is accessible on this page only in case of cookieless session used
                    Session("TxConfirmed") = "1"
                    'update the transaction response entity
    	            Dim sagePayTxEntity As SagePayTransactionEntity = Session("sagePayTxEntity")
                    With sagePayTxEntity
                        .VPSTxId = IIf(String.IsNullOrWhiteSpace(sagePayResponse.VpsTxId), "", sagePayResponse.VpsTxId)
                        .TxAuthNo = IIf(String.IsNullOrWhiteSpace(sagePayResponse.TxAuthNo), "", sagePayResponse.TxAuthNo)
                        .CAVV = IIf(String.IsNullOrWhiteSpace(sagePayResponse.Cavv), "", sagePayResponse.Cavv)
                        .ThreeDSecureStatus = IIf(String.IsNullOrWhiteSpace(sagePayResponse.ThreeDSecureStatus), "", sagePayResponse.ThreeDSecureStatus)
                    End With
     
                    Session("sagePayTxEntity") = sagePayTxEntity
                    postDetailsStatus = True
            	End If
            	Dim sagePayResultUrl As String = SagePaySettings.SiteFqdn & Response.ApplyAppPathModifier("SagePayResult.aspx")
     
                Response.Clear()
                Response.ContentType = "text/plain"
                Response.Write(String.Format("Status={0}{1}", sagePayResponse.Status, Environment.NewLine))
                Response.Write(String.Format("RedirectURL={0}?Status={1}&VendorTxCode={2}&poststatus={3}&statusmsg={4}",
                                             sagePayResultUrl, sagePayResponse.TransactionStatus, sagePayResponse.VendorTxCode,
                                             IIf(postDetailsStatus, "1", "0"), sagePayResponse.StatusDetail))
        	Else
                Response.Write("error")
        	End If
    	End Sub
  5. Add new “SagePayResult.aspx” page, copy and paste the following code in code behind (replace Page_Load event code with following code)
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        	If Request.QueryString("Status") = "OK" Then
            	If (Request.QueryString("poststatus") = "0") Then
                    lblMessage.Text = "Was unable to post the payment transaction"
            	Else
                    If Session("TxConfirmed") = "1" Then
                        Dim redirectUrl As String = String.Empty
                        'Confirm order or post details
                        Dim sagePayTxEntity As SagePayTransactionEntity = Session("sagePayTxEntity")
                        'log succesful transaction details for auditing
                        Session("TxConfirmed") = "0"
                    End If
     
            	End If
        	Else
                lblMessage.Text = Request.QueryString("statusmsg")
        	End If
     
    	End Sub
  6. Web.config changes

  1. Add new “SagePayConfiguration” ConfigSection (register it through adding following line of code under ‘configuration -> configSections’ section)
    <section name="SagePayConfiguration" type="SagePayLib.SagePayConfiguration" />
  2. Copy & paste below code within ‘Configuration’

    <SagePayConfiguration>
        <!--Mandatory 	
        Set to TEST for the Test Server and LIVE for the live environment-->
        <add key="sagepay.api.env" value="TEST" />
        <add key="sagepay.api.messageLoggerName" value="com.sagepay" />
        <add key="sagepay.api.messageLoggerLevel" value="debug" />
     
        <!--Transaction Settings -->
        <add key="sagepay.api.protocolVersion" value="3.00" />
        <add key="sagepay.kit.vendorName" value=" " />
        <add key="sagepay.kit.fullUrl" value="" />
        <add key="sagepay.kit.currency" value="GBP" />
     
        <!--Fully Qualified Domain Name of your server.
        This should start http:// or https:// and should be the name by which our servers can call back to yours-->
        <add key="sagepay.kit.siteFqdn.LIVE" value="" />
        <add key="sagepay.kit.siteFqdn.TEST" value=" " />
     
        <add key="sagepay.kit.defaultTransactionType" value="PAYMENT" />
     
        <!--0 = If AVS/CV2 enabled then check them.  If rules apply, use rules (default).
        1 = Force AVS/CV2 checks even if not enabled for the account. If rules apply, use rules.
        2 = Force NO AVS/CV2 checks even if enabled on account.
        3 = Force AVS/CV2 checks even if not enabled for the account but DON'T apply any rules.-->
        <add key="sagepay.kit.applyAvsCv2" value="2" />
     
        <!--0 = If 3D-Secure checks are possible and rules allow, perform the checks and apply the authorisation rules. (default)
        1 = Force 3D-Secure checks for this transaction if possible and apply rules for authorisation.
        2 = Do not perform 3D-Secure checks for this transaction and always authorise.
        3 = Force 3D-Secure checks for this transaction if possible but ALWAYS obtain an auth code, irrespective of rule base.-->
        <add key="sagepay.kit.apply3dSecure" value="2" />
     
        <!--For charities registered for Gift Aid, set to 1 to display the Gift Aid check
        box on the payment pages, or else 0-->
        <add key="sagepay.kit.allowGiftAid" value="0" />
     
        <add key="sagepay.kit.collectRecipientDetails" value="false"/>
        <add key="sagepay.kit.accountType" value="" />
     
        <!--Optional setting. If you are a Sage Pay Partner and wish to flag transactions with your unique partner id it should be set here-->
        <add key="sagepay.kit.partnerID" value=""/>
     
        <!--Use this key to send surcharge xml and override the default values set for your account. See the protocol documents for further
       	explanation on using the surcharge xml-->
        <add key="sagepay.kit.surchargeXML" value="&lt;surcharges&gt;&lt;surcharge&gt;&lt;paymentType&gt;VISA&lt;/paymentType&gt;&lt;percentage&gt;0&lt;/percentage&gt;&lt;/surcharge&gt;&lt;/surcharges&gt;" />
     
        <!--The Sage Pay server URLs to which customers will be sent for payment for each environment-->
        <add key="sagepay.api.serverPaymentUrl.LIVE" value="https://live.sagepay.com/gateway/service/vspserver-register.vsp" />
     
        <add key="sagepay.api.serverPaymentUrl.TEST" value="https://test.sagepay.com/gateway/service/vspserver-register.vsp" />
     
      </SagePayConfiguration>

Quick Implementation Points:

  1. Update the value of “sagepay.api.env” key to “LIVE” if running on live environment, or to “TEST” if running in test environment
  2. Assign valid vendor name to the value of “sagepay.kit.vendorName” key
  3. In case of test environment, assign valid fully qualified domain name of your server to the value of “sagepay.kit.siteFqdn.TEST” key

  4. In case of test environment assign valid fully qualified domain name of your server to the value of “sagepay.kit.siteFqdn.LIVE” key

  5. Add the IP of the server on which the websites need to be hosted to the Valid IPs section in the Sage Pay vendor account so that Sage Pay will provide a response to the server properly

    While posting the data, the details should contain the valid values and data should match the following format:

    Name Mandatory Max Length Description
    First Names Yes 20 Chars
    Surname Yes 20 Chars
    Address 1 Yes 100 Chars
    Address 2 No 100 Chars
    City Yes 40 Chars
    Post Code Yes 10 Chars The Billing Post Code can be blank for countries that do not have postcodes (e. g. Ireland) but is required in all countries that do have them.The Post Code value can contain alphabets, numbers, hyphens, and spaces.
    Country Yes 2 Chars
    State No 2 Chars The Billing State becomes mandatory when the Billing Country is set to US.
    Phone No 20 Chars
    Email No 255 Chars
    Amount Yes Amount for the transaction should contain 2 decimal places where appropriate (e. g. 5.10 or 3.29. Values such as 3.235 will be rejected).Minimum for no minor unit currencies like JPY is 1.Amounts must be in the UK currency format. The period must be used to indicate the decimal place. The comma must only be used to separate groups of thousands.

The following screenshot shows the content of Sage Pay iFrame on successful transaction registration

screenshot sage pay

References:

https://www.sagepay.co.uk/