Click here to Skip to main content
13,408,239 members (44,814 online)
Click here to Skip to main content
Add your own
alternative version

Stats

2.6K views
4 bookmarked
Posted 12 Jan 2018

Integrating with PayPal smoothly

, 12 Jan 2018
Rate this:
Please Sign up or sign in to vote.
How to easily integrate and interface with PayPal Express Checkout API from a Windows c++ application

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 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);
// 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.

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Michael Haephrati
CEO Secured Globe, Inc.
United States United States
Michael Haephrati, CEO and co-founder of Secured Globe, Inc. Worked on many ventures starting from HarmonySoft, designing Rashumon, the first Graphical Multi-lingual word processor for Amiga computer. During 1995-1996 he worked as a Contractor with Apple at Cupertino.



You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.180221.1 | Last Updated 12 Jan 2018
Article Copyright 2018 by Michael Haephrati
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid