Write message with bot after occured webhook event on STRIPE - php

I'm setting my webhook STRIPE and i want to send message on Telegram when happen event in STRIPE (checkout.session.completed so after payment).
To set webhook is very easy so i'm sure the problem is really easy (just not for me).
\Stripe\Stripe::setApiKey('sk_test_xxx');
// You can find your endpoint's secret in your webhook settings
$endpoint_secret = 'whsec_...';
$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();
}
// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
$session = $event->data->object;
// Fulfill the purchase...
handle_checkout_session($session);
}
http_response_code(200);
If payment is successfull (so if $event->type == 'checkout.session.completed') i want to write a message on telegram.
To write message is very easy:
$url= 'https://api.telegram.org/botxxx/sendMessage?chat_id=xxx&parse_mode=HTML&text=ok-webhook';
file_get_contents($url);
Why doesn't work ?
I tried to put it (code to write message) inside last if but nothing.
I know payment works because i can read the request to my endpoint and status code 200 (OK).
I hope you can help me...

Related

Unable to decode credential from JWT

I am trying to implement the new "Sign in with Google" button as described in https://developers.google.com/identity/gsi/web/guides/display-button.
Everything is fine, and I am able to get a response from the button with "credential" and "g_csrf_token" elements, which I can send to my server. However, using the Google API Client to decode the credential doesn't work. I'm trying to follow the instructions.
Here's my code:
$id_token = filter_input(INPUT_POST, 'credential');
$csrfToken = filter_input(INPUT_POST, 'g_csrf_token'); //??? Do we need this?
$client = new Google_Client(['client_id' => $clientid]);
$client->addScope("email"); // Recommended in another StackOverflow answer but makes no difference
try {
$payload = $client->verifyIdToken($id_token);
} catch(Exception $ex) {
$errorMessage = "Error in verifyIdToken():" . $ex->getMessage();
// ...do stuff with the error message
}
// ...do stuff with the returned payload
The result is the error message id_token must be passed in or set as part of setAccessToken.
I've updated my Google API Client to v2.11.
I assume that I've missed a step somewhere - can someone help?
Have found a solution, by trial and error! Turns out that $id_token needs to be passed to the client twice, once in setAccessToken() and then again in verifyIdToken(). Omitting setAccessToken fails (like the error message says), but if you pass it in setAccessToken but NOT in verifyIdToken, that doesn't work either.
$id_token = filter_input(INPUT_POST, 'credential');
$client = new Google_Client(['client_id' => $clientid]);
try {
$client->setAccessToken($id_token);
$payload = $client->verifyIdToken($id_token);
} catch(Exception $ex) {
$errorMessage = "Error in verifyIdToken():" . $ex->getMessage();
// ...do stuff with the error message
}
// ...do stuff with the returned payload
It would nice, if you're at Google and picking this up, if you updated the documentation.

Why my Stripe Webhook function is not working(test mode)?

I has create a webhook php to trigger the paymentintent event status. I had successfully tigger it but the function of detected event is no working which i just want to redirect to another page if successful or not. I try to echo text, it also not showing. I can see the response body(show the text that i want to echo" in the dashboard of Stripe. Did i misunderstanding the concept of it ? This is my code:
<?php
/*
Template Name: webhook
*/
include_once(get_template_directory_uri().'/customFile/stripe-php-7.71.0/init.php');
\Stripe\Stripe::setApiKey('xxx'); // this is true, i just replace with xxx
$payload = #file_get_contents('php://input');
$event = null;
$paymentstatus = "Payment Failed";
try {
$event = \Stripe\Event::constructFrom(
json_decode($payload, true)
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
//handlePaymentIntentSucceeded($paymentIntent);
echo"Success";
echo "<script>location.href='http://localhost/wordpress/';</script>";
break;
case 'payment_intent.payment_failed':
$paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod
//handlePaymentMethodAttached($paymentMethod);
echo "<script>location.href='http://localhost/wordpress/shop/';</script>";
break;
}
http_response_code(200);
Webhooks are requests that come from Stripe to your web server. There's no user attached to these events so trying to redirect after you receive a webhook event makes no sense. All that's happening is you're sending a <script> string back to Stripe, who promptly ignores it because all they are about is the response status code.
If you want to redirect your user after they've made a successful payment, you should either that on the client after they've confirmed the PaymentIntent or in your success_url if you're using Checkout.

Stripe webhook test returns http 500 error

Here's my code:
<?php
$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();
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object;
$paymentintentid = $paymentIntent['id'];
break;
default:
// Unexpected event type
http_response_code(400);
exit();
}
http_response_code(200);
?>
It's basically the example code from here: https://stripe.com/docs/webhooks/build
What I'm trying to do is grab the PaymentIntent ID via $paymentIntent['id'];
But when I run the test webhook, Stripe says it returns Http error 500.
I'm not as advanced in PHP as their script needs me to be, so I'm not sure if I'm missing any data or code. Looks like I may need to include some file, since Stripe wants me to use their own classes?
Here's the PaymentIntent documentation: https://stripe.com/docs/api/payment_intents/create
Did you use composer to add the Stripe dependencies? If so, are you including your autoload file from composer? The Stripe classes need to be loaded or included in some way. This is part of the 500 error.
Full working code from my test:
<?php
require '../vendor/autoload.php'; \\ replace with the actual location of your autoload file
$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();
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object;
$paymentintentid = $paymentIntent['id']; \\ $paymentIntent->id works as well.
echo $paymentintentid;
break;
default:
// Unexpected event type
http_response_code(400);
exit();
}
http_response_code(200);
?>
If you wanna take it a step further, I recommend sending a response back to Stripe so you can see them when testing in the UI.
Example response:
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object;
// Store the payment ID from the webhook
$paymentintentid = $paymentIntent['id'];
// Set array for successful response
$response = array(
'http_code' => 200,
'payment_id' => $paymentintentid,
'response' => 'webhook caught successfully'
);
// Set status code and echo back response
http_response_code(200);
echo json_encode($response, true);
break;
default:
// Unexpected event type, set array for this case
$response = array(
'http_code' => 400,
'response' => 'Unexpected event type'
);
// Set status code and echo back response
http_response_code(400);
echo json_encode($response, true);
exit();
}
Example testing shown in the stripe UI for 200 response:
Stripe 200 response sample in Stripe UI showing response from my server
Example testing shown in the stripe UI for 400 response:
Stripe 400 response sample in Stripe UI showing response from my server

