laravel / cashier-stripe

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.
https://laravel.com/docs/billing
MIT License
2.37k stars 671 forks source link

Tax ID collection requires updating business name on the customer. #1585

Closed victoralbino closed 10 months ago

victoralbino commented 10 months ago

Cashier Stripe Version

13.17

Laravel Version

10.8

PHP Version

8.1

Database Driver & Version

No response

Description

Hello everybody,

I was using Cashier with Stripe (checkout). It was working normally, but I started getting this error:

"Tax ID collection requires updating business name on the customer. To enable tax ID collection for an existing customer, please set `customer_update[name]` to `auto`.
 {
      "error": {
        "message": "Tax ID collection requires updating business name on the customer. To enable tax ID collection for an existing customer, please set `customer_up ▶
        "request_log_url": "https://dashboard.stripe.com/test/logs/******",
        "type": "invalid_request_error"
      }
    }

Steps To Reproduce

Este é o meu AppServiceProvider:

<?php

namespace App\Providers;
...

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
    }
}

I'm not using Cashier::calculateTaxes();.

This is my model User which must be billable:

<?php

namespace App\Models;
...

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens;
    use HasFactory;
    use HasProfilePhoto;
    use Notifiable;
    use TwoFactorAuthenticatable;
    use HasRoles;
    use Billable;

    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    protected $hidden = [
        'password',
        'remember_token',
        'two_factor_recovery_codes',
        'two_factor_secret',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

}

And this is the controller where I try to make the subscription:

class SubscriptionController extends Controller
{

    public function __invoke(Request $request, Plan $plan)
    {
        try {
            /* @var User $user*/
            $user = auth()->user();
            $stripeCustomer = $user->createOrGetStripeCustomer();

            $subscriptionBuilder = $user->newSubscription('default', $plan->stripe_id);
            if ($plan->free_trial && !$user->onTrial()){
                $subscriptionBuilder->trialDays(31);
            }

            return $subscriptionBuilder->checkout([
                'success_url' => route('dashboard'),
                'cancel_url' => route('dashboard'),
            ])->redirect();

        }catch (\Exception $e){
            ...
        }

    }
}

All migrations were executed.

My .env file has the registered keys:

CASHIER_CURRENCY=brl
STRIPE_KEY=*******
STRIPE_SECRET=*******
STRIPE_WEBHOOK_SECRET=*******
victoralbino commented 10 months ago

I have news about the problem:

The log of my request that generates the error is this:

{
  "payment_method_types": {
    "0": "card"
  },
  "line_items": {
    "0": {
      "quantity": "1",
      "price": "price_*****"
    }
  },
  "cancel_url": "http://localhost/dashboard",
  "tax_id_collection": {
    "enabled": "false"
  },
  "customer": "cus_*****",
  "mode": "subscription",
  "success_url": "http://localhost/dashboard",
  "subscription_data": {
    "metadata": {
      "name": "default"
    },
    "trial_end": "1700872427"
  }
}

However, Stripe is considering the 'customer update' field as mandatory with the following values ​​when calling checkout:

return $subscriptionBuilder->checkout([
                    'customer_update' => ['name' => 'auto', 'address' => 'auto'],
                    'success_url' => route('dashboard'),
                    'cancel_url' => route('dashboard'),
                ])->redirect();

In theory, to fix it, it would be necessary to change the Laravel\Cashier\Checkout class in the create method by changing the following if:

if ($sessionOptions['tax_id_collection']['enabled'] ?? false) {
            $sessionOptions['customer_update']['address'] = 'auto';
            $sessionOptions['customer_update']['name'] = 'auto';
        }

to

$sessionOptions['customer_update']['address'] = 'auto';
$sessionOptions['customer_update']['name'] = 'auto';

However, as Stripe Tax is not available in my country, I cannot say if it will work properly in this situation. Although the documentation states that they are optional https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-customer_update-name

I didn't find anything stating that they are mandatory when the tax_id_collection.enabled = true

So my solution to solve it in my case was:

I add to SubscriptionController

'customer_update' => ['name' => 'auto', 'address' => 'auto'],

return $subscriptionBuilder->checkout([
                    'customer_update' => ['name' => 'auto', 'address' => 'auto'],
                    'success_url' => route('dashboard'),
                    'cancel_url' => route('dashboard'),
                ])->redirect();

It works normally again. If anyone knows if this same solution keeps everything working when Stripe Tax is active, I can send a PR later

Note: In version v14.12.3, his method was changed, but even updating the Cashier version to the latest I tested it and the error persists.

sonvlh commented 10 months ago

Have the same issue. Last day feature still works until today. I think Stripe already updated something that makes this issue happens.

I tested that removing tax_id_collection from payload if you not need to use tax will work.

Hope team can update early

Thank you.

stevebauman commented 10 months ago

I started having this same exception as well, it now looks like tax_id_collection.enabled key cannot be present in the request to create a session at all if its set to false. If I modify the vendor directory Laravel\Cashier\Checkout and unset($data['tax_id_collection']['enabled']) and comment out the customer_update block, then I'm able to get to the Stripe checkout page successfully:

https://github.com/laravel/cashier-stripe/blob/852e26d7a7824d778ffe315bdc875f3b043329ab/src/Checkout.php#L88

unset($data['tax_id_collection']['enabled']);

// Make sure to collect address and name when Tax ID collection is enabled...
// if (isset($data['customer']) && $data['tax_id_collection']['enabled'] ?? false) {
//     $data['customer_update']['address'] = 'auto';
//     $data['customer_update']['name'] = 'auto';
// }

It looks like Stripe must have changed something in their October 16th release, as I wasn't encountering this before that date:

Screenshot 2023-10-25 at 12 46 45 AM
JakeOcean commented 10 months ago

I am seeing this starting today too, but only on my dev server. Strangly both my dev and production servers are using the older API version, and have no usage on the 10/16 update, but I am still seeing the issue.