I'm trying to setup recurring payments in paypal with PHP. But the problem that I'm having is that I don't know if I'm doing the right thing. I have this class which makes the request to the Paypal API:
<?php
class Paypal {
protected $_errors = array();
protected $_credentials = array(
'USER' => 'my-user-id',
'PWD' => 'my-pass',
'SIGNATURE' => 'my-signature',
);
protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp';
protected $_version = '74.0';
public function request($method,$params = array()) {
$this -> _errors = array();
if( empty($method) ) {
$this -> _errors = array('API method is missing');
return false;
}
$requestParams = array(
'METHOD' => $method,
'VERSION' => $this -> _version
) + $this -> _credentials;
$request = http_build_query($requestParams + $params);
$http_header = array(
'X-PAYPAL-SECURITY-USERID' => 'my-user-id',
'X-PAYPAL-SECURITY-PASSWORD' => 'my-pass',
'X-PAYPAL-SECURITY-SIGNATURE' => 'my-signature',
'X-PAYPAL-REQUEST-DATA-FORMAT' => 'JSON',
'X-PAYPAL-RESPONSE-DATA-FORMAT' => 'JSON'
);
$curlOptions = array (
CURLOPT_HTTPHEADER => $http_header,
CURLOPT_URL => $this -> _endPoint,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $request
);
$ch = curl_init();
curl_setopt_array($ch,$curlOptions);
$response = curl_exec($ch);
if (curl_errno($ch)) {
$this -> _errors = curl_error($ch);
curl_close($ch);
return false;
} else {
curl_close($ch);
$responseArray = array();
parse_str($response,$responseArray);
return $responseArray;
}
}
}
?>
Then I'm making the initial request like this:
session_start();
require_once('Paypal.php');
$paypal = new Paypal();
$amount = 1;
$requestParams = array(
'RETURNURL' => 'http://localhost/tester/paypal/new_test/test_done.php',
'CANCELURL' => 'http://localhost/tester/paypal/new_test/test_cancel.php',
'NOSHIPPING' => '1',
'ALLOWNOTE' => '1',
'L_BILLINGTYPE0' => 'RecurringPayments',
'L_BILLINGAGREEMENTDESCRIPTION0' => 'site donation'
);
$orderParams = array(
'PAYMENTREQUEST_0_AMT' => '1',
'PAYMENTREQUEST_0_CURRENCYCODE' => 'USD',
'PAYMENTREQUEST_0_ITEMAMT' => $amount
);
$item = array(
'L_PAYMENTREQUEST_0_NAME0' => 'site donation',
'L_PAYMENTREQUEST_0_DESC0' => 'site donation',
'L_PAYMENTREQUEST_0_AMT0' => $amount,
'L_PAYMENTREQUEST_0_QTY0' => '1'
);
$response = $paypal->request('SetExpressCheckout', $requestParams + $orderParams + $item);
$sandbox_location = 'https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=';
if(is_array($response) && $response['ACK'] == 'Success'){
$token = $response['TOKEN'];
$_SESSION['token'] = $token;
header('Location: ' . $sandbox_location . urlencode($token));
}
?>
As you can see I'm using the SetExpressCheckout API method to get the token that I need and store it in a session so that I can use it later with the request for CreateRecurringPaymentsProfile.
I'm currently redirected to a page similar to this:
Once the user is done logging in with paypal and confirming the amount it redirects to the success page that I've specified which contains this code:
session_start();
require_once('Paypal.php');
$amount = 1;
$paypal = new Paypal();
$token_param = array('TOKEN' => $_SESSION['token']);
$current_date = date('Y-m-d');
$recurring_payment_params = array(
'PROFILESTARTDATE' => gmdate('Y-m-d H:i:s', strtotime($current_date . ' + 1 months')),
'DESC' => 'site donation',
'BILLINGPERIOD' => 'Month',
'BILLINGFREQUENCY' => '1',
'TOTALBILLINGCYCLES' => '0',
'AMT' => $amount
);
$recurringpayment_response = $paypal->request('CreateRecurringPaymentsProfile', $recurring_payment_params + $token_param);
This works, I've verified in the sandbox account that the recurring payment profile was created and that the next billing due is next month. But the problem is that its not really visible in the paypal interface (the screenshot earlier) that they're paying for a subscription. Perhaps I'm getting the redirect url wrong? (https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=) or do I have to add additional arguments to the SetExpressCheckout method? Please help.
You're only showing the login screen. After you login you'll see information about the subscription and the button will see "Agree and Pay" or "Agree and Continue" (depending on your useraction value in the return URL) instead of just "Pay" or "Continue".
Related
I have set up a simple express checkout Paypal, everything work just fine in Dev Mode but i have an error in production mode.
Cannot use object of type Symfony\Component\HttpFoundation\RedirectResponse as array
$responseArray = $this->requestPaypal('SetExpressCheckout', array(
'RETURNURL' => 'http://returnUrl.fr/member/payment/confirm/validate/membership/'.$ref,
'CANCELURL' => 'http://cancelUrl.fr/member/payment/cancel',
'PAYMENTREQUEST_0_AMT' => $info['price'], # amount of transaction \
'PAYMENTREQUEST_0_CURRENCYCODE' => 'EUR', # currency of transaction \
'PAYMENTREQUEST_0_DESC0' => $info['description'],
'PAYMENTREQUEST_0_CUSTOM' => $info['time'],
));
$token = $responseArray['TOKEN']; // Error line
$payPalUrl = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=commit&token='.$token.'';
return $this->redirect($payPalUrl);
METHOD RequestPaypal :
public function requestPaypal($method, $params)
{
$params = array_merge($params, array(
'METHOD' => $method,
'VERSION' => $this->getParameter('version'),
'USER' => $this->getParameter('username'),
'SIGNATURE' => $this->getParameter('signature'),
'PWD' => $this->getParameter('password'),
));
$params = http_build_query($params);
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->getParameter('endpoint'),
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $params,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_VERBOSE => 1
));
$response = curl_exec($curl);
$responseArray = array();
parse_str($response, $responseArray);
if(curl_errno($curl))
{
$errors = curl_error($curl);
$this->addFlash('danger', $errors);
curl_close($curl);
return $this->redirectToRoute('payment');
}
if($responseArray['ACK'] == 'Success')
{
curl_close($curl);
}
return $responseArray;
}
I think the code doesn't not work in prod because of paypal/sandbox.
Help Please
Nic
As I can see, you face with CURL error and your code executes this block of code: if(curl_errno($curl)) { ... }. I assume that method $this->redirectToRoute returns RedirectResponse object. After that, you trying to get "TOKEN" element on RedirectResponse object, which causes the error. To fix this issue, please add condition to check if method requestPaypal returns RedirectResponse object and return RedirectResponse from your controller to "payment" route with flash message, containing CURL error messages.
This code should handle this situation:
$responseArray = $this->requestPaypal('SetExpressCheckout', array(
'RETURNURL' => 'http://returnUrl.fr/member/payment/confirm/validate/membership/'.$ref,
'CANCELURL' => 'http://cancelUrl.fr/member/payment/cancel',
'PAYMENTREQUEST_0_AMT' => $info['price'], # amount of transaction \
'PAYMENTREQUEST_0_CURRENCYCODE' => 'EUR', # currency of transaction \
'PAYMENTREQUEST_0_DESC0' => $info['description'],
'PAYMENTREQUEST_0_CUSTOM' => $info['time'],
));
if ($responseArray instanceof RedirectResponse) {
return $responseArray;
}
$token = $responseArray['TOKEN'];
$payPalUrl = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=commit&token='.$token.'';
return $this->redirect($payPalUrl);
I am attempting to set up a paypal api using the dodirectpayment NVP which I have assembled some code from online resource but when I submit it I get no response whatsoever, just a white screen. I noticed my code doesn't have any echo in it, but I am not sure how to echo whatever response paypal sends. any assistance would be great. All the customer info and credentials are all from the sandbox. Thanks!
enter code here <?php
class Paypal {
/**
* Last error message(s)
* #var array
*/
protected $_errors = array();
/**
* API Credentials
* Use the correct credentials for the environment in use (Live / Sandbox)
* #var array
*/
protected $_credentials = array(
'USER' => 'centerfusiondesign-test_api1.gmail.com',
'PWD' => 'JBTYXGQHZY37RXGH',
'SIGNATURE' => 'ANRk81o3BhdjleyZOhWslseXywLQAfcftsn6e71ykaqxRzNASgC3NYUn',
);
/**
* API endpoint
* Live - https://api-3t.paypal.com/nvp
* Sandbox - https://api-3t.sandbox.paypal.com/nvp
* #var string
*/
protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp';
/**
* API Version
* #var string
*/
protected $_version = ' 95.0';
/**
* Make API request
*
* #param string $method string API method to request
* #param array $params Additional request parameters
* #return array / boolean Response array / boolean false on failure
*/
public function request($method,$params = array()) {
$this -> _errors = array();
if( empty($method) ) { //Check if API method is not empty
$this -> _errors = array('API method is missing');
return false;
}
//Our request parameters
$requestParams = array(
'METHOD' => $method,
'VERSION' => $this -> _version
) + $this -> _credentials;
//Building our NVP string
$request = http_build_query($requestParams + $params);
//cURL settings
$curlOptions = array (
CURLOPT_URL => $this -> _endPoint,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => dirname(__FILE__) . '/cacert.pem', //CA cert file
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $request
);
$ch = curl_init();
curl_setopt_array($ch,$curlOptions);
//Sending our request - $response will hold the API response
$response = curl_exec($ch);
//Checking for cURL errors
if (curl_errno($ch)) {
$this -> _errors = curl_error($ch);
curl_close($ch);
return false;
//Handle errors
} else {
curl_close($ch);
$responseArray = array();
parse_str($response,$responseArray); // Break the NVP string to an array
return $responseArray;
}
}
}
$requestParams = array(
'IPADDRESS' => $_SERVER['REMOTE_ADDR'],
'PAYMENTACTION' => 'Sale'
);
$creditCardDetails = array(
'CREDITCARDTYPE' => 'Visa',
'ACCT' => '4032032109229382',
'EXPDATE' => '012020',
);
$payerDetails = array(
'FIRSTNAME' => 'John',
'LASTNAME' => 'Doe',
'COUNTRYCODE' => 'US',
'STATE' => 'NY',
'CITY' => 'New York',
'STREET' => '14 Argyle Rd.',
'ZIP' => '10010'
);
$orderParams = array(
'AMT' => '500',
'ITEMAMT' => '496',
'SHIPPINGAMT' => '4',
'CURRENCYCODE' => 'GBP'
);
$item = array(
'L_NAME0' => 'iPhone',
'L_DESC0' => 'White iPhone, 16GB',
'L_AMT0' => '496',
'L_QTY0' => '1'
);
$paypal = new Paypal();
$response = $paypal -> request('DoDirectPayment',
$requestParams + $creditCardDetails + $payerDetails + $orderParams + $item
);
if( is_array($response) && $response['ACK'] == 'Failure') { // Payment successful
// We'll fetch the transaction ID for internal bookkeeping
$transactionId = $response['TRANSACTIONID'];
}
?>
I am a little new to PHP so hopefully my error want be too stupid, Thanks!
You seemed to have CURL peer certificate verification enabled, which you might want to disable for testing purpose until you have it setup on server.
Replace:
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => dirname(__FILE__) . '/cacert.pem', //CA cert file
with:
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => FALSE,
Also, to check the response, just add
print_r($response);
below:
$response = $paypal -> request('DoDirectPayment',
$requestParams + $creditCardDetails + $payerDetails + $orderParams + $item
);
Let me help you have the complete code below:
<?php
class Paypal {
/**
* Last error message(s)
* #var array
*/
protected $_errors = array();
/**
* API Credentials
* Use the correct credentials for the environment in use (Live / Sandbox)
* #var array
*/
protected $_credentials = array(
'USER' => 'centerfusiondesign-test_api1.gmail.com',
'PWD' => 'JBTYXGQHZY37RXGH',
'SIGNATURE' => 'ANRk81o3BhdjleyZOhWslseXywLQAfcftsn6e71ykaqxRzNASgC3NYUn',
);
/**
* API endpoint
* Live - https://api-3t.paypal.com/nvp
* Sandbox - https://api-3t.sandbox.paypal.com/nvp
* #var string
*/
protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp';
/**
* API Version
* #var string
*/
protected $_version = ' 95.0';
/**
* Make API request
*
* #param string $method string API method to request
* #param array $params Additional request parameters
* #return array / boolean Response array / boolean false on failure
*/
public function request($method,$params = array()) {
$this -> _errors = array();
if( empty($method) ) { //Check if API method is not empty
$this -> _errors = array('API method is missing');
return false;
}
//Our request parameters
$requestParams = array(
'METHOD' => $method,
'VERSION' => $this -> _version
) + $this -> _credentials;
//Building our NVP string
$request = http_build_query($requestParams + $params);
//cURL settings
$curlOptions = array (
CURLOPT_URL => $this -> _endPoint,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => FALSE,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $request
);
$ch = curl_init();
curl_setopt_array($ch,$curlOptions);
//Sending our request - $response will hold the API response
$response = curl_exec($ch);
//Checking for cURL errors
if (curl_errno($ch)) {
$this -> _errors = curl_error($ch);
curl_close($ch);
return false;
//Handle errors
} else {
curl_close($ch);
$responseArray = array();
parse_str($response,$responseArray); // Break the NVP string to an array
return $responseArray;
}
}
}
$requestParams = array(
'IPADDRESS' => $_SERVER['REMOTE_ADDR'],
'PAYMENTACTION' => 'Sale'
);
$creditCardDetails = array(
'CREDITCARDTYPE' => 'Visa',
'ACCT' => '4032032109229382',
'EXPDATE' => '012020',
);
$payerDetails = array(
'FIRSTNAME' => 'John',
'LASTNAME' => 'Doe',
'COUNTRYCODE' => 'US',
'STATE' => 'NY',
'CITY' => 'New York',
'STREET' => '14 Argyle Rd.',
'ZIP' => '10010'
);
$orderParams = array(
'AMT' => '500',
'ITEMAMT' => '496',
'SHIPPINGAMT' => '4',
'CURRENCYCODE' => 'GBP'
);
$item = array(
'L_NAME0' => 'iPhone',
'L_DESC0' => 'White iPhone, 16GB',
'L_AMT0' => '496',
'L_QTY0' => '1'
);
$paypal = new Paypal();
$response = $paypal -> request('DoDirectPayment',
$requestParams + $creditCardDetails + $payerDetails + $orderParams + $item
);
print_r($response);
if( is_array($response) && $response['ACK'] == 'Failure') { // Payment successful
// We'll fetch the transaction ID for internal bookkeeping
$transactionId = $response['TRANSACTIONID'];
}
?>
Also, you might want to upgrade your sandbox business account to Pro, as refered to this link:
https://stackoverflow.com/a/21926016/4410290
hope this helps.. :)
If you're getting a blank white screen that means there's a PHP error happening but you don't have error reporting enabled.
Add this to the very top of your script.
error_reporting(E_ALL);
ini_set('display_errors', '1');
Then run the script again and you should see the error(s).
i ve been playing with the paypal api for exprescheckout.
the problem: i can not call the L_PAYMENTREQUEST_n_ methods.
the PAYMENTREQUEST_0_ works. but i can use this only for price or itemprice.
for the description and quantity i need to use L_PAYMENTREQUEST_n_ methods.
thx for any help
<?php
// EXpress Checkout Paypal
$paketdata = array(
array(
"name" => "Premium",
"desc" => "Mein Beschreibung",
"preis" => '9.96',
"count" => '2'
)
);
$endpreis = "18.97";
$desc = 'meine beschreibung name';
$paypal ="#";
$user = "paypalap#email.com";
$password = "passwd1234";
$signature ="fhhasHDJKHSAHJAL74327327dbsasahbsdcsadb7434";
$version = "93";
$currency = "EUR";
$params = array(
'METHOD' => 'SetExpressCheckout',
'USER' => $user,
'SIGNATURE' => $signature,
'PWD' => $password,
'RETURNURL' => 'https://localhost/env/paypal/geschafft.php',
'CANCELURL' => 'https://localhost/env/paypal/cancel.php',
'VERSION' => $version,
'PAYMENTREQUEST_0_AMT' => $endpreis,
'PAYMENTREQUEST_0_CURRENCYCODE' => $currency,
);
foreach ($paketdata as $k => $paket){
$params['L_PAYMENTREQUEST_0_NAME$k'] = $paket['name'];
$params['L_PAYMENTREQUEST_0_DESC$k'] = '';
$params['L_PAYMENTREQUEST_0_ITEMAMT$k'] = $paket['preis'];
}
$params = http_build_query($params);
$endpoint = 'https://api-3t.sandbox.paypal.com/nvp';
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $endpoint,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $params,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_VERBOSE => 1
));
$response = curl_exec($curl);
$responseArray = array();
parse_str($response, $responseArray);
if (curl_errno($curl)) {
var_dump(curl_errno($curl));
curl_close($curl);
die();
}else{
if ($responseArray['ACK'] == 'Success') {
}else{
curl_close($curl);
}
}
curl_close($curl);
$paypal = 'https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&useraction=commit&token=' . $responseArray['TOKEN'];
echo '<pre>';
print_r($paket);
echo '</pre>';
print_r($paypal)
?>
PAyPal
Your request is coming out like this...
Array
(
[METHOD] => SetExpressCheckout
[USER] => paypalap#email.com
[SIGNATURE] => fhhasHDJKHSAHJAL74327327dbsasahbsdcsadb7434
[PWD] => passwd1234
[RETURNURL] => https://localhost/env/paypal/geschafft.php
[CANCELURL] => https://localhost/env/paypal/cancel.php
[VERSION] => 93
[PAYMENTREQUEST_0_AMT] => 18.97
[PAYMENTREQUEST_0_CURRENCYCODE] => EUR
[L_PAYMENTREQUEST_0_NAME$k] => Premium
[L_PAYMENTREQUEST_0_DESC$k] =>
[L_PAYMENTREQUEST_0_ITEMAMT$k] => 9.96
)
You need to use double quotes around the param name in order to use $k directly inside like that, so you need this...
foreach ($paketdata as $k => $paket){
$params["L_PAYMENTREQUEST_0_NAME$k"] = $paket['name'];
$params["L_PAYMENTREQUEST_0_DESC$k"] = '';
$params["L_PAYMENTREQUEST_0_ITEMAMT$k"] = $paket['preis'];
}
That change then gives me this, which should go through just fine.
Array
(
[METHOD] => SetExpressCheckout
[USER] => paypalap#email.com
[SIGNATURE] => fhhasHDJKHSAHJAL74327327dbsasahbsdcsadb7434
[PWD] => passwd1234
[RETURNURL] => https://localhost/env/paypal/geschafft.php
[CANCELURL] => https://localhost/env/paypal/cancel.php
[VERSION] => 93
[PAYMENTREQUEST_0_AMT] => 18.97
[PAYMENTREQUEST_0_CURRENCYCODE] => EUR
[L_PAYMENTREQUEST_0_NAME0] => Premium
[L_PAYMENTREQUEST_0_DESC0] =>
[L_PAYMENTREQUEST_0_ITEMAMT0] => 9.96
)
On another note, though, you don't want to use localhost in your return and cancel URL's. PayPal's server is the one redirecting to that URL, so localhost at that time is their own server, which isn't going to do what you want, of course.
You need to use your public IP address or setup a domain that resolves to your IP that you can use.
In fact, it's funny, I just tried to use http:// on the front of localhost here, and Stack won't let me post links with that because of that very reason...they would be linking to themselves.
I'm using the Paypal API to create a subscription system where there are two types of subscriptions
Monthly subscription (5dlls)
Annual subscription (50dlls)
I currently have the following code:
For setting the checkout:
public function do_purchase($type){
$this->load->library('paypal');
$requestParams = array(
'RETURNURL' => site_url('restaurant/get_purchase_details'),
'CANCELURL' => site_url('restaurant/afiliaturestaurante')
);
$orderParams = array(
'L_BILLINGTYPE0' => 'RecurringPayments',
'L_BILLINGAGREEMENTDESCRIPTION0' => 'Monthly',
'AMT' => 0
);
$paypal = new Paypal();
$response = $paypal -> request('SetExpressCheckout',$requestParams + $orderParams);
if(is_array($response) && $response['ACK'] == 'Success') { //Request successful
$token = $response['TOKEN'];
header( 'Location: https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=' . urlencode($token) );
}
}
For creating the recurring Paypal profile:
public function get_purchase_details(){
if( isset($_GET['token']) && !empty($_GET['token']) ) { // Token parameter exists
// Get checkout details, including buyer information.
// We can save it for future reference or cross-check with the data we have
$this->load->library('paypal');
$paypal = new Paypal();
$checkoutDetails = $paypal -> request('GetExpressCheckoutDetails', array('TOKEN' => $_GET['token']));
// Complete the checkout transaction
$requestParams = array(
'TOKEN' => $_GET['token'],
'PAYERID' => $checkoutDetails['PAYERID'],
'PROFILESTARTDATE' => '2014-03-7T05:38:48Z',
'DESC' => 'Monthly',
'BILLINGPERIOD' => 'Month',
'BILLINGFREQUENCY' => '1',
'AMT' => '5',
'CURRENCYCODE' => 'USD',
'COUNTRYCODE' => 'US',
'MAXFAILEDPAYMENTS' => '3',
);
$response = $paypal -> request('CreateRecurringPaymentsProfile',$requestParams);
if( is_array($response) && $response['ACK'] == 'Success') { // Payment successful
// We'll fetch the transaction ID for internal bookkeeping
$profileID = $response['PROFILEID'];
}
}
}
I need to use $type variable on get_purchase_details for setting the amount of the profile, how can I pass the variable through Paypal so I can user on the other function? I'm using a Paypal library for creating the cURL requests.
Thanks in advance
You could just set the value of $type in a session variable, and that would be available upon return from PayPal.
Alternatively, you could pass your $type value in the CUSTOM parameter of SetExpressCheckout and that way it'll be returned in the GetExpressCheckoutDetails response.
I'm very new to paypal api, I've followed this tutorial and adapted the code to my needs.
I'd like to make a basic Authorization & Capture in 3 steps but I always fail in capturing
Customer land to paypal_pay_redirect.php for login into paypal and make a paymet
The payment is fine and we land to paypal_success.php, here I request the Authorization and keep the TRANSACTIONID for the next step
paypal_capture.php I use the transactionid for capture the payment but I always get "10609: Transaction id is invalid"
here the code, where is the mistake?
thanks
paypal_lib.php
<?php
// code from http://coding.smashingmagazine.com/2011/09/05/getting-started-with-the-paypal-api/
class Paypal {
/**
* Last error message(s)
* #var array
*/
protected $_errors = array();
/**
* API Credentials
* Use the correct credentials for the environment in use (Live / Sandbox)
* #var array
*/
protected $_credentials = array(
'USER' => 'xxxxxxxxxxxxxxxxxxxx',
'PWD' => 'xxxxxxxxxxxxx',
'SIGNATURE' => 'xxxxxxxxxxxxxxxxxxxxxxxxx'
);
/**
* API endpoint
* Live - https://api-3t.paypal.com/nvp
* Sandbox - https://api-3t.sandbox.paypal.com/nvp
* #var string
*/
protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp';
/**
* API Version
* #var string
*/
protected $_version = '74.0';
/**
* Make API request
*
* #param string $method string API method to request
* #param array $params Additional request parameters
* #return array / boolean Response array / boolean false on failure
*/
public function request($method,$params = array()) {
$this -> _errors = array();
if( empty($method) ) { //Check if API method is not empty
$this -> _errors = array('API method is missing');
return false;
}
//Our request parameters
$requestParams = array_merge(
array(
'METHOD' => $method,
'VERSION' => $this -> _version
),
$this -> _credentials
);
//Building our NVP string
$request = http_build_query(array_merge($requestParams, $params));
//cURL settings
$curlOptions = array (
CURLOPT_URL => $this -> _endPoint,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $request
);
$ch = curl_init();
curl_setopt_array($ch,$curlOptions);
//Sending our request - $response will hold the API response
$response = curl_exec($ch);
//Checking for cURL errors
if (curl_errno($ch)) {
$this -> _errors = curl_error($ch);
curl_close($ch);
return false;
//Handle errors
} else {
curl_close($ch);
$responseArray = array();
parse_str($response,$responseArray); // Break the NVP string to an array
return $responseArray;
}
}
}
?>
paypal_pay_redirect.php
<?php
require("paypal_lib.php");
//Our request parameters
$requestParams = array(
'RETURNURL' => 'https://www.domain.com/paypal_success.php',
'CANCELURL' => 'https://www.domain.com/paypal_fail.php'
);
$orderParams = array(
'PAYMENTREQUEST_0_AMT' => "57.00",
'PAYMENTREQUEST_0_SHIPPINGAMT' => '0',
'PAYMENTREQUEST_0_CURRENCYCODE' => 'EUR',
'PAYMENTREQUEST_0_ITEMAMT' => "57.00"
);
$item = array(
'L_PAYMENTREQUEST_0_NAME0' => 'xxxxxxxxxx',
'L_PAYMENTREQUEST_0_DESC0' => 'xxxxxxxxxx',
'L_PAYMENTREQUEST_0_AMT0' => "57.00",
'L_PAYMENTREQUEST_0_QTY0' => '1'
);
$paypal = new Paypal();
$response = $paypal -> request('SetExpressCheckout',$requestParams + $orderParams + $item);
if(is_array($response) && $response['ACK'] == 'Success') { //Request successful
$token = $response['TOKEN'];
header( 'Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . urlencode($token) );
}
?>
paypal_success.php
<?php
require("paypal_lib.php");
if( isset($_GET['token']) && !empty($_GET['token']) ) { // Token parameter exists
// Get checkout details, including buyer information.
// We can save it for future reference or cross-check with the data we have
$paypal = new Paypal();
$checkoutDetails = $paypal -> request('GetExpressCheckoutDetails', array('TOKEN' => $_GET['token']));
// Complete the checkout transaction
$requestParams = array(
'TOKEN' => $_GET['token'],
'PAYMENTACTION' => 'Authorization',
'PAYERID' => $_GET['PayerID'],
'PAYMENTREQUEST_0_AMT' => '57', // Same amount as in the original request
'PAYMENTREQUEST_0_CURRENCYCODE' => 'EUR' // Same currency as the original request
);
$response = $paypal -> request('DoExpressCheckoutPayment',$requestParams);
if( is_array($response) && $response['ACK'] == 'Success') { // Payment successful
// We'll fetch the transaction ID for internal bookkeeping
$transactionId = $response['PAYMENTINFO_0_TRANSACTIONID'];
echo "OK id: ".$transactionId;
var_dump($response);
}
var_dump($checkoutDetails);
}
?>
paypal_capture.php
<?php
require("paypal_lib.php");
$paypal = new Paypal();
// Complete the checkout transaction
$requestParams = array(
'AMT' => '57.00',
'AUTHORIZATIONID' => 'xxxxxxxxxxxxxxxxxxx', //what I get in paypal_success.php
'CURRENCYCODE' => 'EUR',
'COMPLETETYPE' => 'Complete', // Same amount as in the original request
);
$response = $paypal -> request('DoCapture',$requestParams);
var_dump($response);
?>
Two things:
First, in paypal_pay_redirect.php, add PAYMENTREQUEST_0_PAYMENTACTION => 'Authorization' to $orderParams.
Second, in paypal_success.php, change PAYMENTACTION TO PAYMENTREQUEST_0_PAYMENTACTION.
Here's why:
In your SetExpressCheckout call, if you don't set PAYMENTREQUEST_0_PAYMENTACTION, PayPal assumes that it will be Sale. And if this is set to Sale in your SetExpressCheckout call, then PayPal will only allow you to set it to Sale on your DoExpressCheckoutPayment call.
Additionally, in your DoExpressCheckoutPayment call, you're mixing new and old-style variable names. (Some variables, such as PAYMENTACTION, were renamed when PayPal introduced parallel payments for Express Checkout. PAYMENTACTION is the old style; PAYMENTREQUEST_0_PAYMENTACTION is the new style.) When you mix old-style and new-style names like this, PayPal recognizes variables using one style, and ignores the other. In your case, PAYMENTREQUEST_0_AMT and PAYMENTREQUEST_0_CURRENCYCODE are being recognized, but PAYMENTACTION is being ignored.
The combination of these two factors means that your transaction is most likely being run as a Sale transaction, not an Authorization. Since you can't capture against a Sale transaction (since it's technically already captured), PayPal responds by saying that the transaction ID is invalid.