Paypal Datasource

By seb (toste)
Simple datasource to communicate with the Paypal NVP api.
Simple datasource to communicate with the Paypal NVP api.

Install instructions :

- Place the newest version of paypal_source.php in your app/models/datasources folder
- Add the credidentials to database.php :
Download code
         var $paypal = array(
            'datasource' => 'paypal',
            'environment' => 'sandbox', // 'sandbox' or 'live'
             'currency' => 'CAD',
            'username' => '...',
            'password' => '...',
            'signature' => '...'
        );
 
- Call it from anywhere :
Download code
        $paypal = ConnectionManager::getDataSource('paypal');    
        $response = $paypal->directPayment($billing, $payment);    
 


Download code
<?php
/**
 * Paypal Datasource 1.0
 * 
 * Paypal datasource to communicate with the Paypal NVP api.
 * 
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * Install instructions :
 * 
 *  - Place the newest version of paypal_source.php in your app/models/datasources folder
 *  - Add the credidentials to database.php :
 *         var $paypal = array(
 *            'datasource' => 'paypal',
 *            'environment' => 'sandbox', // 'sandbox' or 'live'
 *             'currency' => 'CAD',
 *            'username' => '...',
 *            'password' => '...',
 *            'signature' => '...'
 *        );
 *  - Call it from anywhere :
 *             $paypal = ConnectionManager::getDataSource('paypal');    
 *            $response = $paypal->directPayment($billing, $payment);    
 * 
 * 
 * @author Sébastien Testeau <seb@binaryninja.com>
 * @copyright Copyright 2008, Sébastien Testeau, Ltd.
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 * @created December 23, 2008
 * @version 1.0
 * 
 */ 

App::import('Core', array('Xml''HttpSocket'));

class 
PaypalSource extends DataSource 
{      
      var 
$description "Paypal direct payment API";
    var 
$environment '';        
    var 
$currency '';
    
    
// Set up your API credentials, PayPal end point, and API version.
    
var    $userName "";
    var    
$password "";
    var    
$signature "";
    var 
$Http null;
    
    
//class var
    
var $nvpStr null;
      var 
$nvpreq null;

    function 
__construct($config) {
        
parent::__construct($config);        
        
$this->Http =& new HttpSocket();
        
        
$this->userName $this->config['username'];
        
$this->password $this->config['password'];
        
$this->signature $this->config['signature'];
        
$this->environment $this->config['environment'];
        
$this->currency $this->config['currency'];
    }
    
    
/**
     * Returns information about this payment processor.
     * This is meant to be shown to the user on the payment screen, so that they can select this payment method.
     *
     */
     
function info() {
         return 
$this->description;
     }
     
    
/**
     * Called by the checkout routine for payment processing to initialize payment data
     *
     * @param unknown_type $billing
     * @param unknown_type $shipping
     * @param unknown_type $payment
     * @return mixed    array if success, false otherwise.
     */
    
function doDirectPayment($billing$payment) {
        
// Set request-specific fields.
        
$paymentType urlencode('Sale');                // Authorization or 'Sale'
        
$firstName urlencode($billing['firstname']);
        
$lastName urlencode($billing['lastname']);
        
$creditCardType urlencode($payment['cc_type']);
        
$creditCardNumber urlencode($payment['cc']);
        
$expDateMonth $payment['expiration']['month'];
        
// Month must be padded with leading zero
        
$padDateMonth urlencode(str_pad($expDateMonth2'0'STR_PAD_LEFT));
        
        
$expDateYear urlencode($payment['expiration']['year']);
        
$cvv2Number urlencode($payment['security_code']);
        
$address1 urlencode($billing['address']);
        
$address2 "";
        
$city urlencode($billing['city']);
        
$state urlencode($billing['state']);
        
$zip urlencode($billing['postcode']);
        
$country urlencode($billing['country']);                // US or other valid country code
        
$amount urlencode($payment['amount']);
        
$currencyID urlencode('CAD');                            // or other currency ('GBP', 'EUR', 'JPY', 'CAD', 'AUD')
        
        // Add request-specific fields to the request string.
        
$this->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";
        
        return 
$this->query("doDirectPayment");
    }
    
    
    function 
getBalance() {        
        
// Add request-specific fields to the request string.
        
$this->nvpStr =    "";        
        return 
$this->query("GetBalance");
    }
    
    
/**
     * Refund the transaction 
     * 
     * @param $transaction_id
     * @param String $refund_type
     * @param float $amount
     * @param String $memo
     * @return mixed    array if success, false otherwise.
     */
    
function refundTransaction($transaction_id$refund_type 'Full'$amount null$memo null) {        
        
// Set request-specific fields.
        
$transactionID urlencode($transaction_id);
        
$refundType urlencode($refund_type);                    // or 'Partial'
        
$currencyID urlencode($this->currency);                
        
        if(isset(
$amount) && isset($memo) && $refund_type === 'Partial') {
            
$this->nvpStr "&TRANSACTIONID=$transactionID&REFUNDTYPE=$refundType&CURRENCYCODE=$currencyID&AMOUNT=$amount&MEMO=$memo";
        } else {
            
$this->nvpStr "&TRANSACTIONID=$transactionID&REFUNDTYPE=$refundType&CURRENCYCODE=$currencyID";
        }        
            
        return 
$this->query("RefundTransaction");
    }
    
    
/**
     * Get the details of a transaction
     *
     * @param  $transaction_id
     * @return mixed    array if success, false otherwise.
     */
    
function getTransactionDetails($transaction_id) {        
        
// Set request-specific fields.
        
$transactionID urlencode($transaction_id);
        
$this->nvpStr "&TRANSACTIONID=$transactionID";    
            
        return 
$this->query("RefundTransaction");
    }
    
    
/**
     * Search for a transaction during the specified time frame.
     *
     * @param $transaction_id
     * @param $startDateStr
     * @param $endDateStr
     * @return mixed    array if success, false otherwise.
     */
    
function search($transaction_id$startDateStr null$endDateStr null) {
        
// Set request-specific fields.
        
$transactionID urlencode($transaction_id);
        
        
// Add request-specific fields to the request string.
        
$this->nvpStr "&TRANSACTIONID=$transactionID";
        
        
// Set additional request-specific fields and add them to the request string.
        
if(isset($startDateStr)) {
           
$start_time strtotime($startDateStr);
           
$iso_start date('Y-m-d\T00:00:00\Z',  $start_time);
           
$this->nvpStr .= "&STARTDATE=$iso_start";
          }
        
        if(isset(
$endDateStr)&&$endDateStr!='') {
           
$end_time strtotime($endDateStr);
           
$iso_end date('Y-m-d\T24:00:00\Z'$end_time);
           
$this->nvpStr .= "&ENDDATE=$iso_end";
        }
        return 
$this->query("TransactionSearch");
    }
    
    
/**
     * Performs the communication with the paypal api
     * 
     * In case of error it returns false 
     * @return mixed array if success, false otherwise.
     * 
     */
    
function query($methodName) {
        
// Set up your API credentials, PayPal end point, and API version.
        
$API_UserName urlencode($this->userName);
        
$API_Password urlencode($this->password);
        
$API_Signature urlencode($this->signature);
                
        
$API_Endpoint "https://api-3t.paypal.com/nvp";        
        if(
"sandbox" === $this->environment || "beta-sandbox" === $this->environment) {
            
$API_Endpoint "https://api-3t.$this->environment.paypal.com/nvp";
        }
        
$version urlencode('51.0');
    
        
// Set the API operation, version, and API signature in the request.
        
$this->nvpreq "METHOD=$methodName&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$this->nvpStr";
        
        
//call the web service
        
$response $this->Http->post($API_Endpoint$this->nvpreq);
            
        if(!
$response) {
            return 
false;
        }
    
        
// Extract the response details.
        
$httpResponseAr explode("&"$response);
    
        
$httpParsedResponseAr = array();
        foreach (
$httpResponseAr as $i => $value) {
            
$tmpAr explode("="$value);
            if(
sizeof($tmpAr) > 1) {
                
$httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
            }
        }
    
        if((
== sizeof($httpParsedResponseAr)) || !array_key_exists('ACK'$httpParsedResponseAr)) {
            return 
false;
        }
        return 
$httpParsedResponseAr;        
    }
    
    
}
?> 

 

