This whole paypal process has been one nightmare after the next. I've managed to complete the application all except for one small problem. the response object from paypal Payment::execute() has no documentation. My front end is client side, so i really have no way of knowing what this response array contains.
here's what i've got so far:
$paymentId = $this->ppconf; //stores paymentId
if(empty($paymentId)){Throw New \Exception('missing payment id'); }
$payment = Payment::get($paymentId, $apiContext);
$execution = new PaymentExecution();
$execution->setPayerId($z);
$response = $payment->execute($execution, $apiContext); // i need to know what this response array looks like and what the response codes are, so i can generate my $result array for my application.
$state = $response->getState();
$failures = ['failed','canceled','expired'];
if(in_array($state,$failures)){
$result = ['type'=>'error'];
}else{
$result = ['type'=>'success'];
$this->finished = true;
}
return $result;
As per the docs: https://developer.paypal.com/webapps/developer/docs/api/#execute-an-approved-paypal-payment
Returns a payment object for the completed PayPal payment.
So presumably an instance of an PayPal\Api\Payment Object.
You should be able to grab the state property of the payment using the following:
$response->getState();
Returning one of the following strings:
created, approved, failed, canceled, expired
Related
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 have a site that uses the Paypal Rest API SDK and successfully capture the paymentId after the transaction.
I capture it from the return_url's $_SERVER['QUERY_STRING'] using PHP.
I was hoping my Client would be able to then go into their Paypal account and search for records using these PaymentID's. It doesn't seem the case. There is a TransactionID but it does not match the PaymentID.
Any idea how to either:
Search for the record in a Paypal Account using the PaymentID (using the Paypal Account interface record tools - not api programming)
Grab the transactionID after the transaction (the return URL only gives me PaymentID, Token, and PayerID.)
I've realized that I will need to take the PaymentID and use the SDK to retrieve more detailed payment information.
$apiContext = $this->getApiContext();
$payment = new Payment();
$payment = $payment->get( $paymentId, $apiContext );
$execution = new PaymentExecution();
$execution->setPayerId( $_GET['PayerID'] );
// ### Retrieve payment
// Retrieve the payment object by calling the
// static `get` method
// on the Payment class by passing a valid
// Payment ID
// (See bootstrap.php for more on `ApiContext`)
try {
$payment->execute( $execution, $apiContext );
if ( $payment ) {
$obj = json_decode( $payment );
//GET SOME STUFF
$paypal_payment_id = $obj->{'id'};
$status = $obj->{'state'};
//DO SOMETHING WITH IT
}
} catch ( Exception $ex ) {
// NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY
//ResultPrinter::printError("Get Payment", "Payment", null, null, $ex);
log_message( 'error', 'error=' . $ex );
//exit(1);
}
This code does not work:
$sale = $this->get_sale($saleId);
$amt = $sale->getAmount();
$refund = new Refund();
$refund->setAmount($amt);
$refundSale = new Sale();
$refundSale->setId($saleId);
$refundedSale = $refundSale->refund($refund, $this->apiContext);
I tried not providing an Amount object to initiate a full refund, per https://developer.paypal.com/docs/integration/direct/refund-payment/.
Yet this doesn't work either:
$sale = $this->get_sale($saleId);
$refund = new Refund();
$refundSale = new Sale();
$refundSale->setId($saleId);
$refundedSale = $refundSale->refund($refund, $this->apiContext);
Can anyone determine what I'm doing wrong? The API response doesn't give a lot of detail as to what is going on, just error code 400 and "The request was refused.{0}".
Based on the debug_id, the transaction has already been fully refunded, so you get such error message. You can create a new transaction, then try to refund again for testing.
I am using the PayPal SDK for PHP, I am trying to cancel an invoice, the result returned is "true", there isn't exception returned, but the invoice is not canceled. Please could you tell me if there is an error in my code?
$Invoice = new Invoice();
try {
$invoice = $Invoice->get($id_invoice, $apiContext);
$notify = new CancelNotification();
$notify->setSubject("Past due")
->setNote("Canceling invoice")
->setSendToMerchant(true)
->setSendToPayer(true);
$result = $Invoice->cancel($notify, $apiContext);
} catch (Exception $ex) {
$result = self::getException($ex);
}
return $result;
First get an invoice object like this:
$invoice = Invoice::get($invoiceId, $apiContext);
Then, you could do the following to cancel it.
// ### Cancel Notification Object
// This would send a notification to both merchant as well
// the payer about the cancellation. The information of
// merchant and payer is retrieved from the invoice details
$notify = new CancelNotification();
$notify
->setSubject("Past due")
->setNote("Canceling invoice")
->setSendToMerchant(true)
->setSendToPayer(true);
// ### Cancel Invoice
// Cancel invoice object by calling the
// static `cancel` method
// on the Invoice class by passing a valid
// notification object
// (See bootstrap.php for more on `ApiContext`)
$cancelStatus = $invoice->cancel($notify, $apiContext);
Also, to test the code, you could always run the samples, and test it out yourself, by just clicking a button.
I ran the sample to cancel an invoice, and then use the similar information provided back on get response of invoice:
"metadata": {
"created_date": "2015-02-04 13:12:33 PST",
"first_sent_date": "2015-02-04 13:12:34 PST",
"last_sent_date": "2015-02-04 13:12:34 PST",
"payer_view_url": "https://www.sandbox.paypal.com/cgi_bin/webscr?cmd=_pay-inv&viewtype=altview&id=INV2-6S46-MLLN-3FEA-VLZE"
}
Opening the URL showed me that the invoice was cancelled as shown below:
On my site user can fill their order basket with items.
Once this is finished they can click the checkout button.
I want them to checkout using PayPal.
Once the user click on the checkout button the user is redirected to PayPal and sees an overview of the products to pay for.
If the user goes through the payment process the user is redirected to my success page.
However I expect the success page to also receive the transaction id of the payment but paypal only sends back a token and a payerid.
My checkout form looks like this:
<form action="/en/checkout">
<input type="submit" name="submit" value="Checkout">
</form>
My code that does the checkout is:
function checkoutAction()
{
$request = $this->getRequest();
require_once(LIB_PATH.'/MFW/Paypal/Flows/Paypal_NVP.php');
$paypal_nvp = new MFW_Paypal_NVP();
// this should normally be filled by looping though the basket items
$data = array('L_PAYMENTREQUEST_0_NAME0'=>'Single License',
'L_PAYMENTREQUEST_0_NUMBER0'=>'1111-2222-3333-4444-5555-6666-7777-8888',
'L_PAYMENTREQUEST_0_AMT0'=>39.99, // or enterprise 299.00
'L_PAYMENTREQUEST_0_QTY0'=>1,
);
$_SESSION['Payment_Amount'] = 39.99;
$result = $paypal_nvp->CallShortcutExpressCheckout(59.98, $data);
$ack = strtoupper($result['ACK']);
if($ack == 'SUCCESS' || $ack == 'SUCCESSWITHWARNING') {
$paypal->RedirectToPayPal($result['TOKEN']);
exit();
}
}
The code in the Paypal_NCP class:
function generate_nvp_string($total_value, $data = array())
{
$params = array('PAYMENTREQUEST_0_AMT'=>$total_value,
'PAYMENTREQUEST_0_PAYMENTACTION'=>$this->payment_type,
'RETURNURL'=>$this->return_url,
'CANCELURL'=>$this->cancel_url,
'PAYMENTREQUEST_0_CURRENCYCODE'=>$this->currency,
);
$params = array_merge($params, $data);
$nvp_string = '';
foreach($params as $name => $value) {
$nvp_string.= '&'.$name.'='.$value;
}
// example string
// &PAYMENTREQUEST_0_AMT=39.99&PAYMENTREQUEST_0_PAYMENTACTION=Sale&RETURNURL=http://return-address&CANCELURL=http://cancel-address&PAYMENTREQUEST_0_CURRENCYCODE=EUR&L_PAYMENTREQUEST_0_NAME0=Single License&L_PAYMENTREQUEST_0_NUMBER0=1111-2222-3333-4444-5555-6666-7777-8888&L_PAYMENTREQUEST_0_AMT0=39.99&L_PAYMENTREQUEST_0_QTY0=1
return $nvp_string;
}
function CallShortcutExpressCheckout($total_value, $data = array())
{
$_SESSION['currencyCodeType'] = $this->currency;
$_SESSION['PaymentType'] = $this->payment_type;
$result = $this->hash_call('SetExpressCheckout', $this->generate_nvp_string($total_value, $data));
$ack = strtoupper($result['ACK']);
if ($ack == 'SUCCESS' || $ack == 'SUCCESSWITHWARNING') {
$_SESSION['TOKEN'] = urldecode($result['TOKEN']);
}
return $result;
}
So how do I get the information of the transaction for me to be able to process the payment in the backoffice? (I need an transaction ID for this)
You're only calling SetExpressCheckout. In order to finalize a transaction with Express Checkout, you must also call (optional) GetExpressCheckoutDetails to get the PayerID (a unique identifier of the buyer) and (required) DoExpressCheckoutPayment.
To recap:
To use Express Checkout, you would call the SetExpressCheckout API. In the API call, you specify the details of the products, amounts, and the RETURNURL. This is what you're doing in the code above.
Once you post this data to PayPal's API endpoint, you receive a token in return. You would then redirect the buyer, and append the token to the following URL: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-XXXXXXX
Once the buyer has agreed to your purchase, he is redirected back to the URL you specified in the RETURNURL.
You should now show the order confirmation, and call the GetExpressCheckoutDetails API**.
When calling GetExpressCheckoutDetails, supply the token. In the GetExpressCheckoutDetails API response you'll find a PayerID.
Now you're ready to call DoExpressCheckoutPayment, and charge the buyer. Remember to include both the token and the payerID when calling DoExpressCheckoutPayment.
With regards to IPN: You don't really need it anymore, as you'll also get the TransactionID back in the API response to DoExpressCheckoutPayment.
IPN would be useful if you would subsequently want to 'keep track' of the transaction. E.g., get notified in case of any refunds / chargebacks, etc.
This simply requires setting up an IPN script and including NOTIFYURL=http://.... in both SetExpressCheckout and DoExpressCheckoutPayment.
** The PayerID is appended in the GET of your RETURNURL as well. So you could skip calling GetExpressCheckoutDetails if you wanted to.
(Partial copy of my answer at Why is DoExpressCheckoutPayment required for Paypal? )