Integrating a Desktop application with Pay Pal in c++

Introduction

This article was written following a need to integrate PayPal Express Checkout in a c++ Win32 application.

Background

I was thinking about integration in the background without any website other than the payment page as part of a desktop application in c++. Would it be possible to following the following scenario:

  1. Generate the invoice / sale and via REST API obtain some sort of unique ID for the transaction to come.

  2. Redirect to Paypal web site to a ad-hoc payment page, using the unique ID.

  3. In the background, check every few minutes, via REST API, if the payment was made.

The Solution

I have found a way and created a Proof of Concept (POC) for a built-in payment processing engine which allows you to accept payments from any credit card holder (regardless of being a PayPal customer) and pay for unlocking a software product or for specific features.

To process payments you need to apply as a PayPal developer and obtain your own PayPal credentials. You will then receive 2 sets of credentials. One for tests ("sandbox") and the other for real life.

First you should test the Sandbox to test the API.

I have created a PayPal class with one "init()" used for both "sandbox" and real life transactions.

Void InitPayPal(BOOL Sandbox, LPTSTR User, LPTSTR password, LPTSTR signature, LPTSTR successUrl, LPTSTR failedURL)

Sandbox – indicates whether you are testing your integration using PayPal's Sandbox account, or going live.

User – your PayPal user name

Password – your PayPal password

Signature – you PayPal signature

successUrl – a url leading to a web page which you wish to be shown after successful payment.

failedURL – a url leading to a web page which you wish to be shown after failed / cancalled payment.

The InitPayPal() function is straight forward:

void InitPayPal(BOOL Sandbox, LPTSTR User, LPTSTR password, LPTSTR signature, LPTSTR successUrl, LPTSTR failedURL, LPWSTR ProductName)

{

m_sandbox = Sandbox;

m_user = User;

m_password = password;

m_signature = signature;

m_SuccessURL = successUrl;

m_FailureURL = failedURL;

m_ProductName = ProductName;

CUR_CHAR = L"$";

SYSTEMTIME st;

GetSystemTime(&st);

g_tPayStart = CTime(st);

InitilizedPaypal = TRUE;

}

Initiating a payment

When you wish to initiate a payment from your program, you call the following function which I wrote which generally build a string (ExpChkoutStr) and use the following PayPal API call:

For all HTTP communication, I used The WinHTTP class was developed by Cheng Shi.

Here is how I send the initial request to the PayPal servers:

// Send string to PayPal server WinHttpClient WinClient1(ExpChkoutStr.GetBuffer()); WinClient1.SetRequireValidSslCertificates(false); // Now we get PayPal's response: WinClient1.SendHttpRequest(L"GET"); httpResponseContent1 = WinClient1.GetResponseContent(); CString strTransactionRet = UrlDecode(httpResponseContent1.c_str());

As you can see we are sending PayPal a long string we generate using another function. This function combined the credentials, the nature of the requested transaction, additional details all into a single string.

CString result;

result = (m_sandbox) ? PAYPAL_SANDBOX_HTTPS :

PAYPAL_REAL_HTTPS;

result += Q_USER;

result += m_user;

result += AND_PASSWORD;

result += m_password;

result += AND_SIGNATURE;

result += m_signature;

result += AND_PAYMENTAMOUNT;

result += strAmount;

result += L"&METHOD=SetExpressCheckout";

result += AND_RETURN_URL;

result += m_SuccessURL;

result += AND_CANCEL_URL;

result += m_FailureURL;

result += AND_VERSION;

result += L"&NOSHIPPING=1";

result += L"&ADDROVERRIDE=0&BRANDNAME=Secured Globe, Inc.";

result += L"&PAYMENTREQUEST_0_DESC=";

result += L"Item name: " + strUnits + L"(" + UnitName + L") "; result += L"Price: " + strAmount;

result += L"&NOTETOBUYER=Here you can add a note to the buyer";

Now, result will hold the string to be sent in the previous code block.

We then examine the result we have received back from PayPal:

The result from the PayPal server is a "token" used to figure out a one-time web page (LinkToOpen ) that must be opened in order for the end user to confirm the purchase:

// Extract token from response CString sToken = ExtractElement(strTransactionRet, L"TOKEN");

if (sToken == L"")

{

wprintf(L"Internal error: (Paypal):

no token was generated (%s)", strTransactionRet);

MessageBox(NULL, L"Internal payment processing error", L"", MB_OK);

return FALSE;

}

CString LinkToOpen = (m_sandbox) ? SANDBOX_PAYPAL_CHECKOUT : REAL_PAYPAL_CHECKOUT; LinkToOpen += L"&token="; LinkToOpen += sToken;

To extract elements from the PayPal server response, we wrote this small function:

CString ExtractElement(CString EntireString, CString ElementName)

{

CString result = L"";

CString WhatToFind = ElementName + L"=";

int foundToken = EntireString.Find(WhatToFind);

if (foundToken > -1)

{

int EndToken = EntireString.Find(L"&", foundToken);

if (EndToken != -1)

{

result = EntireString.Mid(foundToken + ElementName.GetLength()+1, EndToken - foundToken - ElementName.GetLength()-1);

}

}

return result;

}

Invoking a one-time web page

The next step is to open the default web browser with a one-time generated secure web page hosted by the PayPal server:

STARTUPINFO si;

PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));

si.cb = sizeof(si);

ZeroMemory(&pi, sizeof(pi));

CString command_line;

command_line.Format(L"cmd.exe /c start \"link\" \"%s\" ", LinkToOpen);

if (!CreateProcess(

NULL, // No module name (use command line)

command_line.GetBuffer(),

NULL, // Process handle not inheritable

NULL, // Thread handle not inhberitable

FALSE, // Set handle inheritance to FALSE

NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, // No creation flags

NULL, // Use parent's environment block

NULL, // Use parent's starting directory

&si, // Pointer to STARTUPINFO structure

&pi) // Pointer to PROCESS_INFORMATION structure )

{

wprintf(L"CreateProcess failed (%d).\n", GetLastError());

// At this stage you would want to mark this transaction as "failed"

return FALSE;

}

Then the rest is to maintain a small database of all pending transactions and follow up each of them until it is either succeed, failed, cancelled or if a timeout has passed.

User Interface

We have used a minimal UX integrated in our small DRM component, which looks like this:

Then the one-time web page will look like this:

Examples are from a real product Datattoo Recovery.

Featured Posts
Recent Posts
Archive
Search By Tags
Follow Us
  • Facebook Basic Square
  • Twitter Basic Square
  • Google+ Basic Square