Stripe - 'Send Test Webhook' working but not logged in 'Webhook Attempts' list

I am using Stripe API and webhooks to link payments to my website. I have a webhook listener at https://mywebsite.com/hook.php. When I send a test webhook through Stripe's developer dashboard, I receive my expected response of hello world.
However, in my list of webhook attempts, this request was not logged (this request was sent ~2 hours after the last request on this list.
Here is my PHP webhook code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once('/var/www/html/vendor/autoload.php');
\Stripe\Stripe::setApiKey("sk_test_CHANGEDFORTHISSOQUESTION"); //test
// Retrieve the request's body and parse it as JSON
$payload = #file_get_contents("php://input");
// Return a response to acknowledge receipt of the event
http_response_code(200);
echo("hello world");
$endpoint_secret = "whsec_CHANGEDFORTHISSOQUESTION"; //test
$sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
// Do something with $event_json
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400); // PHP 5.4 or greater
exit();
} catch(\Stripe\Error\SignatureVerification $e) {
// Invalid signature
http_response_code(400); // PHP 5.4 or greater
exit();
}

stripe, multiple requests using idempotency keys return errors

Need assistance with Stripe error response.
Everything seems to work according to stripe dashboard logs when creating a Customer and then enrolling them into a Subscription therefore generating a Charge, in the event where there are multiple requests made with idempotency keys in place.
How ever in this event I get this stripe error response (capture of the exception $error6) which opens up as a page (charge.php) where the code runs, instead of sending to success page.
charge.php
\Stripe\Stripe::setApiKey('sk_live_xxxxxxxxxxx');
$POST = filter_var_array($_POST, FILTER_SANITIZE_STRING);
$email = $POST['email'];
$token = $POST['stripeToken'];
$membership_type = $POST['membership_type'];
$user_id = $POST['user_id'];
$success = 0;
try {
// Create customer in Stripe
$customer = \Stripe\Customer::create([
"email" => $email,
"source" => $token,
],[
"idempotency_key" => $_SESSION['sid2'],
]);
$success = 1;
} catch(Stripe_CardError $e) {
$error1 = $e->getMessage();
} catch (Stripe_InvalidRequestError $e) {
// Invalid parameters were supplied to Stripe's API
$error2 = $e->getMessage();
} catch (Stripe_AuthenticationError $e) {
// Authentication with Stripe's API failed
$error3 = $e->getMessage();
} catch (Stripe_ApiConnectionError $e) {
// Network communication with Stripe failed
$error4 = $e->getMessage();
} catch (Stripe_Error $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
$error5 = $e->getMessage();
} catch (Exception $e) {
// Something else happened, completely unrelated to Stripe
$error6 = $e->getMessage();
}
if ($success!=1)
{
$_SESSION['error1'] = $error1;
$_SESSION['error2'] = $error2;
$_SESSION['error3'] = $error3;
$_SESSION['error4'] = $error4;
$_SESSION['error5'] = $error5;
$_SESSION['error6'] = $error6;
print_r($_SESSION);
}
// Add Customer to a Subscription in Stripe
$subscription = \Stripe\Subscription::create([
'customer' => $customer->id,
'items' => [['plan' => $membership_type]]
],[
"idempotency_key" => $_SESSION['sid'],
]);
//adding all relevent info into data base...
//send user to success page
header('Location: ../success.php?id='.$user_id.'&product='.$subscription->plan->nickname);
Could this be because each time the Stripe JS $token parameter changes? is this normal or am I doing something wrong? (I got a similar error when running idempotency only on Subscribing a Customer but then stripe creates multiple customers with the same email and payment cards but different customer->id)
Can anyone kindly suggest how can I resolve this error page?
Could this be because each time the Stripe JS $token parameter changes?
Yes, I suspect what's happening here is that you are reusing $_SESSION['sid2'] for two separate requests with different source parameters to create a Customer. And this error in response is the expected behavior!
You should be able to see this in your Dashboard logs: Assuming this is a test mode request, https://dashboard.stripe.com/test/logs/iar_IgylJRGpbLyVb6 should tell you where the same key was originally used.
best option i could find is disabling the button after the Stripe JS event listener
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
$('.button').attr("disabled", true);
stripe.createToken(card).then(function(result) {...........

Categories