Paypal Sandbox IPN no Response - php

I am using Zend Framework 2 as my listener for a Paypal payment.
My listener is triggered when the payment is made in the sandbox environment, but when I generate the request to reply to Paypal in order to get a VERIFIED or INVALID response I do not get a response.
There is nothing coming up in the web server logs, no errors and no exception is thrown.
Have tried both the dispatch and Send methods.
Is there any way I can see if the request is sent to Paypal sandbox?
Anywhere in the sandbox I can see this?
Or is there any way I can see the response come back.
Am using Amazon WS but I don't think it's getting blocked as the listener is initially triggered.
Many thanks
Code for IPN listenter is below:
$request1 = $this->getRequest();
// Follow Paypal IPN protocol
// First send back to PayPal received request
$request = new Request();
$request->setMethod(Request::METHOD_POST);
$client = new Client();
$client->setRequest($request);
$client->setUri('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate');
$postArray = $request1->getPost()->getArrayCopy();
$client->setParameterPost($postArray);
$requestHeaders = $client->getRequest()->getHeaders();
try {
$response = $client->send();
//$response = $client->dispatch($request);
} catch (Exception $e) {
$logger->info("Exception:");
$logger->info($e->getMessage());
}

Ended up using the paypal code on https://github.com/paypal/ipn-code-samples/blob/master/IPN_PHP.txt to solve the above.

Related

Stripe Webhook Testing Issue - Test payments don't call the webhook

I'm trying to integrate Stripe to accept payments on a website. I've come to the point where pretty much everything works from the client's perspective - test payments go through, everything is integrated and I can do stuff on payment intent succeeded (on the client). However, I can only detect that on the front-end.
Now, I want to show customer some sensitive data when payment is completed. I can't do it on front end - because then client does not even have to pay for that. I need to use webhooks.
So, I've created a sample webhook like this:
require_once 'stripe-php-7.97.0/init.php';
$endpoint_secret = 'endpoint_secret_code';
$payload = #file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
ob_flush();
ob_start();
var_dump($event);
file_put_contents("dump.txt", ob_get_flush());
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object;
var_dump($event->type);
// ... handle other event types
default:
echo 'Received unknown event type ' . $event->type;
}
http_response_code(200);
I've also created a webhook in the Stripe dashboard, like this:
However, based on the payment amount, I need to do something on this web hook - create a session, store data into the database and so on and so on. I've made it possible with Stripe CLI to test this webhook. However, how to test it using the test payments on the actual page? I have no idea how to do that - it does not work at the moment and without it, I can't be sure that it will work properly once everything goes live until I properly test it like this.
Does anyone have any tips, tutorials, or any kind of help to solve this? I'm pretty much stuck on it so any help would be greatly appreciated.

PHP verify Paypal webhook signature

