PayPal Direct Payment API Component
Useful component that provides a wrapper for PayPal's Direct Payment API, allowing any cake based application to accept payments via Direct Payment (processing credit cards and payments without leaving your website) and Express Checkout (allowing users to use their PayPal account to pay)
Index
Introduction
While building a large CakePHP based application I found myself needing to integrate PayPal Direct Payment API with CakePHP. For those of you who don't know this API here's a short statement from PayPal's website describing its main objective:
Direct Payment API offers you direct credit card payment processing capability through PayPal. For credit card transactions, customers stay on your website as PayPal processes the payment in the background.
Now, I have built PayPal Direct Payment API applications in the past, but I wanted to bake paypal the proper cakish way. Furthermore, as PayPal's TOS states, PayPal's business rules require that sites that offer Direct Payment API (credit card processing without leaving your website) also must offer Express Checkout Payment (where buyer gets transferred to PayPal's website to confirm the order and then taken back to your website.) It is a bummer, but it is mandatory.
It is also important to know that only people with bank accounts in the US can apply for Website Payments Pro (the PayPal service that allows you to use Direct Payment API.) While this may discourage some bakers from even trying the API, you should now that PayPal offers a Sandbox environment to allow you to test every aspect of the integration.
For that purpose I've created a CakePHP component that provides a wrapper for PayPal's Direct Payment API. I have tested it with CakePHP 1.1.10.3825 running on:
- Apache 2, Windows XP, PHP 4.4.4
- Apache 2, Debian Linux, PHP 5.2.0
Pre-requisites
PEAR and PayPal Direct Payment API
You'll obviously need PayPal's Direct Payment API for PHP. You can get it at:https://www.paypal.com/IntegrationCenter/ic_sdk-resource.html
It is a PEAR based package so needless to say PEAR's core must be included on the vendors path. It is up to you how you install the API on your cake environment. This is what I've done:
- Downloaded PEAR base from http://pear.php.net/package/PEAR
- Unzipped PEAR based to {CAKE}/app/vendors/PEAR
- Downloaded PayPal Direct Payment SDK from https://www.paypal.com/IntegrationCenter/ic_sdk-resource.html
- Unzipped directory php-sdk/lib in SDK's zip to {CAKE}/app/vendors/PEAR
- Created a pear.inc.php file on {CAKE}/app/vendors with following content:
// Set path to PEAR filesܡםX]yZ0x%w ((kjaܡם
define('PEAR_PATH', dirname(__FILE__) . DS . 'PEAR');
// Add PEAR path to library path
set_include_path(PEAR_PATH . PATH_SEPARATOR . get_include_path());vendor('pear.inc');
Set up a PayPal Sandbox account
Can't really go through the whole explanation, but follow instructions on https://www.paypal.com/IntegrationCenter/ic_sandbox.htmlImportant Notes
There are two ways to make a payment: through Direct Payment API and via Express Checkout.
The Direct Payment API takes mandatory information such as order amount, credit card info, and shipping addresses to process the order by contacting PayPal's server via SOAP messages. When it is done, you either get a succesfull code (meaning that the sale was made) or an error. Therefore, it is a one-time call to the component. You set up the component's required variables, call directPayment(), and you get the appropiate result.
Unlike the simplicity of Direct Payment API, Express Checkout requires the user to be redirected to PayPal's website to confirm the payment, and then sends a callback to your site sending a Token ID. This callback is a way for PayPal to give us this ID that we will need when we want it to process the order. This means that you will need to call expressCheckout() function inside the component twice: when you initiate the payment (at which point the user is redirected to paypal) and when you get back the token and want to perform the actual transaction. There's no need to tell the component which token you've got, it will figure out what it's supposed to do when you call expressCheckout().
One very important issue regarding Express Checkout: I have my PayPal payment behind an authenticated action. When testing online I discovered that after paypal's callback to my website Cake's session got lost. Since you can tell the component which will be the URL that will be called when PayPal gives the callback, I added Cake's session ID to the URL. Before the first call to expressCheckout(), the call that makes the redirect to paypal, I store the session information using the component's function:
$this->Paypal->storeSession();
Then, when I get the callback (which I can check because I specify which URL gets called) I restore the session:
if (isset($_REQUEST['csid']))
{
// Restore session
if (!$this->Paypal->restoreSession($_REQUEST['csid']))
{
$this->redirect('/');
exit;
}
}
Doing a Direct Payment
$order = array(
'action' => CAKE_COMPONENT_PAYPAL_ORDER_TYPE_SALE,
'description' => 'CakePHP Component',
'total' => 100.00,
'buyer' => array (
'first' => 'Mariano',
'last' => 'Iglesias',
'address1' => '123 CakePHP Street',
'address2' => 'Apartment A',
'city' => 'San Diego',
'state' => 'CA',
'zip' => 92014,
'country' => 'US'
),
'cc' => array (
'type' => 'Visa', // Can be: Visa, MasterCard, Amex, Discover
'number' => '0000000000000000',
'expiration' => '01/2010',
'cvv2' => '999',
'owner' => array (
'first' => 'Mariano',
'last' => 'Iglesias'
)
)
);
$this->Paypal->setEnvironment(CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX);
$this->Paypal->setUser('ApiUser');
$this->Paypal->setPassword('ApiPassword');
$this->Paypal->setCertificate('cert_perm.txt');
$this->Paypal->setOrder($order);
// Make payment via PayPal
$result = $this->Paypal->directPayment();
// Check PayPal status
if ($result === false)
{
switch($this->Paypal->getErrorCode())
{
case CAKE_COMPONENT_PAYPAL_ERROR_INVALID_CREDIT_CARD:
echo 'INVALID CREDIT CARD';
exit;
break;
case CAKE_COMPONENT_PAYPAL_ERROR_INVALID_CVV2:
echo 'INVALID Credit Card Verification Number.';
exit;
break;
default:
echo 'ERROR: ' . $this->Paypal->getError();
exit;
break;
}
}
else
{
echo 'Woha! Got the money!';
echo '<pre>'; print_r($result); echo '</pre>';
exit;
}
Doing an Express Checkout
Here it gets a little tricky. Remember that I said that you achieve this in two steps:
- First call to expressCheckout() after which user gets redirected to PayPal
- PayPal calls us back using the URL we specified and we do then another expressCheckout() to perform the actual sale
So let's suppose we're doing this on an action called express() on a controller called Payments. We'll set it to receive one optional parameter indicating if we are receiving PayPal's callback. I'll also add the code here that stores and restores the session:
function express($callback = null)
{
if (isset($callback) && isset($_REQUEST['csid']))
{
// Restore session
if (!$this->Paypal->restoreSession($_REQUEST['csid']))
{
$this->redirect('/');
exit;
}
}
// Neither buyer nor credit card information since it
// is handled by PayPal
$order = array(
'action' => CAKE_COMPONENT_PAYPAL_ORDER_TYPE_SALE,
'description' => 'CakePHP Component',
'total' => 100.00
);
// Set up common component's parameters
$this->Paypal->setEnvironment(CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX);
$this->Paypal->setUser('ApiUser');
$this->Paypal->setPassword('ApiPassword');
$this->Paypal->setCertificate('cert_perm.txt');
$this->Paypal->setOrder($order);
if (!isset($callback))
{
// First call, user gets redirected to PayPal
$this->Paypal->setTokenUrl('http://www.server.com/payments/express/pay?csid=' . session_id());
$this->Paypal->setCancelUrl('http://www.server.com/payments/express/cancel?csid=' . session_id());
// Save current session
$this->Paypal->storeSession();
// Make payment via PayPal
$result = $this->Paypal->expressCheckout();
if ($result === false)
{
echo 'ERROR: ' . $this->Paypal->getError();
exit;
}
}
else if ($callback == 'cancel')
{
echo 'SNIFF... Why not?';
exit;
}
else if ($callback == 'pay')
{
// Second call, make payment via PayPal
$result = $this->Paypal->expressCheckout();
// Check PayPal status
if ($result === false)
{
echo 'ERROR: ' . $this->Paypal->getError();
exit;
}
else
{
echo 'Woha! Got the money!';
echo '<pre>'; print_r($result); echo '</pre>';
exit;
}
}
}
I hope this component is useful, I know it is for me anyway :) If you have any comments / questions try to add them (if you think they'll add value to other bakers) as comments on this page. If you want to contact me directly try:
email: mariano@cricava.com blog: http://www.marianoiglesias.com.ar
Otherwise just drop a question on Cake's Google Group mentioning this component on the subject since I am constantly reading/writing on the group.
On the next page you will find the component source code.
Got your CakeSchwag? I bought myself the Baseball Jersey and the Khaki Cap. I have to wait till December 29 for them to arrive (I asked a friend from the states to buy them and bring it to me down here... Argentina is a long way from the US.) What are you waiting for?
Remember, smart coders answer ten questions for every question they ask. So be smart, be cool, and share your knowledge.
BAKE ON
The Paypal Component
Component Class:
<?php
/**
* Paypal Direct Payment API Component class file.
*
* @filesource
* @copyright Mariano Iglesias - mariano@cricava.com
* @link http://www.marianoiglesias.com.ar Mariano Iglesias
* @package cake
* @subpackage cake.controllers.components
*/
require_once('PayPal.php');
require_once('PayPal/Profile/API.php');
require_once('PayPal/Profile/Handler.php');
require_once('PayPal/Profile/Handler/Array.php');
require_once('PayPal/Type/AbstractResponseType.php');
require_once('PayPal/Type/AddressType.php');
require_once('PayPal/Type/BasicAmountType.php');
require_once('PayPal/Type/CreditCardDetailsType.php');
require_once('PayPal/Type/DoCaptureResponseDetailsType.php');
require_once('PayPal/Type/DoCaptureResponseType.php');
require_once('PayPal/Type/DoDirectPaymentRequestType.php');
require_once('PayPal/Type/DoDirectPaymentRequestDetailsType.php');
require_once('PayPal/Type/DoDirectPaymentResponseType.php');
require_once('PayPal/Type/DoExpressCheckoutPaymentRequestType.php');
require_once('PayPal/Type/DoExpressCheckoutPaymentRequestDetailsType.php');
require_once('PayPal/Type/DoExpressCheckoutPaymentResponseType.php');
require_once('PayPal/Type/DoVoidResponseType.php');
require_once('PayPal/Type/ErrorType.php');
require_once('PayPal/Type/GetExpressCheckoutDetailsRequestType.php');
require_once('PayPal/Type/GetExpressCheckoutDetailsResponseDetailsType.php');
require_once('PayPal/Type/GetExpressCheckoutDetailsResponseType.php');
require_once('PayPal/Type/GetTransactionDetailsResponseType.php');
require_once('PayPal/Type/PayerInfoType.php');
require_once('PayPal/Type/PaymentDetailsType.php');
require_once('PayPal/Type/PersonNameType.php');
require_once('PayPal/Type/RefundTransactionResponseType.php');
require_once('PayPal/Type/SetExpressCheckoutRequestType.php');
require_once('PayPal/Type/SetExpressCheckoutRequestDetailsType.php');
require_once('PayPal/Type/SetExpressCheckoutResponseType.php');
require_once('PayPal/Type/TransactionSearchResponseType.php');
define ('CAKE_COMPONENT_PAYPAL_ENVIRONMENT_LIVE', 'live');
define ('CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX', 'sandbox');
define ('CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX_BETA', 'beta-sandbox');
define ('CAKE_COMPONENT_PAYPAL_ORDER_TYPE_SALE', 'Sale');
define ('CAKE_COMPONENT_PAYPAL_CURRENCY', 'USD');
define ('CAKE_COMPONENT_PAYPAL_CHARSET_DEFAULT', 'iso-8859-1');
define ('CAKE_COMPONENT_PAYPAL_ACK_SUCCESS', 'Success');
define ('CAKE_COMPONENT_PAYPAL_ACK_SUCCESS_WITH_WARNING', 'SuccessWithWarning');
define ('CAKE_COMPONENT_PAYPAL_SESSION_SAVE_PATH', ROOT . DS . APP_DIR . DS . 'tmp' . DS . 'sessions'); // No trailing slash!
define ('CAKE_COMPONENT_PAYPAL_EXPRESS_CHECKOUT_URL', 'https://www.{$environment}.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=commit&token={$token}');
define ('CAKE_COMPONENT_PAYPAL_ERROR_CANT_CREATE_CALLER', 1);
define ('CAKE_COMPONENT_PAYPAL_ERROR_INVALID_ORDER', 2);
define ('CAKE_COMPONENT_PAYPAL_ERROR_INVALID_BUYER', 3);
define ('CAKE_COMPONENT_PAYPAL_ERROR_CANT_GET_AMOUNT_TYPE', 4);
define ('CAKE_COMPONENT_PAYPAL_ERROR_INVALID_CREDIT_CARD_EXPIRATION_DATE', 5);
define ('CAKE_COMPONENT_PAYPAL_ERROR_CREDIT_CARD_NOT_SET', 6);
define ('CAKE_COMPONENT_PAYPAL_ERROR_INVALID_REQUEST', 7);
define ('CAKE_COMPONENT_PAYPAL_ERROR_INVALID_CVV2', 10504);
define ('CAKE_COMPONENT_PAYPAL_ERROR_INVALID_CREDIT_CARD', 10527);
/**
* Provides a wrapper for Paypal Direct Payment API.
*
* @author Mariano Iglesias - mariano@cricava.com
* @package cake
* @subpackage cake.controllers.components
*/
class PaypalComponent extends Object
{
/**#@+
* @access protected
*/
/**
* Name of this component.
*
* @since 1.0
* @var string
*/
var $name = 'Paypal';
/**
* Components that will be used.
*
* @since 1.0
* @var array
*/
var $components = array('Session');
/**#@-*/
/**#@+
* @access private
*/
/**
* Settings.
*
* @since 1.0
* @var array
*/
var $settings = array(
'api.environment' => CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX,
'api.username' => null,
'api.password' => null,
'api.certificate' => null,
'api.signature' => null,
'api.charset' => CAKE_COMPONENT_PAYPAL_CHARSET_DEFAULT
);
/**
* Paypal API caller.
*
* @since 1.0
* @var CallerServices
*/
var $caller;
/**
* Last Paypal error code.
*
* @since 1.0
* @var int
*/
var $errorCode;
/**
* Last Paypal error.
*
* @since 1.0
* @var string
*/
var $error;
/**#@-*/
/**
* Startup the component.
*
* @param AppController $controller The controller using the component
*
* @access public
* @since 1.0
*/
function startup(&$controller)
{
}
/**
* Stores the current session to a temporary file for later retrieval.
*
* @return bool true if stored, false otherwise
*
* @access public
* @since 1.0
*/
function storeSession()
{
$sessionFileHandle = fopen(CAKE_COMPONENT_PAYPAL_SESSION_SAVE_PATH . DS . session_id() . '.ser.tmp', 'w');
if ($sessionFileHandle !== false)
{
fwrite($sessionFileHandle, serialize($_SESSION));
fclose($sessionFileHandle);
return true;
}
return false;
}
/**
* Restores the specified session.
*
* @param string Session ID
*
* @return bool true if able to restore, false otherwise
*
* @access public
* @since 1.0
*/
function restoreSession($session_id)
{
if (preg_match('/^[A-Za-z0-9]*$/', $session_id))
{
$sessionFile = CAKE_COMPONENT_PAYPAL_SESSION_SAVE_PATH . DS . $session_id . '.ser.tmp';
if (@file_exists($sessionFile) && @is_file($sessionFile) && @is_readable($sessionFile) && @filesize($sessionFile) > 0)
{
$contents = file_get_contents($sessionFile);
$oldSession = @unserialize($contents);
if (is_array($oldSession) && count($oldSession) > 0)
{
foreach($oldSession as $id => $value)
{
$this->Session->write($id, $value);
}
}
@unlink($sessionFile);
return true;
}
}
return false;
}
/**
* Sets the API environment.
*
* @param string $environment API environment.
*
* @access public
* @since 1.0
*/
function setEnvironment($environment)
{
if (in_array($environment, array(CAKE_COMPONENT_PAYPAL_ENVIRONMENT_LIVE, CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX, CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX_BETA)))
{
$this->settings['api.environment'] = $environment;
}
}
/**
* Sets the full path to the certificate file.
*
* @param string $certificate Path to Certificate file.
*
* @access public
* @since 1.0
*/
function setCertificate($certificate)
{
$this->settings['api.certificate'] = $certificate;
}
/**
* Sets the API signature.
*
* @param string $signature API signature.
*
* @access public
* @since 1.0
*/
function setSignature($signature)
{
$this->settings['api.signature'] = $signature;
}
/**
* Sets the API user.
*
* @param string $user API user.
*
* @access public
* @since 1.0
*/
function setUser($user)
{
$this->settings['api.username'] = $user;
}
/**
* Sets the API password.
*
* @param string $password API password.
*
* @access public
* @since 1.0
*/
function setPassword($password)
{
$this->settings['api.password'] = $password;
}
/**
* Sets the default charset.
*
* @param string $charset charset (example: iso-8859-1)
*
* @access public
* @since 1.0
*/
function setCharset($charset)
{
$this->settings['api.charset'] = $charset;
}
/**
* Sets the URL to which PayPal Express Checkout will redirect when setting the token.
*
* @param string $uri The URI (for example, $this->here from a controller)
*
* @access public
* @since 1.0
*/
function setTokenUrl($uri)
{
$this->settings['express.token_uri'] = $uri;
}
/**
* Sets the URL to which PayPal Express Checkout will redirect when order cancelled.
*
* @param string $uri The URI (for example, $this->here from a controller)
*
* @access public
* @since 1.0
*/
function setCancelUrl($uri)
{
$this->settings['express.cancel_uri'] = $uri;
}
/**
* Sets the order to be processed. The order is an indexed array.
* Example:
*
* Array
* (
* [action] => Sale
* [description] => ORDER_DESCRIPTION
* [id] => INVOICE_ID
* [total] => 200
* [buyer] => Array
* (
* [first] => FIRST_NAME
* [last] => LAST_NAME
* [address1] => ADDRESS_1
* [address2] => ADDRESS_2
* [city] => CITY
* [state] => STATE (two letter for US)
* [zip] => ZIP
* [country] => us
* )
* [cc] => Array
* (
* [type] => Visa/MasterCard/Discovery/Amex
* [number] => CC_NUMBER
* [expiration] => 1/2010
* [cvv2] => 123
* [owner] => Array
* (
* [first] => HOLDER_FIRST_NAME
* [last] => HOLDER_LAST_NAME
* )
* )
* )
*
* @param array $order Order to be processed.
*
* @access public
* @since 1.0
*/
function setOrder($order)
{
$this->settings['order'] = $order;
}
/**
* Gets the latest error message. If more than one error message was
* reported by PayPal, each message is separated by a new line.
*
* @return string Latest error message (null if none).
*
* @access public
* @since 1.0
*/
function getError()
{
return $this->error;
}
/**
* Gets the latest error code.
*
* @return int latest error code (0 if no error).
*
* @access public
* @since 1.0
*/
function getErrorCode()
{
return $this->errorCode;
}
/**
* Performs a direct payment with the specified order. If order was processed,
* returns an indexed array with:
*
* - transaction: Paypal Transaction id
* - ack: success code
* - avs: AVS response code for US credit cards (see https://www.paypal.com/IntegrationCenter/ic_direct-payment.html)
* - cvv2: CVV response code for US credit cards (see - avs: AVS response code for US credit cards (see https://www.paypal.com/IntegrationCenter/ic_direct-payment.html)
* - amount: processed amount
*
* In case of error it returns false and sets error code and error message.
*
* @return mixed array if success, false otherwise.
*
* @since 1.0
* @access public
*/
function directPayment()
{
$this->_initialize();
if (!isset($this->caller))
{
return false;
}
if (!isset($this->settings['order']) || !isset($this->settings['order']['total']) || !isset($this->settings['order']['action']))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_ORDER;
$this->error = 'Order was not set up properly';
return false;
}
$this->errorCode = 0;
$this->error = null;
// Set up buyer's information
$shipTo =& PayPal::getType('AddressType');
if (isset($this->settings['order']['buyer']))
{
$this->settings['order']['buyer']['country'] = strtoupper($this->settings['order']['buyer']['country']);
if ($this->settings['order']['buyer']['country'] == 'US')
{
$this->settings['order']['buyer']['state'] = strtoupper($this->settings['order']['buyer']['state']);
}
$shipTo->setName($this->settings['order']['buyer']['first'] . ' ' . $this->settings['order']['buyer']['last']);
$shipTo->setStreet1($this->settings['order']['buyer']['address1']);
if (isset($this->settings['order']['buyer']['address2']))
{
$shipTo->setStreet2($this->settings['order']['buyer']['address2']);
}
$shipTo->setCityName($this->settings['order']['buyer']['city']);
$shipTo->setStateOrProvince($this->settings['order']['buyer']['state']);
$shipTo->setPostalCode($this->settings['order']['buyer']['zip']);
$shipTo->setCountry($this->settings['order']['buyer']['country']);
}
else
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_BUYER;
$this->error = 'Buyer was not set in order';
return false;
}
// Set up total $ for order
$orderTotal =& PayPal::getType('BasicAmountType');
if (PayPal::isError($orderTotal))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_CANT_GET_AMOUNT_TYPE;
$this->error = $orderTotal->getMessage();
return false;
}
$orderTotal->setattr('currencyID', CAKE_COMPONENT_PAYPAL_CURRENCY);
$orderTotal->setval($this->settings['order']['total'], $this->settings['api.charset']);
// Set up payment details
$paymentDetails =& PayPal::getType('PaymentDetailsType');
$paymentDetails->setOrderTotal($orderTotal);
$paymentDetails->setShipToAddress($shipTo);
if (isset($this->settings['order']['description']))
{
$paymentDetails->setOrderDescription($this->settings['order']['description'], $this->settings['api.charset']);
}
if (isset($this->settings['order']['id']))
{
$paymentDetails->setInvoiceId($this->settings['order']['id'], $this->settings['api.charset']);
}
// Set up credit card information
$cardDetails =& PayPal::getType('CreditCardDetailsType');
if (isset($this->settings['order']['cc']))
{
$personDetails =& PayPal::getType('PersonNameType');
if (isset($this->settings['order']['cc']['owner']))
{
$personDetails->setFirstName($this->settings['order']['cc']['owner']['first']);
$personDetails->setLastName($this->settings['order']['cc']['owner']['last']);
}
else
{
$personDetails->setFirstName($this->settings['order']['buyer']['first']);
$personDetails->setLastName($this->settings['order']['buyer']['last']);
}
$payerDetails =& PayPal::getType('PayerInfoType');
$payerDetails->setPayerName($personDetails);
$payerDetails->setPayerCountry($this->settings['order']['buyer']['country']);
$payerDetails->setAddress($shipTo);
$cardDetailsExpiration = explode('/', $this->settings['order']['cc']['expiration']);
if (count($cardDetailsExpiration) != 2 || $cardDetailsExpiration[0] < 1 || $cardDetailsExpiration[0] > 12 || $cardDetailsExpiration[1] < date('Y'))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_CREDIT_CARD_EXPIRATION_DATE;
$this->error = 'Credit Card Expiration date seems to be wrong (format: month/year)';
return false;
}
$cardDetailsExpiration[0] = str_pad($cardDetailsExpiration[0], 2, '0', STR_PAD_LEFT);
$cardDetails->setCreditCardType($this->settings['order']['cc']['type']);
$cardDetails->setCreditCardNumber($this->settings['order']['cc']['number']);
$cardDetails->setCVV2($this->settings['order']['cc']['cvv2']);
$cardDetails->setExpMonth($cardDetailsExpiration[0]);
$cardDetails->setExpYear($cardDetailsExpiration[1]);
$cardDetails->setCardOwner($payerDetails);
}
else
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_CREDIT_CARD_NOT_SET;
$this->error = 'Credit Card was not set in order';
return false;
}
// Set up request details
$requestDetails =& PayPal::getType('DoDirectPaymentRequestDetailsType');
$requestDetails->setPaymentDetails($paymentDetails);
$requestDetails->setCreditCard($cardDetails);
$requestDetails->setPaymentAction($this->settings['order']['action']);
$requestDetails->setIPAddress($_SERVER['SERVER_ADDR']);
// Set up request
$request =& PayPal::getType('DoDirectPaymentRequestType');
$request->setDoDirectPaymentRequestDetails($requestDetails);
// Execute request
$response = $this->caller->DoDirectPayment($request);
if (PayPal::isError($response))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_REQUEST;
$this->error = $response->getMessage();
return false;
}
$response_ack = $response->getAck();
if ($response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS || $response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS_WITH_WARNING)
{
$response_amount = $response->getAmount();
$result = array (
'transaction' => $response->getTransactionID(),
'ack' => $response_ack,
'avs' => $response->getAVSCode(),
'cvv2' => $response->getCVV2Code(),
'amount' => $response_amount->_value
);
return $result;
}
else
{
$errorList = $response->getErrors();
if(!is_array($errorList))
{
$this->errorCode = $errorList->getErrorCode();
$this->error = '#' . $errorList->getErrorCode() . ': ' . $errorList->getShortMessage() . ' [' . $errorList->getLongMessage() . ']';
}
else
{
$this->error = '';
foreach($errorList as $error)
{
if (!empty($this->error))
{
$this->error .= "\n";
}
$this->errorCode = $error->getErrorCode();
$this->error .= '#' . $error->getErrorCode() . ': ' . $error->getShortMessage() . ' [' . $error->getLongMessage() . ']';
}
}
}
return false;
}
/**
* Performs an express checkout payment with the specified order. If order was processed,
* returns an indexed array with:
*
* - transaction: Paypal Transaction id
* - ack: success code
* - amount: processed amount
*
* In case of error it returns false and sets error code and error message.
*
* Please note that this function should be called TWICE to make an actual payment. First call
* sets environment and paypal token up and tells paypal to redirect back to the URL specified
* by the function setTokenUrl(). Once this URL is reached (meaning paypal has sent us the
* generated token) then this function should be called again to perform the actual payment.
*
* @return mixed array if success, false otherwise.
*
* @since 1.0
* @access public
*/
function expressCheckout()
{
$this->_initialize();
if (!isset($this->caller))
{
return false;
}
if (!isset($this->settings['order']) || !isset($this->settings['order']['total']) || !isset($this->settings['order']['action']))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_ORDER;
$this->error = 'Order was not set up properly';
return false;
}
$this->errorCode = 0;
$this->error = null;
if (!isset($_REQUEST['token']))
{
if (isset($this->settings['express.token_uri']))
{
$tokenUrl = $this->settings['express.token_uri'];
}
else
{
$serverName = $_SERVER['SERVER_NAME'];
$serverPort = $_SERVER['SERVER_PORT'];
$pathParts = pathinfo($_SERVER['SCRIPT_NAME']);
$pathInfo = $pathParts['dirname'];
$tokenUrl = 'http://';
if (isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') == 0)
{
$tokenUrl = 'https://';
}
$tokenUrl .= $serverName . ($serverPort != 80 ? ':' . $serverPort : '');
$tokenUrl .= $pathInfo;
$tokenUrl .= '/' . $_SERVER['SCRIPT_NAME'];
if (!empty($_SERVER['QUERY_STRING']))
{
$tokenUrl .= '?' . $_SERVER['QUERY_STRING'];
}
}
if (isset($this->settings['express.cancel_uri']))
{
$cancelUrl = $this->settings['express.cancel_uri'];
}
// Set up total $ for order
$orderTotal =& PayPal::getType('BasicAmountType');
if (PayPal::isError($orderTotal))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_CANT_GET_AMOUNT_TYPE;
$this->error = $orderTotal->getMessage();
return false;
}
$orderTotal->setattr('currencyID', CAKE_COMPONENT_PAYPAL_CURRENCY);
$orderTotal->setval($this->settings['order']['total'], $this->settings['api.charset']);
// Set up request details
$requestDetails =& PayPal::getType('SetExpressCheckoutRequestDetailsType');
$requestDetails->setReturnURL($tokenUrl);
$requestDetails->setCancelURL($cancelUrl);
$requestDetails->setPaymentAction($this->settings['order']['action']);
$requestDetails->setOrderTotal($orderTotal);
// Set up request
$request =& PayPal::getType('SetExpressCheckoutRequestType');
$request->setSetExpressCheckoutRequestDetails($requestDetails);
// Execute request
$response = $this->caller->SetExpressCheckout($request);
if (PayPal::isError($response))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_REQUEST;
$this->error = $response->getMessage();
return false;
}
$response_ack = $response->getAck();
if ($response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS || $response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS_WITH_WARNING)
{
$token = $response->getToken();
$payPalUrl = CAKE_COMPONENT_PAYPAL_EXPRESS_CHECKOUT_URL;
$payPalUrl = str_replace('{$environment}', $this->settings['api.environment'], $payPalUrl);
$payPalUrl = str_replace('{$token}', $token, $payPalUrl);
header('Location: ' . $payPalUrl);
exit;
}
else
{
$errorList = $response->getErrors();
if(!is_array($errorList))
{
$this->errorCode = $errorList->getErrorCode();
$this->error = '#' . $errorList->getErrorCode() . ': ' . $errorList->getShortMessage() . ' [' . $errorList->getLongMessage() . ']';
}
else
{
$this->error = '';
foreach($errorList as $error)
{
if (!empty($this->error))
{
$this->error .= "\n";
}
$this->errorCode = $error->getErrorCode();
$this->error .= '#' . $error->getErrorCode() . ': ' . $error->getShortMessage() . ' [' . $error->getLongMessage() . ']';
}
return false;
}
}
}
else
{
// Set up request
$request =& PayPal::getType('GetExpressCheckoutDetailsRequestType');
$request->setToken($_REQUEST['token']);
// Execute request
$response = $this->caller->GetExpressCheckoutDetails($request);
if (PayPal::isError($response))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_REQUEST;
$this->error = $response->getMessage();
return false;
}
$response_ack = $response->getAck();
if ($response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS || $response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS_WITH_WARNING)
{
$responseDetails = $response->getGetExpressCheckoutDetailsResponseDetails();
$payerInfo = $responseDetails->getPayerInfo();
$payerId = $payerInfo->getPayerID();
}
else
{
$errorList = $response->getErrors();
if(!is_array($errorList))
{
$this->errorCode = $errorList->getErrorCode();
$this->error = '#' . $errorList->getErrorCode() . ': ' . $errorList->getShortMessage() . ' [' . $errorList->getLongMessage() . ']';
}
else
{
$this->error = '';
foreach($errorList as $error)
{
if (!empty($this->error))
{
$this->error .= "\n";
}
$this->errorCode = $error->getErrorCode();
$this->error .= '#' . $error->getErrorCode() . ': ' . $error->getShortMessage() . ' [' . $error->getLongMessage() . ']';
}
}
return false;
}
// Set up total $ for order
$orderTotal =& PayPal::getType('BasicAmountType');
if (PayPal::isError($orderTotal))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_CANT_GET_AMOUNT_TYPE;
$this->error = $orderTotal->getMessage();
return false;
}
$orderTotal->setattr('currencyID', CAKE_COMPONENT_PAYPAL_CURRENCY);
$orderTotal->setval($this->settings['order']['total'], $this->settings['api.charset']);
// Set up payment details
$paymentDetails =& PayPal::getType('PaymentDetailsType');
$paymentDetails->setOrderTotal($orderTotal);
if (isset($this->settings['order']['description']))
{
$paymentDetails->setOrderDescription($this->settings['order']['description'], $this->settings['api.charset']);
}
if (isset($this->settings['order']['id']))
{
$paymentDetails->setInvoiceId($this->settings['order']['id'], $this->settings['api.charset']);
}
// Set up request details
$requestDetails =& PayPal::getType('DoExpressCheckoutPaymentRequestDetailsType');
$requestDetails->setToken($_REQUEST['token']);
$requestDetails->setPayerID($payerId);
$requestDetails->setPaymentAction($this->settings['order']['action']);
$requestDetails->setPaymentDetails($paymentDetails);
// Set up request
$request =& PayPal::getType('DoExpressCheckoutPaymentRequestType');
$request->setDoExpressCheckoutPaymentRequestDetails($requestDetails);
// Execute request
$response = $this->caller->DoExpressCheckoutPayment($request);
if (PayPal::isError($response))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_INVALID_REQUEST;
$this->error = $response->getMessage();
return false;
}
$response_ack = $response->getAck();
if ($response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS || $response_ack == CAKE_COMPONENT_PAYPAL_ACK_SUCCESS_WITH_WARNING)
{
$responseDetails = $response->getDoExpressCheckoutPaymentResponseDetails();
$responsePaymentInfo = $responseDetails->getPaymentInfo();
$response_amount = $responsePaymentInfo->getGrossAmount();
$result = array (
'transaction' => $responsePaymentInfo->getTransactionID(),
'ack' => $response_ack,
'amount' => $response_amount->_value
);
return $result;
}
else
{
$errorList = $response->getErrors();
if(!is_array($errorList))
{
$this->errorCode = $errorList->getErrorCode();
$this->error = '#' . $errorList->getErrorCode() . ': ' . $errorList->getShortMessage() . ' [' . $errorList->getLongMessage() . ']';
}
else
{
$this->error = '';
foreach($errorList as $error)
{
if (!empty($this->error))
{
$this->error .= "\n";
}
$this->errorCode = $error->getErrorCode();
$this->error .= '#' . $error->getErrorCode() . ': ' . $error->getShortMessage() . ' [' . $error->getLongMessage() . ']';
}
}
return false;
}
}
return false;
}
/**
* Initializes the PayPal API caller handler.
*
* @return bool true on success, false otherwise.
*
* @access private
* @since 1.0
*/
function _initialize()
{
$this->errorCode = 0;
$this->error = null;
$handler =& ProfileHandler_Array::getInstance(array(
'username' => $this->settings['api.username'],
'certificateFile' => null,
'subject' => null,
'environment' => $this->settings['api.environment'] ));
$pid = ProfileHandler::generateID();
$profile =& new APIProfile($pid, $handler);
$profile->setAPIUsername($this->settings['api.username']);
$profile->setAPIPassword($this->settings['api.password']);
if(isset($this->settings['api.certificate']))
{
$profile->setCertificateFile($this->settings['api.certificate']);
}
$profile->setSignature($this->settings['api.signature']);
$profile->setEnvironment($this->settings['api.environment']);
$this->caller =& PayPal::getCallerServices($profile);
if (PayPal::isError($this->caller))
{
$this->errorCode = CAKE_COMPONENT_PAYPAL_ERROR_CANT_CREATE_CALLER;
$this->error = $this->caller->getMessage();
unset($this->caller);
return false;
}
return true;
}
}
?>








