-2

So I am new with stripe, I am trying to get the checkout payment intent response using webhook
my purpose is to send the checkout response to my dashboard angular application so that I can save data about the client and it's payment whether it is successful or not
so I used this code :

<?php
require_once('vendor/autoload.php');
\Stripe\Stripe::setApiKey('sk_test_xxx');

$payload = @file_get_contents('php://input');
$event = null;

try {
    $event = \Stripe\Event::constructFrom(
        json_decode($payload, true)
    );
} catch(\UnexpectedValueException $e) {
    // Invalid payload
    http_response_code(400);
    exit();
}

$payload = @file_get_contents('php://input');
$event = null;

try {
    $event = \Stripe\Event::constructFrom(
        json_decode($payload, true)
    );
} catch(\UnexpectedValueException $e) {
    // Invalid payload
    http_response_code(400);
    exit();
}
print_r($payload);
// Handle the event
switch ($event->type) {
    case 'payment_intent.succeeded':
        $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
echo 'success';
        // Then define and call a method to handle the successful payment intent.
        // handlePaymentIntentSucceeded($paymentIntent);
        break;
    case 'payment_intent.payment_failed':
        $paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod
echo 'failed';
        // Then define and call a method to handle the successful attachment of a PaymentMethod.
        // handlePaymentMethodAttached($paymentMethod);
        break;
    // ... handle other event types
    default:
        // Unexpected event type
        http_response_code(400);
        exit();
}

http_response_code(200); 

then I run a checkout test and after I finished and got the success page I tried to access www.website.com/webhooks.php it always gives me a 400 error,
I don't know if what I am doing is wrong or not and how the uses webhooks I am still figuring it so can some one tell me what to do

elaaa
  • 19
  • 1
  • 11
  • 1
    It makes little sense to try and “access” this webhook script via your browser address bar. That will cause a GET request, but the script expects to get JSON data POSTed to it. JSON-decoding the non-existing payload will probably only get you null or false, and trying to create a stripe event based on that will then simply throw an exception, so you get the 400 response. – CBroe Mar 12 '20 at 10:53
  • so I need to make a post request right? but from where should I send it and with what parameters? – elaaa Mar 12 '20 at 10:58
  • _“so I need to make a post request right?”_ – if you want to debug your script, by sending it a set of test data yourself, then you could do that, yes. (But you are aware that this is not how a webhook actually works, in practice, right? _Their_ system would make the POST request to yours.) _“and with what parameters?”_ - that should be explained somewhere in their API documentation. – CBroe Mar 12 '20 at 11:04
  • it's the first time that I use a webhook and I don't know how it works – elaaa Mar 12 '20 at 11:49
  • 1
    Then you should do some reading up on that first of all. There are plenty explanations available if you just google a bit. – CBroe Mar 12 '20 at 11:55
  • thank you for your help now I understand how webhooks works – elaaa Mar 12 '20 at 12:28

2 Answers2

2

You can use the Stripe CLI to trigger a test event to your endpoint, or even to test locally by forwarding. You can also send test webhooks from your Stripe dashboard in the Webhooks section.

You should add some logging and write to a file to check the event processing to debug.

Nolan H
  • 6,205
  • 1
  • 5
  • 19
  • I recommend sending test events from the Stripe dashboard. This is how this should be done. +1 – Martin Mar 12 '20 at 21:33
  • thank you for your advice, I already tried that, but my problem was that I did not understand how to use webhooks and how to receive the response and show it without Stripe CLI so I tried to write the response into a file and I got my response now – elaaa Mar 13 '20 at 09:28
-2

