0

I am using Laravel Spark for billing my customers. In case they will pay with 3D Secure cards (I test it with card no. from stripe doc's https://stripe.com/docs/testing#regulatory-cards: 4000 0027 6000 3184) I have the following problem:

The stripe pop-up/modal opens and I click 'Complete Authentication'.

enter image description here

After that the authentication process starts and the user gets directed to http://127.0.0.1:8000/stripe/payment/pi_xxx?redirect=/home

Here I get the following Laravel error (I do not find other error causes in console or somewhere else):

403-error

I've added stripe/* in VerifyCsrfToken Class already... Maybe do I need to test this case on my server?

Very weird and I guess thats a sign that I do not have any issues with stripe, with laravel instead. When I remove the query parameter ?redirect=home I get this screen:

enter image description here

When I proceed I do not get redirected.. Of course because there is no redirect uri...

Does any one had this issue before?

Neneil
  • 105
  • 12
  • Shoot, I am was very glad to read this error, I am experiencing the exact same thing as we speak. Then I scrolled down, no answer! I'll check for a solution as well, will share if I find it. I have a similar error when I do a single charge payment, there is a big fat error and the user gets an email to confirm the payment. Very annoying. – helloworld Nov 21 '20 at 20:15
  • 1
    @helloworld I’ve already build a workaround as well. I will post it here tomorrow. In my opinion it’s a bug in the Spark library. – Neneil Nov 22 '20 at 15:27

2 Answers2

1

For me this is a bug in Spark. I've searched for all occurences where Stripe used a redirect. One indication for me that this could really be a bug is:

In subscription-notice.blade.php file there ist the link build as follows:

{!! __('Please :linkOpen confirm your payment :linkClose to activate your subscription!', ['linkOpen' => '<a href="/'.config('cashier.path').'/payment/'.auth()->user()->subscription()->latestPayment()->id.'?redirect='.url('/home').'">', 'linkClose' => '</a>']) !!}

The part '?redirect='.url('/home').' creates a full valid URL with host address. Not only a relative path! These relative paths runs into the 403 Error in my case. Like in the RegisterController:

/**
 * Handle a registration request for the application.
 *
 * @param  \Laravel\Spark\Contracts\Http\Requests\Auth\RegisterRequest  $request
 * @return \Illuminate\Http\Response
 */
public function register(RegisterRequest $request)
{
    list($user, $paymentId) = Spark::interact(
        Register::class, [$request]
    );

    Auth::login($user);

    event(new UserRegistered($user));

    if ($user instanceof MustVerifyEmail && ! $user->hasVerifiedEmail()) {
        $user->sendEmailVerificationNotification();
    }

    return response()->json([
        'redirect' => $paymentId ?
            '/'.config('cashier.path').'/payment/'.$paymentId.'?redirect='.$this->redirectPath()
            : $this->redirectPath(),
    ]);
}

$this->redirectPath() returns a relative path. I've changed this part into:

return response()->json([
        'redirect' => $paymentId ?
            '/'.config('cashier.path').'/payment/'.$paymentId.'?redirect='.config('app.url').$this->redirectPath()
            : $this->redirectPath(),
    ]);

In this case I took the host address from my config and put it in front of the relative path.

Just for better understanding, the returned URL above is used here (register-stripe.js):

    /*
     * After obtaining the Stripe token, send the registration to Spark.
     */
    sendRegistration(paymentMethod) {
        this.registerForm.stripe_payment_method = paymentMethod;

        Spark.post('/register', this.registerForm)
            .then(response => {
                window.location = response.redirect;
            });
    }

There are some more cases where I needed to override some JavaScript or PHP sources...

  • register process (showed here)
  • update process of payment information
  • create subscription with existing account

I hope I could help others with that! If necessary I could also post the exact places where I've changed the redirect URL in the comments.

Neneil
  • 105
  • 12
0

I came up with a (dirty?) workaround:

In my StripWebHookController there is some code that makes a notification for the user:

if ($billable) {
        $model = config('cashier.model');
        $notifiable = $billable instanceof $model ? $billable : $billable->owner;
        if (in_array(Notifiable::class, class_uses_recursive($notifiable))) {
            $payment = new Payment(StripePaymentIntent::retrieve(
                $payload['data']['object']['payment_intent'],
                $billable->stripeOptions()
            ));
            $notifiable->notify(new $notification($payment));
        }
    }

Now, this is a notification that apparently makes the StripePaymentIntent notification that is created in the PaymentController of Cashier (located /var/www/html/site/vendor/laravel/cashier/src/Http/Controllers)

There is a VerifyRedirectUrl middleware that is causing the problem right. So when you comment it out, the 403 disappears:

public function __construct()
{
    //$this->middleware(VerifyRedirectUrl::class);
}

However, the "go back" button after accepting the payment is not working so I'll check that out. But for now, this 403 is at least gone. If I can't another solution, I'll go with this.

helloworld
  • 223
  • 1
  • 7
  • 24
  • The back button was still not working, as a dirty workaround I changed the blade file that contains that go back button. Located here: /var/www/html/site/vendor/laravel/cashier/resources/views# more payment.blade.php and added this – helloworld Nov 22 '20 at 19:31