Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

1stevengrant's avatar

Register and charge with Stripe.js

I have a pretty simple form that allows users to register for an event.

The form contains all of their personal info and their CC info.

The form submits to a registration method that:

  • validates the form
  • sets the Stripe token
  • creates user in the db
  • makes the charge on Stripe
  • creates a contact registrant based on the form data in another db table

So far, this method works great for me.

public function postRegister(Request $request)
    {
        $validator = \Validator::make(\Input::all(), [
            'first_name' => 'required|string|min:2|max:32',
            'last_name' => 'required|string|min:2|max:32',
            'email' => 'required|email',
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        $token = $request->input('stripeToken');
        $first_name = $request->input('first_name');
        $last_name = $request->input('last_name');
        $email = $request->input('email');
        $emailCheck = User::where('email', $email)->value('email');

        \Stripe\Stripe::setApiKey(env('STRIPE_SK'));

        // If the email doesn't exist in the database create new customer and user record
        if (!isset($emailCheck)) {
            // Create a new Stripe customer
            try {
                $customer = \Stripe\Customer::create([
                    'source' => $token,
                    'email' => $email,
                    'metadata' => [
                        "First Name" => $first_name,
                        "Last Name" => $last_name
                    ]
                ]);
            } catch (\Stripe\Error\Card $e) {
                return redirect()->route('register')
                    ->withErrors($e->getMessage())
                    ->withInput();
            }

            $customerID = $customer->id;

            // Create a new user in the database with Stripe
            $user = User::create([
                'first_name' => $first_name,
                'last_name' => $last_name,
                'email' => $email,
            ]);
        } else {
            $customerID = User::where('email', $email)->value('stripe_customer_id');
            $user = User::where('email', $email)->first();
        }

        $amount = 2500;

        // Charging the Customer with the selected amount
        try {
            $charge = \Stripe\Charge::create([
                'amount' => $amount,
                'currency' => 'gbp',
                'source' => $token,
                'receipt_email' => $request->email,
                'description' => '2017 registration fee',
                'metadata' => [
                    'group' => $request->input('group'),
                    'name' => $request->first_name .' '. $request->last_name,
                    'email' => $request->email,
                    'phone' => $request->phone
                ]
            ]);
        } catch (\Stripe\Error\Card $e) {
            return redirect()->route('register')
                ->withErrors($e->getMessage())
                ->withInput();
        }

        // Create contact record in the database
        Contact::create([
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'address' => $request->address,
            'city' => $request->city,
            'postcode' => $request->postcode,
            'phone' => $request->phone,
            'email' => $user->email,
            'group' => $request->group,
            'stripe_transaction_id' => $charge->id,
        ]);

        return redirect()->route('register')
            ->with('successful', 'Your registration was successful! Keep an eye on your email inbox (and your junk folder too) for further choir updates.');
    }

What I'd like to do is after the contact is created, is send them an email to say that they're registered.

Referencing https://scotch.io/tutorials/ultimate-guide-on-sending-email-in-laravel

I added the Mail::send after Contact::create

Mail::send('emails.receipt', ['title' => $title, 'content' => $content], function ($message)
        {

            $message->from('[email protected]', 'Dave');

            $message->to('[email protected]);

        });

but when I add that, I get a Stripe error about not being able to use a Stripe token more than once.

Any ideas why this is coming into play now?

Thanks, Steven

0 likes
4 replies
ejdelmonico's avatar
Level 53

Listen for whichever event you broadcast when the contact is created and then create a notification to send the email. It will work well.

1stevengrant's avatar

Thanks - I've never delved into events before. I've just started looking at having the Stripe API ping a webhook on charge.succeeded which looks like a good starting point.

Granted it's not the cleanest code but should this work within my WebhookController ?

public function handle()
    {
        $payload = request()->all();

        if($payload['type'] == 'charge.succeeded') {

            $contact = new Contact();

            $contact->first_name = $payload['data']['object']['metadata']['first_name'];
            $contact->last_name = $payload['data']['object']['metadata']['last_name'];
            $contact->email = $payload['data']['object']['metadata']['email'];
            $contact->save();

            return response('Webhook received');

        }
    }
1stevengrant's avatar

That does work when all of the meta data is passed but I have an optional phone field which I guess I should want to set to null when it's not completed to still have it registered in Stripe.

ejdelmonico's avatar

I don't believe the customer object uses a phone number with the Stripe API. At least, I could not find it in the docs. Personally, I store phone number locally and process the rest with Stripe. You could probably pass it as metadata.

Please or to participate in this conversation.