Sandbox buyer account with balance not working (PAYER_CANNOT_PAY) - php

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.

Related

Why paypal sandbox account amount does not updating?

My code is successfully processing payments to paypal and then return to success page, buy business account amount does not updating.
I am trying paypal sdk in laravel and below is my script which I am using it, but on front side it is successfully going to paypal page where I login using buyer account then pay and then paypal return to success page. But in seller account the amount does not showing and nor deducting from buyer account.
public function createpayment(){
$apiContext = new \PayPal\Rest\ApiContext(
new \PayPal\Auth\OAuthTokenCredential(
'Ac.................asd', // ClientID
'Ac.................sdf' // ClientSecret
)
);
$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 = getBaseUrl(); */
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl(route('success'))
->setCancelUrl(route('cancel'));
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
/* $payment->create($apiContext);
return redirect($payment->getApprovalLink()); */
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();
echo $payment, $approvalUrl;
}
public function success(){
$apiContext = new \PayPal\Rest\ApiContext(
new \PayPal\Auth\OAuthTokenCredential(
'Ac.................asd', // ClientID
'Ac.................sdf' // ClientSecret // ClientSecret
)
);
return request();
}
I want this code to be transfer money from buyer to seller account and then return success page with response. Can someone kindly guide me about I would like to appreciate.
On the success page you need to execute the payment in order to actually finish the transaction.
https://github.com/paypal/PayPal-PHP-SDK/blob/master/sample/payments/ExecutePayment.php

Getting "undefined variable" warning and "class not found" error when trying to use Paypal PHP SDK

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.

Multiple products in newest version of PayPal API

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;

How to enable credit card payment option in the "select your payment method" window?

I'm using the PayPal PHP SDK. I cannot enable the credit card payment option. Here are the relevant parts of my code and screenshots from the PayPal payment pages.
I set up my test merchant account and upgraded to pro. The test buyer account has a credit card attached to their acccount.
What can I do?
Screenshot 1
Screenshot 2
Screenshot 3
Relevant code
$payer = new Payer();
$payer->setPaymentMethod("paypal");
// Specify the payment amount.
$amount = new Amount();
$amount->setCurrency($currency);
$amount->setTotal($total);
$transaction = new Transaction();
$transaction->setAmount($amount);
$transaction->setDescription($paymentDesc);
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl($returnUrl);
$redirectUrls->setCancelUrl($cancelUrl);
$payment = new Payment();
$payment->setRedirectUrls($redirectUrls);
$payment->setIntent("sale");
$payment->setPayer($payer);
$payment->setTransactions(array($transaction));
$payment->create($this->getApiContext());

PayPal REST API through PHP SDK return "Incoming JSON request does not map to API request"

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.

Categories