I'm fairly new to PEAR, though, have some experience with Cake ...
I'm following all the steps and think i manage to get the whole setup up and running ... I used
set_include_path(dirname(__FILE__).DS.'..'.DS.'vendors'.DS.'PEAR'.PATH_SEPARATOR.get_include_path());
to add PEAR include PATH ...
I keep getting these error messages:
----------------------------------------------
Missing argument 2 for Profile::Profile(), called in E:\workspaces\cake_1.2.5\cake\libs\class_registry.php on line 140 and defined [APP\vendors\PEAR\PayPal\Profile.php, line 59]
Undefined property: Profile::$table [CORE\cake\libs\model\model.php, line 646]
Warning (2): Cannot modify header information - headers already sent by (output started at E:\workspaces\cake_1.2.5\app\controllers\components\paypal.php:976) [CORE\cake\libs\controller\controller.php, line 644] ----------------------------------------------
I thought at first it might have to do with the Profile model i'm using in my app users section, but that sounds unlikely ..
ANyone has a clue what i might be doing wrong .. ?
Thanks all ....
////////////////////////////////
An update on this, for who might be having the same problem: setting debug to Configure::write('debug',0); seems to have fixed it, though am not sure yet cuz i still have to test the whole thing ...
cheers
ps Thanks for this copmponent by the way :-) ...
Somebody please let me know if its just a bug in my code or if it is with the component.
I was wondering if anybody has ran into this problem when going from the sandbox with zero problems to live.
When I go to place the order i get this error message:
Safari can't find the server "www.live.paypal.com".
I've tried the endpoints that Martin posted earlier and still didn't work.
All I did was change setEnvironment to this from the sandbox:
$this->Paypal->setEnvironment(CAKE_COMPONENT_PAYPAL_ENVIRONMENT_LIVE);
Any help or suggestions would be greatly appreciated.
I was wondering if anybody has ran into this problem when going from the sandbox with zero problems to live.
When I go to place the order i get this error message:
Safari can't find the server "www.live.paypal.com".
I've tried the endpoints that Martin posted earlier and still didn't work.
All I did was change setEnvironment to this from the sandbox:
$this->Paypal->setEnvironment(CAKE_COMPONENT_PAYPAL_ENVIRONMENT_LIVE);
Any help or suggestions would be greatly appreciated.
[end quote]
I found this problem also.
The solution is (in component):
function setEnvironment($environment)
{
if (in_array($environment, array(CAKE_COMPONENT_PAYPAL_ENVIRONMENT_LIVE, CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX, CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX_BETA)))
{
$this->settings['api.environment'] = $environment;
if ($environment=='live')
{define ('CAKE_COMPONENT_PAYPAL_EXPRESS_CHECKOUT_URL', 'https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=commit&token={$token}');}
else
{define ('CAKE_COMPONENT_PAYPAL_EXPRESS_CHECKOUT_URL', 'https://www.{$environment}.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=commit&token={$token}');}
}
}
$payPalUrl = str_replace('live.', '', $payPalUrl);
underneath the line:
$payPalUrl = str_replace('{$environment}', $this->settings['api.environment'], $payPalUrl);
I am confused about the php component, I have this example component called components/paypal.php with the class PaypalComponent extends Object, also it seems that the userful component for direct paypal payment an example given as....
Useful component that provides a wrapper for PayPal's Direct Payment API, ...
Doing a Direct Payment
$order = array(
'action' => CAKE_COMPONENT_PAYPAL_ORDER_TYPE_SALE,
'description' => 'CakePHP Component',
'total' => 100.00,
'buyer' => array (
'first' => 'Mariano',
'last' => 'Iglesias',....
My question is where does this code go???
$order = array(
'action' => CAKE_COMPONENT_PAYPAL_ORDER_TYPE_SALE,
'description' => 'CakePHP Component',
'total' => 100.00,
'buyer' => array (
'first' => 'Mariano',
'last' => 'Iglesias',....
In the component/paypal.php component?
i did the installation like posted by Jorge Pedret. it works fine on my local server (win xp, xampp). but i get an error on my live server:
Fatal error: require_once() [http://php.net/function.require]: Failed opening required 'PEAR.php'does anybody have any idea why?
trying to make the component work, I finally got it working in Cake
1.2. I'm relatively new to Cake, but have been working with PHP for
over 5 year, so there are a few things that I'm not sure if I used the
best way to do it.
So this are the confusions I got:
1. The PEAR directory I comes like PEAR-1.8.1/PEAR. I wasn't sure of
which of the two directories I should uncompress and where. Also I had
confusions with what directories should be uncompressed from the
PayPal SDK.
For the PEAR directory, you should uncompress the files so you get the
file PEAR.php in vendors/PEAR/ (vendors/PEAR/PEAR.php).
For the SDK, you should uncompress the php-sdk/lib directory at
vendors/PEAR/.
The final directory structure should look like the following: (only
showing the main files, not all of them)
->{CAKE}/app/vendors
->./PEAR
->./HTTP
->./Log
->./Net
->./PayPal
->./PEAR
->PayPal.php
->Multi.php
->Log.php
->PEAR.php
->Multi.php
2. The second confusion I had was how to replace the vendors call to
App::import() for Cake 1.2... Unfortunately this wasn't working for me
at all. So I (and this is the part that I think is not how it's
supposed to be done, but I worked for me) went to the bootstrap file
({cake}/app/config/bootstrap.php) and added the following code to the
bottom of the file:
set_include_path(dirnameThis sets the PEAR directory in the vendors file as part of the(__FILE__).DS.'..'.DS.'vendors'.DS.'PEAR'.PATH_SEPARATOR.get_include_path
());
include path, so all the require calls from {cake}/app/controllers/
components/paypal.php work fine.
3. I'm a bit ashamed of this one, but I forgot for a moment that they
were talking about a component for I was a bit confused of were to put
the paypal component content. It was a stupid confusion, but if
anybody has a doubt, you have to put the component in {cake}/app/
controllers/components/paypal.php.
Those were the main confusions that were bugging me during the whole
day.
To make the component work, follow this steps:
1. Download PEAR and place it how it's explained in my confusions #1
(above)
2. Download the PayPal PHP SDK (https://cms.paypal.com/us/cgi-bin/? cmd=_render-content&content_ID=developer/library_download_sdks) and
uncompress it how I explained in my confusions #1 (above) -> 3. Create the file {cake}/app/controllers/components/paypal.php and
write the components content (http://bakery.cakephp.org/leafs/view/22)
in this file.
4. Don't forget to add 'Paypal' to your controller's components: var
$components = array('Paypal');
5. Change the credentials (username,password and signature/
certificate) to your paypal's account
Note: In the example code, a certificate is being used instead of a
signature. Paypal let you use one or the other, if you use signature,
change the method call from $this->Paypal->setCertificate() to $this-
>Paypal->setSignature().
6. You should be able to use now the example code at
http://bakery.cakephp.org/leafs/view/20
I hope this was helpful for somebody. If you have any questions you
can send me an email and I'll try to help you!
When moved to LIVE, I was getting success response messages with the transaction IDs. However, no money being charged to the CC and no money going to the Paypal's account.
After spending about an hour with the Paypal technician on the phone, we learned that the endpoint URLs are incorrect in the PEAR package !.
To correct that, you need to update these files :
(suppose you installed the PEAT into vendors (not in the app dir, but in the root of your cake installation)
vendors/PEAR/Paypal/lib/Paypal/wsdl/paypal-endpoints.php
vendors/PEAR/Paypal/lib/Paypal/wsdl/paypal-endpoints.xml
Note ; I do not know which file is used , so I update both of them
This is the new values for the LIVE environment :
'PayPalAPI' => 'https://api-3t.paypal.com',
'PayPalAPIAA' => 'https://api-3t.paypal.com',
'PayPalAPI-threetoken' => 'https://api-3t.paypal.com',
'PayPalAPIAA-threetoken' => 'https://api-3t.paypal.com',
Change the URL in the XML file to https://api-3t.paypal.com as well.
Everything should be fine and you should get the money into your account.
Note : these files also hold min and max values for the price you charge via Paypal.
Note 2 : I have created complete a complete payments controller with four (4) steps :
1) enter personal info
2) enter billing info
3) review order (with the options to edit)
4) process payment
The payments controller also have admin functionality.
Let me know if anyone were interested in this as a packge.
Good Luck
Martin
Thanks for this tutorial. I have tried to follow it through along with help from existing comments but there seem to be header modify error that is very annoying.
This is what I have done.
I have saved the PaypalComponent php script as paypal.php in components/.
I have created a folder inside vendor called "PEAR", inside I have extracted the base lib folder from pear base package as well as the Paypal SDK.
I have also created a Pear.inc.php file inside vendor that Includes the PEAR directory.
In my payment controller, I have added App::import('Vendor', 'PearVendor', array('file' => 'pear.inc.php')); on the top.
And var $components = array('othAuth', 'Paypal');
Now, when I try to access any actions inside this controller, it gives me the following error:
Warning (2): Cannot modify header information - headers already sent by (output started at F:\production\Workspace\paymenttest\dev\app\controllers\components\paypal.php:984) [CORE\cake\libs\controller\controller.php, line 640]
Code | Context
$status = "Location: http://localhost/users/login?from=users/express"
header - [internal], line ??
Controller::header() - CORE\cake\libs\controller\controller.php, line 640
Controller::redirect() - CORE\cake\libs\controller\controller.php, line 621
othAuthComponent::redirect() - APP\controllers\components\oth_auth.php, line 818
othAuthComponent::check() - APP\controllers\components\oth_auth.php, line 936
AppController::beforeFilter() - APP\app_controller.php, line 26
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 209
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 194
[main] - APP\webroot\index.php, line 88
---------
Any help is appreciated.
it will occur when on line number 731 in paypal.php
header('Location: ' . $payPalUrl);
At the moment, the way the component is written, it's not possible to access this object. Can the author think of a way to allow customisation without hardcoding it in the component?
To use this component, the following steps need to be taken:
1) The complete code for the component (located on page 4) needs to be saved as app/controller/components/paypal.php
2) In the controller you wish to use the component for, add: var $uses = array('Paypal');
3) In your controller, add the example express() method (provided on page 2).
This presumes that you have the PayPal API set up. The PayPal API is completely separate to this component. To install the PayPal API:
1) Download the PayPal API from the PayPal SDK website
2) Copy the file PayPal.php and the folder PayPal into your existing PEAR installation.
This again assume that you have a working PEAR installation, and that your include_path correctly includes your PEAR library.
I am not able to understand the given code. Some part of code is not explained where to place it
So, here is my situation. I seem to have everything working fine on cake1.2 on my local box (os x leopard). However, when I deploy the same code to the pre-production box (Aplus.net shared hosting), I am getting a curl permission denied issue. Typically this can be due to proxy issues, and I think its only related to hitting the sandbox site.
Apparently, this can be fixed by resetting the endpoint URL to api-aa.sandbox.paypal.com/2.0/.
However, I can not for the life of me find the section in the code that is physically setting the URL request in the DirectPayment method. I see how its setting the environment to the constant declared above (i.e. CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX)-- and I can see in the Express Checkout where its replacing the string based off of that value. But, I can not find how the request is being built for the directPayment method to change the value to api-aa.sandbox.paypal.com/2.0/.
Please let me know if anyone has any ideas.
Thanks!
Chris
I try to implement the whole tutorials but it seems...it's quit difficult for me to understand with specially it doesn't give any instruction where to go. Where to put the a certain code. Specially the form and it's components.
Can u or anyone could help me how to make a step by step work in cooking paypal payment methods? Sorry but i'm just a newbie,...could anyone help me???
thnks
i am able to copy PEAR and paypal component ...every thing is working fine (it is able to include Pear , recognize paypal component).. but i am unable to figure out hoe to implement it in my project.
please guide me to solve this issue..
i will be greatfull to you if you can send some example application if you can...
Thanks in advance
M A Rasheed
Warning (2): require_once(PayPal.php) [function.require-once]: failed to open stream: No such file or directory [APP/controllers/components/paypal.php, line 12]Hi it is working fine on local system (localhost)but it is not working on live server.... any solution?
please help me!!
Thanks in advance
M A Rasheed
- Remove setCertificate and replace it with
$this->Paypal->setSignature('signature provided by paypal');.
and people it worked!!
Controller Class:
<?php$this->Paypal->setEnvironment(CAKE_COMPONENT_PAYPAL_ENVIRONMENT_SANDBOX);
$this->Paypal->setUser('ApiUser');
$this->Paypal->setPassword('ApiPassword');
$this->Paypal->setCertificate('sandbox.paypal.com.pem');
$this->Paypal->setOrder($order);
?>
Hi, where should i put the pem file? technically it is located under {cake}/app/vendors/PEAR/PayPal/cert but the code errors up the says sandbox.paypal.com.pem cannot be located.
Please, badly need help to implement your API.
I'll be trying it out today. It will most definitely save me many, many hours.
Is the API used the US version for paypal pro?
I am wondering as paypal pro api is now avaliable in the uk but doesn't use the same sdk as the US version.
Would it be easy to have an all-in-one component that handled all version as this could be updated centrally instead of the uk users having to write there own?
Penfold
Penfold: Well I'm using the API they give you when you look for DirectPayment's SDK. I find it hard to believe they would change the API for another country. Can you provide a link (to my email) with the information you have that tells you their SDKs are different for US and UK?
Comments are closed for articles over a year old