Comments 894

CakePHP Team Comments Author Comments
 

Comment

1 Fantastic Datasource

toste,

This worked flawlessly for me both in the sandbox and in for the production site (live). Only suggestion I might give is making the variables the same for the form as they are in the class just to make it a little easier to keep track of. Other than that this script worked flawlessly and took me 15 minutes to get it working.

Thanks so much!
Posted Jan 2, 2009 by Gary
 

Comment

2 Reoccuring payment support?

Does this work for reoccurring payments?
Posted Jan 5, 2009 by Khaled Dostzada
 

Comment

3 very smart

I like it. I'm sure over time it could use some upgrades, but the base concept is great.
Posted Jan 5, 2009 by Rob Conner
 

Comment

4 Why "Missing Database Table paypals"?

Missing Database Table

Error: Database table paypals for model Paypal was not found
Posted Jan 17, 2009 by Joshua Chi
 

Bug

5 WHOPS RefundTransaction instead of GetTransactionDetails


/**
     * Get the details of a transaction
     *
     * @param  $transaction_id
     * @return mixed    array if success, false otherwise.
     */
    function getTransactionDetails($transaction_id) {        
        // Set request-specific fields.
        $transactionID = urlencode($transaction_id);
        $this->nvpStr = "&TRANSACTIONID=$transactionID";    
            
        return $this->query("RefundTransaction");
    } 

Should be:


/**
     * Get the details of a transaction
     *
     * @param  $transaction_id
     * @return mixed    array if success, false otherwise.
     */
    function getTransactionDetails($transaction_id) {        
        // Set request-specific fields.
        $transactionID = urlencode($transaction_id);
        $this->nvpStr = "&TRANSACTIONID=$transactionID";    
            
        return $this->query("GetTransactionDetails");
    }

Don't make the same mistake I did. I accidentally refunded a transaction when I just wanted to view it.
Posted Mar 27, 2009 by Nick Baker
 

Comment

6 Revolution Money

Paypal has been popular from the time it started. Its services are good and many are satisfied with it. However, there is this new credit card style transaction called the Revolution Money. Think of Revolution Money as a credit card with a PIN number. You can use it for store purchases, payday loans, whatever you wish. It's being bankrolled right now by major corporations, as it will eliminate merchant fees on credit purchases. It is also being hailed as the biggest, and amongst the first, competitors with PayPal. The Revolution Card will be available soon, and it is expected to make an immediate impact. It could be worth looking into payday loans to get in on Revolution Money.
Posted Apr 14, 2009 by ArthurD