I am using PHP REST APIv1 (I believe) to integrate with paypal.
My request code looks as follows:
include '../../classes/db.connect.php';
use PayPal\Api\Amount;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
require 'bootstrap.php';
if (empty($_POST['buy_now'])) {
throw new Exception('This script should not be called directly, expected post data');
}
$setitem = strip_tags($_POST['item']);
$stmt=$db->prepare("SELECT * FROM shopping WHERE id = :id");
$stmt->bindParam(':id', $setitem);
$stmt->execute();
$row = $stmt->fetch();
$payer = new Payer();
$payer->setPaymentMethod('paypal');
$currency = 'USD';
$amountPayable = $row['price'];
$item1 = new Item();
$item1->setName($row['name'])
->setCurrency('USD')
->setQuantity('1')
->setPrice($amountPayable);
$invoiceNumber = uniqid();
$amount = new Amount();
$amount->setCurrency($currency)
->setTotal($amountPayable);
$itemList = new ItemList();
if (isset($item1) && isset($item2)) {
$itemList->setItems(array($item1, $item2));
} elseif (isset($item1)) {
$itemList->setItems(array($item1));
} elseif (isset($item2)) {
$itemList->setItems(array($item2));
}
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription('Website '.$row['name'].' Purchase')
->setInvoiceNumber($invoiceNumber)
->setNotifyUrl("https://REDACTED/notify.php")
->setCustom($username);
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl($paypalConfig['return_url'])
->setCancelUrl($paypalConfig['cancel_url']);
$payment = new Payment();
$payment->setIntent('sale')
->setPayer($payer)
->setTransactions([$transaction])
->setRedirectUrls($redirectUrls);
try {
$payment->create($apiContext);
} catch (Exception $e) {
throw new Exception('Unable to create link for payment');
}
header('location:' . $payment->getApprovalLink());
A payment goes through just fine, but notify_url is not called by paypal. There are no errors at all. The user can make a payment, the payment goes through, the user is returned to setReturnUrl but setNotifyUrl seems to get ignored.
I have done a var_dump on $transaction and the notify_url is sent to paypal, but it is not called by paypal - thus I get no notifications of transactions/nothing updated in the database.
I have done the most basic test I can think to ensure paypal is not calling notify_url. The php in the file is simply set to:
include '../../classes/db.connect.php';
$stmt = $db->prepare("INSERT INTO test (info) VALUES ('1122')");
$stmt->execute();
I realize REST is intended to work with webhooks - but I am not wanting to use them for several various reasons. My understanding is that setting a notify_url will allow paypal to use that url as an IPN. However I am finding paypal is just ignoring this variable.
Also I should mention I have tried this with IPN enabled and IPN status updates disabled, I have tried with IPN enabled and status updates enabled, and I have tried it with IPN disabled. All three ways has the same result - no errors, everything work, but no notifications sent nor received by paypal.
My IPN istory page on paypal is completely empty.
Am I doing something wrong? Misunderstanding something?
I cannot find any solid information about this.
Paypal IPNs setup through your Paypal account are sent irrespective of the method used to create the transactions.
https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNSetup/
You can use the IPN simulator to test your receiving code, or by signing up for a sandbox account as configuring the IPN setting there.
Related
I am using PayPal REST API in sandbox mode to test payments.
I create the approval link, then redirect user to said link.
PayPal then asks for credentials which I insert as a sandbox test buyer. But after logging in, PayPal does not redirect me to complete the approval of payment, and instead straight to My Account summary from where I cannot approve the payment. However if the user was already logged in, the payment approval proceeds as expected.
Is it the problem with how was the link created or is it a bug?
This is the code used to create the link
<?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;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Rest\ApiContext;
class PaypalFactory
{
private const CLIENT_ID = 'yyy';
private const CLIENT_SECRET = 'xxx';
private function __construct()
{
}
public static final function getContext()
{
return new ApiContext(
new OAuthTokenCredential(
self::CLIENT_ID,
self::CLIENT_SECRET
)
);
}
public static final function createPaymentLink(
int $orderId,
string $currency,
float $totalPrice,
float $deliveryPrice,
string $returnUrl,
string $cancelUrl): string
{
$payer = new Payer();
$payer
->setPaymentMethod("paypal");
$details = new Details();
$details
->setShipping($deliveryPrice)
->setSubtotal($totalPrice);
$item = new Item();
$item
->setName('products and shipping')
->setCurrency($currency)
->setPrice($totalPrice)
->setQuantity(1);
$itemList = new ItemList();
$itemList->setItems(array($item));
$amount = new Amount();
$amount
->setCurrency($currency)
->setTotal($totalPrice + $deliveryPrice)
->setDetails($details);
$transaction = new Transaction();
$transaction
->setItemList($itemList)
->setAmount($amount)
->setDescription("Products from ")
->setInvoiceNumber($orderId);
$redirectUrls = new RedirectUrls();
$redirectUrls
->setReturnUrl($returnUrl)
->setCancelUrl($cancelUrl);
$payment = new Payment();
$payment
->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
try {
$payment->create(PaypalFactory::getContext());
} catch (Exception $ex) {
print $ex;
}
return $payment->getApprovalLink();
}
}
Purging all browser cookies for paypal domains is good advice, and may help. The problem you're experiencing is probably a general sandbox issue (that won't happen in live mode), and not a problem with your code.
However, seeing your code/solution, I do have suggestions for trying some newer/better things:
Instead of the old PayPal-PHP-SDK for v1/payments, use the new Checkout-PHP-SDK for v2/orders
Instead of redirecting the buyer to the approval URL, give the approval token to the Javascript code of Smart Payment Buttons, which will display an in-context window that keeps your site loaded in the background. Here's a demo pattern
I'm a slight bit confused about the Paypal API. I'm using Paypal Payments to have a customer pay on the spot with the PHP SDK.
$apiContext = new ApiContext(
new OAuthTokenCredential(
$this->paypalid,
$this->paypalsecret
)
);
$payer = $_GET['payerId'];
$paymentid = $_GET['paymentId'];
$payment = Payment::get($paymentid, $apiContext);
$transaction = $payment->getTransactions();
$execution = new PaymentExecution();
$execution->setPayerId($payer)
->setTransactions($transaction);
try{
$result = $payment->execute($execution, $apiContext);
} catch (Exception $ex) {
echo "Couldn't process payment";
exit;
}
I would like to generate an invoice based on the payment done for tax reasons. Currently all this does is send a notification to both the seller/buyer concerning the transaction being successful. Paypal's API seems to heavily imply that invoices are used to process payments, which in this case, the payment is already done; I don't want the customer to pay twice.
I imagine that I need to set the status property on an Invoice object to "PAID" and set the amount paid equal to the total amount present on the payment, and then use the send method along with the apiContext.
Am I wrong?
I am very new to the PayPal API and REST request/responses. As such, I have been trying to follow along with online samples (mostly from GitHub) about how to use PayPal's REST Api to process payments.
However, I have encountered a problem. When I click on the link that is generated, I am successfully redirected to PayPal's site. However, at the checkout page, there is nothing that indicates the amount of the purchase. What might the issue be? Thanks!
<?php
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 = new Payer();
$payer->setPaymentMethod("paypal");
$amount = new Amount();
$amount->setCurrency("USD");
$amount->setTotal('5.55');
$transaction = new Transaction();
$transaction->setAmount($amount)->setDescription("Purchase from Leisurely Diversion")->setInvoiceNumber(uniqid());
$redirectURLs = new RedirectUrls();
$redirectURLs->setReturnUrl("http://localhost/leisurelydiversion/confirmation.php")->setCancelUrl("http://localhost/leisurelydiversion/confirmation.php");
$payment = new Payment();
$payment->setIntent("sale")->setPayer($payer)->setTransactions(array($transaction))->setRedirectUrls($redirectURLs);
try {
$payment->create($apiContext);
} catch(Exception $e) {
echo "<h2> Error Sending Payment! $e</h2>";
}
$url = $payment->getApprovalLink();
echo $url;
?>
You have to add an item list to the payment:
http://paypal.github.io/PayPal-PHP-SDK/sample/doc/payments/OrderCreateUsingPayPal.html
You can also change the action by appending &useraction=commit to the approval url:
Does PayPal Rest API have the classic useraction equivalent
Hope this will help
$item = new Item();
$item->setSku('Product Id');
$item->setName('Product Name');
$item->setPrice('5.55');
$item->setCurrency('USD');
$item->setQuantity(1);
$itemList = new ItemList();
$itemList->setItems(array($item));
$transaction = new Transaction();
$transaction->setItemList($itemList);
$transaction->setAmount($amount);
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.
I'm coding in PHP using the Paypal REST SDK. I've set up my Sandbox account to use AUD. I worked this out after realising that my initial transactions were in USD and the transactions were getting held.
Using my revised code I'm trying to create payment - I assume I'll get back a URL which will allow me to redirect the user to approve the payment.
I'm getting a message which says:
Exception: Got Http response code 403 when accessing https://api.sandbox.paypal.com/v1/payments/payment. Retried 0 times.
string(215) "{"name":"REQUIRED_SCOPE_MISSING","message":"Access token does not have required scope","information_link":"https://developer.paypal.com/webapps/developer/docs/api/#REQUIRED_SCOPE_MISSING","debug_id":"34683601f5dcd"}"
My code is:
$apiContext = new ApiContext(new OAuthTokenCredential(
'xxxxxx',
'xxxxxx'));
//### FundingInstrument
// A resource representing a Payer's funding instrument.
// For direct credit card payments, set the CreditCard
// field on this object.
$fi = new FundingInstrument();
$creditCardToken = new CreditCardToken();
$creditCardToken->setCreditCardId($creditcard->cardToken);
$fi->setCreditCardToken($creditCardToken);
// ### Payer
// A resource representing a Payer that funds a payment
// For direct credit card payments, set payment method
// to 'credit_card' and add an array of funding instruments.
$payer = new Payer();
$payer->setPaymentMethod("credit_card")
->setFundingInstruments(array($fi));
// ### Itemized information
// (Optional) Lets you specify item wise
// information
$paymentItems=Yii::app()->session['paymentitems'];
$items=array();
$total=0;
foreach ($paymentItems as $item)
{
$pp_item = new Item();
$pp_item->setName("Donation to ".$item->organisation->organisationName)
->setCurrency('AUD')
->setQuantity(1)
->setPrice($item->amount);
array_push($items,$pp_item);
$total+=(float)$item->amount;
}
$itemList = new ItemList();
$itemList->setItems($items);
// ### Amount
// Lets you specify a payment amount.
// You can also specify additional details
// such as shipping, tax.
$amount = new Amount();
$amount->setCurrency("AUD")
->setTotal($total);
// ### 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");
// ### Payment
// A Payment Resource; create one using
// the above types and intent set to sale 'sale'
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setTransactions(array($transaction));
// ### Create Payment
// Create a payment by calling the payment->create() method
// with a valid ApiContext (See bootstrap.php for more on `ApiContext`) href
// The return object contains the state.
try {
$response=$payment->create($apiContext);
var_dump($response);
//$this->redirect($response->links[0]->href);
} catch (PayPal\Exception\PPConnectionException $ex) {
echo "Exception: " . $ex->getMessage() . PHP_EOL;
var_dump($ex->getData());
exit(1);
}
Any thoughts as to what this message means. It would seem that direct credit card payments are not supported by Paypal in Australia, but I don't think that's the problem.
In your Paypal developer account, under My Apps > [Your App], make sure the feature you are trying to use is enabled in the APP SETTINGS section.