So the problem with my code is that I should not access www.website.com/webhooks.php to get my response, instead, I should store the response into a database or a file or send it somewhere like so :

    <?php
    require_once('vendor/autoload.php');
    \Stripe\Stripe::setApiKey('sk_test_xxxx');

    $payload = @file_get_contents('php://input');
    $event = null;

    try {
        $event = \Stripe\Event::constructFrom(
            json_decode($payload, true)
        );
    } catch(\UnexpectedValueException $e) {
        // Invalid payload
        http_response_code(400);
        exit();
    }

    $payload = @file_get_contents('php://input');
    $event = null;

    try {
        $event = \Stripe\Event::constructFrom(
            json_decode($payload, true)
        );
    } catch(\UnexpectedValueException $e) {
        // Invalid payload
        http_response_code(400);
        exit();
    }
    print_r($payload);
    // Handle the event
    switch ($event->type) {
        case 'payment_intent.succeeded':
            $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
    //echo 'success';
            // Then define and call a method to handle the successful payment intent.
            $msg='success';
            handlePaymentIntentSucceeded($paymentIntent,$msg);
            break;
        case 'payment_intent.payment_failed':
            $paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod

            $msg='failed';
            handlePaymentIntentSucceeded($paymentMethod,$msg);
            // Then define and call a method to handle the successful attachment of a PaymentMethod.
            // handlePaymentMethodAttached($paymentMethod);
            break;
        case 'payment_intent.canceled':
            $paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod

            $msg='canceled';
            handlePaymentIntentSucceeded($paymentMethod,$msg);
            // Then define and call a method to handle the successful attachment of a PaymentMethod.
            // handlePaymentMethodAttached($paymentMethod);
            break;
        // ... handle other event types
        case 'payment_intent.created':
            $paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod

            $msg='created';
            handlePaymentIntentSucceeded($paymentMethod,$msg);
            // Then define and call a method to handle the successful attachment of a PaymentMethod.
            // handlePaymentMethodAttached($paymentMethod);
            break;
        case 'payment_intent.processing':
            $paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod

            $msg='processing';
            handlePaymentIntentSucceeded($paymentMethod,$msg);
            // Then define and call a method to handle the successful attachment of a PaymentMethod.
            // handlePaymentMethodAttached($paymentMethod);
            break;

        default:
            // Unexpected event type
            http_response_code(400);
            exit();
    }

    http_response_code(200);


    function handlePaymentIntentSucceeded($paymentIntent,$status){


        $data=[
            'amount'=>$paymentIntent->amount,
            'name'=>$paymentIntent->charges->data[0]->billing_details->name,
            'email'=>$paymentIntent->charges->data[0]->billing_details->email,
            'error'=>$paymentIntent->last_payment_error->message,
            'status'=>$status

        ];
        $date=date("Y/m/d");

        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE");
        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
    // db credentials
        define('DB_HOST', 'localhost');
        define('DB_USER', 'root');
        define('DB_PASS', '');
        define('DB_NAME', 'database');

    // Connect with the database.
        function connect()
        {
            $connect = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);

            if (mysqli_connect_errno($connect)) {
                die("Failed to connect:" . mysqli_connect_error());
            }
            mysqli_set_charset($connect, "utf8");

            return $connect;
        }

        $con = connect();




        // Store data into a database .
        $sql = "INSERT INTO `ordre`( `amount`, `email`, `name`, `status`, `msg`, `date`) VALUES ({$data['amount']},'{$data['email']}','{$data['name']}','{$data['status']}',\"{$data['error']}\",'{$date}')";



        if(mysqli_query($con,$sql))
        {
            http_response_code(201);
//to check if the storage process is done and
            $myFile = "https://6537bee0.ngrok.io/file.txt";
            $myFileLink2 = fopen($myFile2, 'w+') or die("Can't open file.");
            $newnbord ='done';
            fwrite($myFileLink2, $newnbord);
            fclose($myFileLink2);
            return $newnbord ;
        }
        else
        {  http_response_code(422);
            // write error code in a file
            http_response_code(201);
            $myFile2 = "https://6537bee0.ngrok.io/file.txt";
            $myFileLink2 = fopen($myFile2, 'w+') or die("Can't open file.");
            $newnbord =mysqli_error($con).$sql
            ;
            fwrite($myFileLink2, $newnbord);
            fclose($myFileLink2);
            return $newnbord ;

        }


    }
elaaa
  • 19
  • 1
  • 11
  • 1
    **Warning:** You are wide open to [SQL Injections](https://stackoverflow.com/a/60496/1839439) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/5741187) – Dharman Mar 14 '20 at 00:20