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

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.

Related

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

Write message with bot after occured webhook event on STRIPE

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...

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) {...........

Magento custom payment notification

I have successfully integrated a custom payment solution for magento with a lot of help from this tutorial http://www.junaidbhura.com/how-to-make-a-custom-magento-payment-extension-for-an-external-gateway/
I am at the last stage of notifying the website if a payment has been successful or not.
I have a PaymentController.php file below but am not sure how to link this to the payment gateway notification.
The payment gateway provide a notification to the server via an HTTP GET request, letting you know if a payment was accepted or declined. This is below
http://www.websitedomain.co.uk/mygateway/payment/response?Operator=&SessionID=&Note=&Tariff=&Status=&Mobile=
The code for the payment controller where I need to enter the code is below
class Myname_Mygateway_PaymentController extends Mage_Core_Controller_Front_Action {
// The redirect action is triggered when someone places an order
public function redirectAction() {
$this->loadLayout();
$block = $this->getLayout()->createBlock('Mage_Core_Block_Template','mygateway',array('template' => 'mygateway/redirect.phtml'));
$this->getLayout()->getBlock('content')->append($block);
$this->renderLayout();
}
// The response action is triggered when your gateway sends back a response after processing the customer's payment
public function responseAction() {
if($this->getRequest()->isPost()) {
/*
/* Your gateway's code to make sure the reponse you
/* just got is from the gatway and not from some weirdo.
/* This generally has some checksum or other checks,
/* and is provided by the gateway.
/* For now, we assume that the gateway's response is valid
*/
$validated = true;
$orderId = ''; // Generally sent by gateway
if($validated) {
// Payment was successful, so update the order's state, send order email and move to the success page
$order = Mage::getModel('sales/order');
$order->loadByIncrementId($orderId);
$order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true, 'Gateway has authorized the payment.');
$order->sendNewOrderEmail();
$order->setEmailSent(true);
$order->save();
Mage::getSingleton('checkout/session')->unsQuoteId();
Mage_Core_Controller_Varien_Action::_redirect('checkout/onepage/success', array('_secure'=>true));
}
else {
// There is a problem in the response we got
$this->cancelAction();
Mage_Core_Controller_Varien_Action::_redirect('checkout/onepage/failure', array('_secure'=>true));
}
}
else
Mage_Core_Controller_Varien_Action::_redirect('');
}
// The cancel action is triggered when an order is to be cancelled
public function cancelAction() {
if (Mage::getSingleton('checkout/session')->getLastRealOrderId()) {
$order = Mage::getModel('sales/order')->loadByIncrementId(Mage::getSingleton('checkout/session')->getLastRealOrderId());
if($order->getId()) {
// Flag the order as 'cancelled' and save it
$order->cancel()->setState(Mage_Sales_Model_Order::STATE_CANCELED, true, 'Gateway has declined the payment.')->save();
}
}
}
}
You have the line $validated = true;
Here you have to enter your own conditions if the payment has been validated.
So if this is the response from the payment gateway use the variables in the response
http://www.websitedomain.co.uk/mygateway/payment/response?Operator=&SessionID=&Note=&Tariff=&Status=&Mobile=
for example
if ( $_GET('Status') == 'Paid' ){
$validated = true;
}
You have to read the payment gateway documentation on info for their codes. For example the Status variable can have values like "Paid", "Pending", "Expired" or "1", "2", "3". Depends on the gateway.

Categories