I used this snippet in my application in Symfony2 + KMJPayPalBridgeBundle
http://paypal.github.io/PayPal-PHP-SDK/sample/doc/payments/CreatePaymentUsingPayPal.html
Few months ago it was all good but now I'm getting "Unsupported SSL protocol version" error.
Controller code
public function testAction()
{
$paypal = $this->get('paypal');
$apiContext = $paypal->getApiContext();
$payer = new Payer();
$payer->setPaymentMethod("paypal");
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setSku("123123"); // Similar to `item_number` in Classic API ->setPrice(7.5);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(5)
->setSku("321321"); // Similar to `item_number` in Classic API ->setPrice(2);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
$details = new Details();
$details->setShipping(1.2)
->setTax(1.3)
->setSubtotal(17.50);
$amount = new Amount();
$amount->setCurrency("USD")
->setTotal(20)
->setDetails($details);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription("Payment description")
->setInvoiceNumber(uniqid());
$baseUrl = "http://development.local";
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("$baseUrl/ExecutePayment.php?success=true")
->setCancelUrl("$baseUrl/ExecutePayment.php?success=false");
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
$request = clone $payment;
try { $payment->create($apiContext); } catch (Exception $ex) {
ResultPrinter::printError("Created Payment Using PayPal. Please visit the URL to Approve.",
"Payment", null, $request, $ex); exit(1);
}
$approvalUrl = $payment->getApprovalLink();
ResultPrinter::printResult("Created Payment Using PayPal. Please visit the URL to Approve.",
"Payment", "<a href='$approvalUrl' >$approvalUrl</a>", $request, $payment);
return array();
}
Are you testing against the PayPal Sandbox API endpoints?
PayPal upgraded their Sandbox API endpoints last night to require TLS 1.2 and offering (only) a SHA256-signed certificate.
More details are here and here.
By the sounds of it, you're either trying to enforce something other than TLS 1.2 (likely), or your openssl libs are so old, they don't support TLS 1.2 (anything below OpenSSL 1.0.1c, so unlikely).
You may want to try running TlsCheck.php from the SDK
There was an upgrade of the SDK:
https://github.com/paypal/PayPal-PHP-SDK/issues/474
with a checklist of current system requirments.
In my case it was different CLI PHP and different on server that caused an issue.
PHP uses the system supplied CURL library. Version 7.34.0 or later is required. -- From the second link.
I'm running into the same issue, and followed the update guides.
I figured out that php is still using curl version 7.19.0 Even when I run curl --version, I get 7.46.0. Working with server admin to recompile php.
Related
I'm using Paypal's PHP SDK, but I'm having trouble with executing payments (400, error code: PAYER_CANNOT_PAY ).
Sandbox setup:
Created a business sandbox account
Created a developer account
Created an App
Created sandbox buyer accounts with balance and linked credit card
Code:
Create a payment with Paypal SDK
$cred = new OAuthTokenCredential("$clientID", "$secret", $sdkConfig);
$cred->accessToken = $cred->getAccessToken($sdkConfig);
$apiContext = new ApiContext($cred);
$payer = new Payer();
$payer->setPaymentMethod("paypal");
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setSku("123123") // Similar to `item_number` in Classic API
->setPrice(7.5);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(5)
->setSku("321321")
->setPrice(2);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
$details = new Details();
$details->setShipping(1.2)
->setTax(1.3)
->setSubtotal(17.50);
$amount = new Amount();
$amount->setCurrency("USD")
->setTotal(20)
->setDetails($details);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription("Payment description")
->setInvoiceNumber(uniqid());
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("http://test.dev/paypal?success=true")
->setCancelUrl("http://test.dev/paypal?success=false");
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
$request = clone $payment;
$payment->create($apiContext);
App redirects user to Paypal sandbox login page
Login with sandbox account (Pay with section is empty)
User is redirected back with token, paymentID, payerID and status(success)
Execute the payment <-- response from API 400, PAYER_CANNOT_PAY
$paymentId = $request->all()['paymentId'];
$payment = Payment::get($paymentId, $apiContext);
$execution = new PaymentExecution();
$execution->setPayerId($request->all()['PayerID']);
$payment->execute($execution, $apiContext);
Error:
{
"status": 400,
"duration_time": 156,
"body": {
"message": "The combination of payer and payee settings mean that this buyer can't pay this seller.",
"debug_id": "debugid",
"details": [],
"name": "PAYER_CANNOT_PAY",
"information_link": "https://developer.paypal.com/docs/api/payments/#errors"
},
}
Any idea why this is failing?
Thank you in advance!
Perhaps payment is declined by buyer's card bank. There is no integration issue. Try by another account to confirm your integration.
Are you sure you aren't trying to login and pay with the same developer account that is acting as the seller? You need to make sure you're using separate sandbox accounts for buyer and seller.
I'm having this problem where ther Paypal API is not loading on my server but it loads completely normal on my localhost. I really don't know what and where it went wrong. Everything is the same as I upload files from my localhost to the server, nothing change and it's exactly the same files.
When making a payment using Paypal REST API, I had this error on my server but not on my localhost.
Fatal error: Class 'PayPal\Api\item' not found in /var/www/test.my-domain.com/public_html/controllers/credits.php on line 24
My code as below:
require_once('./inc/lib/paypal/autoload.php');
$apiContext = new \PayPal\Rest\ApiContext(
new \PayPal\Auth\OAuthTokenCredential(
'hidden-clientid',// ClientID
'hidden-secret'// ClientSecret
)
);
if (isset($_POST['checkout'])) {
$payer = new \PayPal\Api\Payer();
$payer->setPaymentMethod('paypal');
$item = new \PayPal\Api\item();
$item->setName('Top Up')
->setDescription('My account.')
->setCurrency('USD')
->setQuantity(1)
->setTax(0)
->setPrice(10);
$itemList = new \PayPal\Api\itemList();
$itemList->setItems(array($item));
$details = new \PayPal\Api\details();
$details->setShipping("0")
->setTax("0")
->setSubtotal(10);
$amount = new \PayPal\Api\amount();
$amount->setCurrency("USD")
->setTotal(10)
->setDetails($details);
$transaction = new \PayPal\Api\transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription("Top up account")
->setInvoiceNumber(uniqid());
$redirectUrls = new \PayPal\Api\RedirectUrls();
$redirectUrls->setReturnUrl("http://".$_SERVER["HTTP_HOST"].$web_path."credits/done?status=success");
$redirectUrls->setCancelUrl("http://".$_SERVER["HTTP_HOST"].$web_path."credits/done?status=cancel");
$payment = new \PayPal\Api\Payment();
$payment->setIntent('sale');
$payment->setPayer($payer);
$payment->setRedirectUrls($redirectUrls);
$payment->setTransactions(array($transaction));
$response = $payment->create($apiContext);
$redirectUrl = $response->links[1]->href;
header( "Location: $redirectUrl" );
The weird part is that it goes through $payer->setPaymentMethod('paypal'); But it does not pass at $item = new \PayPal\Api\item();
All code are the same as my localhost and it works on my localhost. The Paypal API is also uploaded on my server on the exact location (/inc/lib/paypal/).
What does the autoload contain. Try and use the full path EX: /var/www/test.my-domain.com/public_html when using the autoload or
I've solved this problem by including the API files one by one.
I include these lines below:
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/Item.php');
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/ItemList.php');
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/Details.php');
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/Amount.php');
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/Transaction.php');
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/RedirectUrls.php');
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/Payment.php');
require_once('./inc/lib/paypal/paypal/rest-api-sdk-php/lib/PayPal/Api/PaymentExecution.php');
and this fixed the problem. I think this is not really the best solution, but it works. I don't know why I still need to include these one by one where else the autoload.php should have included all these API files altogether.
I hope this helps for others who ran into the same problem like I do.
I want to integrate paypal payments to my site.
I tried integrating the paypal button form straight from paypal but there is a problem with it. The price of the product can be changed by easily inspecting the element and changing the price input.
I found out about the Paypal PHP SDK so I installed it via composer. The problem I'm having is when I want the user to pay for the product.
I copied and pasted the Create Payment method found here. But I'm getting an error:
Notice: Undefined variable: apiContext in C:\xampp\htdocs\paypal\index.php on line 62
Fatal error: Class 'ResultPrinter' not found in C:\xampp\htdocs\paypal\index.php on line 64
I know I'm getting this error because I haven't initialized this variable. I don't know where to create it and what this variable it must contain. How can I fully integrate this?
This is my full PHP code:
<?php
require 'vendor/autoload.php';
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
$payer = new Payer();
$payer->setPaymentMethod("paypal");
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setSku("123123") // Similar to `item_number` in Classic API
->setPrice(7.5);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(5)
->setSku("321321") // Similar to `item_number` in Classic API
->setPrice(2);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
$details = new Details();
$details->setShipping(1.2)
->setTax(1.3)
->setSubtotal(17.50);
$amount = new Amount();
$amount->setCurrency("USD")
->setTotal(20)
->setDetails($details);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription("Payment description")
->setInvoiceNumber(uniqid());
//I changed the base url and the return url's to mine.
$baseUrl = "http://www.localhost/paypal";
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("$baseUrl/ExecutePayment.php?success=true")
->setCancelUrl("$baseUrl/ExecutePayment.php?success=false");
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
$request = clone $payment;
try {
$payment->create($apiContext);
} catch (Exception $ex) {
ResultPrinter::printError("Created Payment Using PayPal. Please visit the URL to Approve.", "Payment", null, $request, $ex);
exit(1);
}
$approvalUrl = $payment->getApprovalLink();
ResultPrinter::printResult("Created Payment Using PayPal. Please visit the URL to Approve.", "Payment", "<a href='$approvalUrl' >$approvalUrl</a>", $request, $payment);
return $payment;
It looks like you've not defined $apiContext. I'm not totally familiar with this SDK but it looks like you can create one like so:
$apiContext = new \Paypal\Rest\ApiContext(
new \PayPal\Auth\AuthTokenCredential(
$clientId,
$clientSecret
)
);
reference
You will need to pass in your $clientId and $clientSecret that you have obtained from PayPal.
What is the correct way of passing in multiple products into a php paypal payment?
Currect working testcode for single product:
$api = new ApiContext(
new OAuthTokenCredential(
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
)
);
$api->setConfig([
'mode' => 'sandbox',
'log.LogEnabled' => false,
'log.FileName' => '',
'log.LogLevel' => 'FINE',
'validation.level' => 'log'
]);
$payer = new Payer();
$details = new Details();
$amount = new Amount();
$transaction = new Transaction();
$payment = new Payment();
$redirecturls = new RedirectUrls();
$payer->setPaymentMethod('paypal');
$details->setShipping('2.00')
->setTax('0.00')
->setSubtotal('20.00');
$amount->setCurrency('EUR')
->setTotal('22.00')
->setDetails($details);
$transaction->setAmount($amount)
->setDescription('Test');
$payment->setIntent('sale')
->setPayer($payer)
->setTransactions([$transaction]);
$redirecturls->setReturnUrl('RETURN URL')
->setCancelUrl('CANCEL URL');
$payment->setRedirectUrls($redirecturls);
try {
$payment->create($api);
} catch (PPConnectionException $e) {
header('Location: ERROR URL');
}
header('Location: '.$payment->getApprovalLink());
Keep in mind, this is not how I will implement it, this is just proof of concept!
I made a little CodeIgniter library with which I can easily call a payment!
If anyone is interested, don't hesitate to message me!
$this->load->library('Paypal');
$this->load->model('Config_model');
$ClientID = $this->Config_model->get('paypal.ClientID');
$Secret = $this->Config_model->get('paypal.Secret');
$defaultCurrency = $this->Config_model->get('transactions.currency');
$this->paypal->setSandbox(true);
$this->paypal->setMerchant($ClientID, $Secret);
$this->paypal->setDefaultCurrency($defaultCurrency);
$this->paypal->addItem('test', 5.3, 2);
$this->paypal->addItem('test2', 3.3, 5);
$this->paypal->setShipping(2);
$this->paypal->setTax(3);
$this->paypal->setDescription("Betalingetje");
$this->paypal->setCancelUrl('CANCEL URL HERE');
$this->paypal->setReturnUrl('RETURN URL HERE');
$this->paypal->execute();
PS: It works in conjunction with another tiny 'library' which is autoloaded. This library only includes the composer autoload.php like this:
class MyComposer
{
function __construct()
{
include("application/composer/vendor/autoload.php");
}
}
You can find the source code here: http://paypal.github.io/PayPal-PHP-SDK/sample/doc/payments/CreatePaymentUsingPayPal.html
There are so many more samples that comes packaged with the SDK itself. You can follow the instructions provided here at https://github.com/paypal/PayPal-PHP-SDK/wiki/Samples to execute samples in your local machine.
Let me know if I could be of any more help.
Here is the sample code snippet:
<?php
// # Create Payment using PayPal as payment method
// This sample code demonstrates how you can process a
// PayPal Account based Payment.
// API used: /v1/payments/payment
require __DIR__ . '/../bootstrap.php';
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
// ### Payer
// A resource representing a Payer that funds a payment
// For paypal account payments, set payment method
// to 'paypal'.
$payer = new Payer();
$payer->setPaymentMethod("paypal");
// ### Itemized information
// (Optional) Lets you specify item wise
// information
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setPrice(7.5);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(5)
->setPrice(2);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
// ### Additional payment details
// Use this optional field to set additional
// payment information such as tax, shipping
// charges etc.
$details = new Details();
$details->setShipping(1.2)
->setTax(1.3)
->setSubtotal(17.50);
// ### Amount
// Lets you specify a payment amount.
// You can also specify additional details
// such as shipping, tax.
$amount = new Amount();
$amount->setCurrency("USD")
->setTotal(20)
->setDetails($details);
// ### Transaction
// A transaction defines the contract of a
// payment - what is the payment for and who
// is fulfilling it.
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription("Payment description")
->setInvoiceNumber(uniqid());
// ### Redirect urls
// Set the urls that the buyer must be redirected to after
// payment approval/ cancellation.
$baseUrl = getBaseUrl();
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("$baseUrl/ExecutePayment.php?success=true")
->setCancelUrl("$baseUrl/ExecutePayment.php?success=false");
// ### Payment
// A Payment Resource; create one using
// the above types and intent set to 'sale'
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
// For Sample Purposes Only.
$request = clone $payment;
// ### Create Payment
// Create a payment by calling the 'create' method
// passing it a valid apiContext.
// (See bootstrap.php for more on `ApiContext`)
// The return object contains the state and the
// url to which the buyer must be redirected to
// for payment approval
try {
$payment->create($apiContext);
} catch (Exception $ex) {
// NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY
ResultPrinter::printError("Created Payment Using PayPal. Please visit the URL to Approve.", "Payment", null, $request, $ex);
exit(1);
}
// ### Get redirect url
// The API response provides the url that you must redirect
// the buyer to. Retrieve the url from the $payment->getApprovalLink()
// method
$approvalUrl = $payment->getApprovalLink();
// NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY
ResultPrinter::printResult("Created Payment Using PayPal. Please visit the URL to Approve.", "Payment", "<a href='$approvalUrl' >$approvalUrl</a>", $request, $payment);
return $payment;
I'm trying to create and execute a payment with PayPal REST API through PHP SDK (sandbox environment) like showing below. The payment creation ($payment->create) work fine but the payment execution ($payment->execute) return "Incoming JSON request does not map to API request".
The JSON request is created by the SDK, then what can be the problem?
Thanks in advance.
$payer = new Payer();
$payer->setPaymentMethod("paypal");
$item = new Item();
$item->setName('Any name')
->setCurrency('EUR')
->setQuantity(1)
->setPrice(0.99);
$itemList = new ItemList();
$itemList->setItems(array($item));
$details = new Details();
$details->setTax(0)
->setSubtotal(0.99);
$amount = new Amount();
$amount->setCurrency('EUR')
->setTotal(0.99)
->setDetails($details);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription('Any description')
->setInvoiceNumber(uniqid());
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl(BASE_URL.'/payment/?success=true')
->setCancelUrl(BASE_URL.'/payment/?success=false');
$payment = new Payment();
$payment->setIntent('sale')
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
try {
$payment->create($apiContext);
$execution = new PaymentExecution();
$result = $payment->execute($execution, $apiContext);
} catch (Exception $ex) {
//Function for extract the error message,
//the error message can be showing with
//a simple var_dump($ex)
$exception = self::getException($ex);
}
Am not a PHP dev (.Net), so based on reading the above, check into this section in your code:
$execution = new PaymentExecution();
$result = $payment->execute($execution, $apiContext);
You are sending a new PaymentExecution without the payer_id and the Payment.Id which you would obtain after the user approves your paypal Payment request that you created.
That said, I don't see that part (though as above, not a PHP dev) so I could be wrong. The steps are:
Create the Payment
Go into the Approval Flow -> user is redirected to Paypal and approves the Payment you created in #1 -> and is redirected back to your site (the returnUrl)
a. the PayerID will be in the querystring in this process
b. the paymentId will also be in the querystring in this process
After the user is redirected back to your site from PayPal (your returnUrl) - Execute a new Payment, set it's id to the one you obtained (#2b), sending the PaymentExecution with its PayerID set to the what you you obtained (#2a)
In c# (you'll need to convert this to PHP):
var _payment = new Payment { id = the_payment_id_you_obtained };
var _payExec = new PaymentExecution { payer_id = the_payer_id_you_obtained };
var _response = _payment.Execute(context, _payExec);
Hth...
It was enough put
$payment->setIntent('authorize')
instead of
$payment->setIntent('sale')
and eliminate the execution
$execution = new PaymentExecution(); $result = $payment->execute($execution, $apiContext);
Then, after
$payment->create
I used the "href" from
$payment->links
to do the redirect. Everything went perfectly. Thank you all.