I'm having trouble trying to verify paypal webhook signatures with PHP. Using the new V2 of paypals APIs I am receiving the paypal webhook on my page.
However I can not seem to successfully validate the signature.
From the link HERE I got some sample webhook validation PHP code from paypal.
I can not get it working, I don't know where I am supposed to get bootstrap.php from in the paypal code. The paypal information seems incomplete or half baked. Paypal seems to be terrible to set-up compared to Stripe.
Has anyone got experience of validating paypal webhook signatures with PHP when using V2 of the paypal APIs ?
Well I have come to the conclusion that the Paypal developer information is rather poor, it is scatted all over the place, on multiple different pages and sites. The examples they give on the paypal developer website HERE are not a complete picture of what is required to validate a webhook signature. Stripe developer documentation is much better formatted and concise.
Installing Paypal Checkout V2 SDK does not give you the necessary development tools to validate paypal webhook signatures i.e. you can process payments and receive webhooks but you can not validate the webhook signatures....I know stupid. Tip do not download the SDK directly as you will not include the required autoload.php file. Use composer to install Paypal Checkout V2 SDK so that you get the autoload.php file.
Once you are to a point that you can process payments and receive webhooks form paypal you need to install the another SKD called Paypal Rest API SDK. Again use composer to install the SDK so that you get a autoload.php file which you will need.
When you install Paypal Rest API SDK amazingly you will still be missing files that are required to validate the payapl webhook signatures. I can find no mention of these anywhere on the paypal developer website.
bootstrap.php & common.php
Thanks to #Grumpy I got some samples provided on github HERE
Note you will probably need to modify the samples a bit in order to get them working with your website. Tip set the logger to false and save yourself some bother if you don't have the necessary access permissions to write.
Once you have bootstrap.php & common.php files created you can write the code for your webhook endpoint page i.e. the page that paypal sends the webhook to. I have included my PHP code below for how to validate and then process the paypal webhook. Tip in the below code you need to specify the webhook ID, each webhook that you create in paypal has a unique ID. Also when you are testing you can not use webhook simulator as this will fail validation, you can make manually a payment with your sandbox account details which will trigger a webhook payment event.
Paypal sure don't make it easy, their documentation is all over the place compared to Stripe. The Paypal webhooks can sometimes take several minutes to arrive after a payment is made, very frustrating when trying to debug. Also it's a bit ridiculous that they have a webhook simulator on the paypal developer website that can not be used to validate signatures...if stripe can do it why can't paypal.
<?php
//get the webhook payload
$requestBody = file_get_contents('php://input');
//check if webhook payload has data
if($requestBody) {
//request body is set
} else {
//request body is not set
exit();
}
use \PayPal\Api\VerifyWebhookSignature;
use \PayPal\Api\WebhookEvent;
$apiContext = require __DIR__ . '/bootstrap.php';
//Receive HTTP headers that you received from PayPal webhook.
$headers = getallheaders();
//need header keys to be UPPERCASE
$headers = array_change_key_case($headers, CASE_UPPER);
/*
example header paypal signature content for webhook, these values are recieved as an array, we then need to use this data to verify the payload
CONTENT-LENGTH : 1376
CORRELATION-ID : 6db85170269e7
USER-AGENT : PayPal/AUHD-214.0-54377828
CONTENT-TYPE: application/json
PAYPAL-AUTH-ALGO : SHA256withRSA
PAYPAL-CERT-URL : https://api.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a784-5edc0ebc
PAYPAL-AUTH-VERSION : v2
PAYPAL-TRANSMISSION-SIG : Hc2lsDedYdSjOM4/t3T/ioAVQqFPNVB/AY/EyPNlavXk5WYUfnAmt9dyEP6neAPOjFHiVkXMK+JlLODbr6dalw6i26aFQdsPXqGl38Mafuu9elPE74qgsqNferUFgHi9QFXL+UZCNYcb4mvlDePXZIIAPbB0gOuFGOdEv2uqNwTCSAa/D8aguv1/51FWb3RkytFuVwXK/XNfIEy2oJCpDs8dgtYAZeojH8qO6IAwchdSpttMods5YfNBzT7oCoxO80hncVorBtjj1zQrkoynEB9WNNN9ytepNCkT8l29fQ4Sx/WRndm/PESCqxqmRoYJoiSosxYU3bZP7QTtILDykQ==
PAYPAL-TRANSMISSION-TIME : 2020-04-05T14:40:43Z
PAYPAL-TRANSMISSION-ID : 6dec99b0-774b-11ea-b306-c3ed128f0c4b
*/
//if any of the relevant paypal signature headers are not set exit()
if(
(!array_key_exists('PAYPAL-AUTH-ALGO', $headers)) ||
(!array_key_exists('PAYPAL-TRANSMISSION-ID', $headers)) ||
(!array_key_exists('PAYPAL-CERT-URL', $headers)) ||
(!array_key_exists('PAYPAL-TRANSMISSION-SIG', $headers)) ||
(!array_key_exists('PAYPAL-TRANSMISSION-TIME', $headers))
)
{
exit();
}
//specify the ID for the webhook that you have set up on the paypal developer website, each web hook that you create has a unique ID
$webhookID = "ENTER_YOUR_WEBHOOK_ID_HERE";
//start paypal webhook signature validation
$signatureVerification = new VerifyWebhookSignature();
$signatureVerification->setAuthAlgo($headers['PAYPAL-AUTH-ALGO']);
$signatureVerification->setTransmissionId($headers['PAYPAL-TRANSMISSION-ID']);
$signatureVerification->setCertUrl($headers['PAYPAL-CERT-URL']);
$signatureVerification->setWebhookId($webhookID);
$signatureVerification->setTransmissionSig($headers['PAYPAL-TRANSMISSION-SIG']);
$signatureVerification->setTransmissionTime($headers['PAYPAL-TRANSMISSION-TIME']);
$signatureVerification->setRequestBody($requestBody);
$request = clone $signatureVerification;
try {
$output = $signatureVerification->post($apiContext);
} catch (Exception $ex) {
//error during signature validation, capture error and exit
ResultPrinter::printError("Validate Received Webhook Event", "WebhookEvent", null, $request->toJSON(), $ex);
exit(1);
}
$sigVerificationResult = $output->getVerificationStatus();
// $sigVerificationResult is a string and will either be "SUCCESS" or "FAILURE"
//if not webhook signature failed validation exit
if($sigVerificationResult != "SUCCESS"){
exit();
}
else if($sigVerificationResult == "SUCCESS"){
//paypay webhook signature is valid
//proceed to process webhook payload
//decode raw request body
$requestBodyDecode = json_decode($requestBody);
//pull whatever info required from decoded request body, some examples below
$paymentSystemID = $requestBodyDecode->id;
$eventType = $requestBodyDecode->event_type;
//do something with info captured from the webhook payload
}
This seems to work with php 8.1:
if (openssl_verify(
data: implode(separator: '|', array: [
$httpPayPalTransmissionId,
$httpPayPalTransmissionTime,
$webhookID,
crc32(string: $rawRequestBody),
]),
signature: base64_decode(string: $httpPayPalTransmissionSignature),
public_key: openssl_pkey_get_public(public_key: file_get_contents(filename: $cachedHttpPayPalCertUrl)),
algorithm: 'sha256WithRSAEncryption'
) === 1) {
die('OK');
} else {
die('FAILED');
}

