winnery
winnery

Reputation: 31

How to implement stripe webhook in symfony 5?

I have integrated Stripe in my symfony project for subscriptions, the subscription to plans from stripe and payment it works just fine, but the problem is that i couldn't implement the webhook in the right way so i can know if a subscription is created, payed etc.

what i have done so far: in my subscription controller i created the route to the webhook:

class SubscriptionController extends AbstractController
{
    /**
     * webhook  page
     *
     * @Route("/bonsai_webhook",name="webhookPage")
     */
    public function bonsai_webook(Request $request,Response $response){
        \Stripe\Stripe::setApiKey('sk_test_...');
        $webhookSecret = "whsec_...";
        $event = $request->query;
        // Parse the message body and check the signature
        $signature = $request->headers->get('stripe-signature');
        if ($webhookSecret) {
            try {
                $event = \Stripe\Webhook::constructEvent(
                    $request->getcontent(),
                    $signature,
                    $webhookSecret
                );
            } catch (\Exception $e) {
                return new JsonResponse([['error' => $e->getMessage(),'status'=>403]]);
            }
        } else {
            $request->query;
        }
        $type = $event['type'];
        $object = $event['data']['object'];
        $manager = $this->getDoctrine()->getManager();
        $today = date("Y-m-d",strtotime('today'));
        switch ($type) {
            case 'checkout.session.completed':
                // Payment is successful and the subscription is created.
                // You should provision the subscription.
                $user->setSubEndDate($today);
                $manager->persist($user);
                $manager->flush();
                break;
            case 'invoice.paid':
                // Continue to provision the subscription as payments continue to be made.
                // Store the status in your database and check when a user accesses your service.
                // This approach helps you avoid hitting rate limits.
                break;
            case 'invoice.payment_failed':
                // The payment failed or the customer does not have a valid payment method.
                // The subscription becomes past_due. Notify your customer and send them to the
                // customer portal to update their payment information.
                break;
            // ... handle other event types
            default:
                // Unhandled event type
        }

        return new JsonResponse([['session'=>$session,'status'=>200]]);
    }

when i run./stripe listen --forward-to https://localhost:8000/bonsai_webhook and try to create a subscription i got

customer.created [evt_1IYs4HKoLZxEIn3zDY5tFGZV]
2021-03-25 13:13:41            [307] POST http://localhost:8000/bonsai_webhook [evt_1IZ2SeKoLZxEIn3zvx1urxJ1]

and in in the webhook route i got [{"error":"Unable to extract timestamp and signatures from header","status":403}] there is no stripe signature is always empty , and i don't know what i did wrong.

i also added some logs

$logger->info($request->headers->get('stripe-signature'),$request->headers->all());
$logger->error($request->headers->get('stripe-signature'),$request->headers->all());
$logger->critical($request->headers->get('stripe-signature'),$request->headers->all());

and i did never receive the logs from the trigger create.subscription.event

so my question is: how to get the stripe signature ? and i hope its the only thing missing in my code.

Thank you.

Upvotes: 2

Views: 2569

Answers (3)

Michael Hirschler
Michael Hirschler

Reputation: 2518

In a more recent version of stripe (e.g. 1.11.0 and above) the certificate check can be skipped using --skip-verify.

So in any case someone is stumble upon the same issue like the author:

# listen on HTTPS but do not verify SSL/TLS certificate
stripe listen --forward-to https://localhost:8000/bonsai_webhook --skip-verify

Upvotes: 1

winnery
winnery

Reputation: 31

I just figure it out with the help of the stripe communit, my server was trying to redirect to a https:// URL(that's what the 307 redirect is). Setting https:// in the webhook URL doesn't work because it's a self-signed certificate. And the solution was to disable SSL/HTTPS entirely on the local application, instead i switched to an https environement on a server .

Upvotes: 0

Justin Michael
Justin Michael

Reputation: 6495

The error you're seeing indicates the HTTPS certificate you're using locally isn't recognized as valid by Stripe CLI.

I recommend trying the command with http:// instead of https://:

./stripe listen --forward-to http://localhost:8000/bonsai_webhook

If your web server allows insecure local connections that should get things working.

Upvotes: 2

Related Questions