Reputation: 621
I am currently working (for the first time) with Paypal Payments Pro. I have a registered business account, API username, password, and signature. I also have a (pretty much) complete checkout form. But I have a few issues. The website is for political contributions, meaning I need to collect additional information like Employer and Job title. I would like to have this information sent to and stored on PayPal's servers, and I am not entirely sure how to do this, so I started doing some research. I now have a basic paypal php form that I think works:
<?php
/** DoDirectPayment NVP example;
*
* Process a credit card payment.
*/
$environment = 'sandbox'; // 'sandbox' or 'beta-sandbox' or 'live'
/**
* Send HTTP POST Request
*
* @param string The API method name
* @param string The POST Message fields in &name=value pair format
* @return array Parsed HTTP Response body
*/
function PPHttpPost($methodName_, $nvpStr_) {
global $environment;
// Set up your API credentials, PayPal end point, and API version.
$API_UserName = urlencode('My Username'); // set your api username
$API_Password = urlencode('My Password'); // set your api password
$API_Signature = urlencode('My Signature'); // set your api Signature
$API_Endpoint = "https://api.sandbox.paypal.com";
if("sandbox" === $environment || "beta-sandbox" === $environment) {
$API_Endpoint = "https://api.$environment.paypal.com";
}
$version = urlencode('51.0');
// Set the curl parameters.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
// Turn off the server and peer verification (TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
// Set the API operation, version, and API signature in the request.
$nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";
// Set the request as a POST FIELD for curl.
curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
// Get response from the server.
$httpResponse = curl_exec($ch);
if(!$httpResponse) {
exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
}
// Extract the response details.
$httpResponseAr = explode("&", $httpResponse);
$httpParsedResponseAr = array();
foreach ($httpResponseAr as $i => $value) {
$tmpAr = explode("=", $value);
if(sizeof($tmpAr) > 1) {
$httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
}
}
if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
}
return $httpParsedResponseAr;
}
// Set request-specific fields.
$paymentType = urlencode('Sale'); // 'Authorization' or 'Sale'
$firstName = urlencode($_POST['firstName']);
$lastName = urlencode($_POST['lastName']);
$creditCardType = urlencode($_POST['card_type']);
$creditCardNumber = urlencode($_POST['card_number']);
$expDateMonth = $_POST['11'];
// Month must be padded with leading zero
$padDateMonth = urlencode(str_pad($expDateMonth, 2, '0', STR_PAD_LEFT));
$expDateYear = urlencode($_POST['18']);
$cvv2Number = urlencode($_POST['cvv']);
$address1 = urlencode($_POST['address1']);
$address2 = urlencode($_POST['address2']);
$city = urlencode($_POST['customer_city']);
$state = urlencode($_POST['customer_state']);
$zip = urlencode($_POST['zip']);
$country = urlencode($_POST['state']); // US or other valid country code
$amount = urlencode($_POST['50']);
$currencyID = urlencode('USD'); // or other currency ('GBP', 'EUR', 'JPY', 'CAD', 'AUD')
// Add request-specific fields to the request string.
$nvpStr = "&PAYMENTACTION=$paymentType&AMT=$amount&CREDITCARDTYPE=$creditCardType&ACCT=$creditCardNumber".
"&EXPDATE=$padDateMonth$expDateYear&CVV2=$cvv2Number&FIRSTNAME=$firstName&LASTNAME=$lastName".
"&STREET=$address1&CITY=$city&STATE=$state&ZIP=$zip&COUNTRYCODE=$country&CURRENCYCODE=$currencyID";
// Execute the API operation; see the PPHttpPost function above.
$httpParsedResponseAr = PPHttpPost('DoDirectPayment', $nvpStr);
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {
exit('Direct Payment Completed Successfully: '.print_r($httpParsedResponseAr, true));
} else {
exit('DoDirectPayment failed: ' . print_r($httpParsedResponseAr, true));
}
?>
I found this sample online and it's the first I was able to get functioning. The issue is I'm not entirely sure where I can store the extra information to send to paypal. Another issue is that on the PayPal site, it says never send a live transaction using POST, as it is not secure. So what should I use? I ahve SSL and the content should be encrypted. Furthermore, how can I prevent a user from navigating directly to this page and getting my credentials? I have seen people suggest placing the php file outside of the webroot, would this work for me?
I am aware that I need to add validity checks to the actual php file, which once I get the basic payment things working I can add.
Another issue I had was passing this extra information on to the paypal express checkout page. Is it possible to do that? I am fairly certain I saw a post about that on here, but I can no longer seem to find it.
In short:
How do I securely transmit data to PayPal?
How do I transmit extra data (Employer, Job Title, etc.) to PayPal?
How do I keep my API information secure?
How can I send extra data if the user chooses to use PayPal express?
I'm very sorry if any of this information is readily available I really have been doing as much research as I can:
It seems I'm just in a bit over my head at the moment and I would really appreciate any help I can get. Links to documentation, explanations of how certain things should work. Really, and help would be appreciated.
Thanks StackOverflow!
Upvotes: 0
Views: 181
Reputation: 2206
With all respect, I would encourage you to make two significant changes in your approach.
First, I would recommend using one of PayPal's SDKs rather than writing everything yourself from the URL upwards using curl. You are making like hard on yourself when you don't need to. See e.g. https://github.com/paypal/codesamples-php/blob/master/Merchant/sample/code/DoDirectPayment.php
Second, PayPal is not your database; you need one of your own to store your extra information (such as employer and job title). You can do some awkward things to shove a little bit of your data into pass-through fields on a PayPal transaction but you will likely have issues and be unsatisfied with this approach. The accepted solution to this is to generate your own transaction record (call it donation, or invoice, or whatever) and store it in your db, and pass a unique identifier of this record from your database to PayPal as the PayPal "invoice_id". This has the additional benefit of PayPal being able to catch potential errors on your side that could lead to double-charging someone twice for the same transaction.
As for your specific questions:
How do I securely transmit data to PayPal?
Use https (which you do). Preferably via an SDK which helps prevent a variety of of other ways to leak information which you could inadvertently do if you code it all yourself.
How do I transmit extra data (Employer, Job Title, etc.) to PayPal?
Don't; see above.
How do I keep my API information secure?
Keep it only on your server (except when sending it to PayPal), and secure your server properly. Use https to secure the communication between your server and PayPal (which PayPal will enforce anyway).
How can I send extra data if the user chooses to use PayPal express?
Both Express Checkout and DoDirectPayment support an invoice field.
Upvotes: 1