How can I pass PayPal IPN callback throw idevaffiliate to a framework?

We are started to use iDevAffiliate.
Based on following instructions,
we made a PayPal's Buy Now button which has notify_url attribute pointed to our iDevAffiliate server (/paypal_ipn_buynow.php).
What I don't understand is, how now PayPal can notify our server about a purchase, if all requests are going to iDevAffiliate server?
How can I pass a request to our server, without hacking the code of iDevAffiliate?
You can redirect to your server first and then redirect to the affiliate url from your server. If that is not possible maybe your affiliate provides some king of API that you can use to check the status
Cheers
You are doing it wrong.
PayPal sends IPN request to the website you specified in the notify_url filed. Here you want to specify name of the script on your domain which will listen IPN requests comming from PayPal. For example: http://yourwebsite.com/listen_ipn.php where listen_ipn.php is your PHP script.
Please note that if you are using framework, then you can implement your IPN listener in controller's action. Then your URL might be like this: http://yourdomain.com/controllerID/actionID
To implement IPN listener use the following library https://github.com/Quixotix/PHP-PayPal-IPN. This library is really useful and easy to use.
Here is example code:
<?php
include('ipnlistener.php');
$listener = new IpnListener();
$listener->use_sandbox = true;
try {
$verified = $listener->processIpn();
} catch (Exception $e) {
// fatal error trying to process IPN.
exit(0);
}
if ($verified) {
// IPN response was "VERIFIED"
} else {
// IPN response was "INVALID"
}
?>
When you receive and parse IPN request, you would maybe like to update some data in your database,for example to allow your user to access to some data beacuse user paid.
When you do that, you have to notify iDevAffiliate that payment occured. You have all data from PayPal in your PHP $_POST array. So in order to notify iDevAffiliate, just make POST request containing all data that PayPal sent you (again, you can retrieve this data from your $_POST array) to iDevAffiliate listener from your website .
For sending POST requests, you can use cURL libraray. Here is example:
$url = 'http://server.com/path';
$data = array('key1' => 'value1', 'key2' => 'value2');
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
var_dump($result);
UPDATE: PayPal may send you several IPN requests for the same transaction, so make sure you have some flag column in your DB which tells you that IPN is already processed.
When you send data to iDevAffiliate, then circle is closed.
Hope I helped.

PHP Listener Script for Paypal Webhooks

I'm having trouble writing a PHP listener script for Paypal notification webhooks. I simply need a script to listen for and request the Paypal json data. I have created one for Stripe successfully, thanks to plenty of online documentation. This is what I have:
<?php require_once('./lib/Stripe.php');
Stripe::setApiKey("my_secret_stripe_key");
$input = #file_get_contents("php://input");
$event_json = json_decode($input);
// then I request the json data from a Stripe event... //
$event_json->type == 'charge.succeeded'
// etc... //
?>
I just need something similar to handle Paypal event json.
PayPal just released a new version, PayPal PHP-SDK 1.4.0;
this has a webhook listener.
https://github.com/paypal/PayPal-PHP-SDK/releases/tag/v1.4.0
The file is ValidateWebhookEvent.php
It is in the samples.
PayPal-PHP-SDK/paypal/rest-api-sdk-php/sample/notifications/ValidateWebhookEvent.php
The docs are here
https://github.com/paypal/PayPal-PHP-SDK/wiki/Webhook-Validation
I used this tutorial on http://code.tutsplus.com/ which was very helpful. You might also want to take a look at the webhook validation.

Paypal IPN receiving via simulator but not via my site

I have an odd problem, testing my IPN handler using the IPN simulator on the paypal website, it works (I've just got it emailing me the report), but when I do it through my site, I don't receive anything.
So I guess the problem must be with sending the pay request and setting the ipn url there
$payRequest = new PayRequest(new RequestEnvelope("en_US"), "PAY", $cancelURL, $currencyCode, $receiverList, $returnURL);
$payRequest->ipnNotificationUrl = $notifyURL;
$service = new AdaptivePaymentsService($config);
try {
/* wrap API method calls on the service object with a try catch */
$response = $service->Pay($payRequest);
}
I've double checked $notifyURL is the same as what i'm using in the simulator. Everything else is working, the user gets sent to the paypal website to complete the payment, it's just the IPN never gets sent afterwards.
I figured out that IPN has to be manually turned on in one of the accounts' profile.

Categories