cashier-stripe: Proration Invoice after subscription swap do not include tax, if tax is used

Turns out the proration invoice created by cashier does not include tax when a tax amount is defined. This should be changed. Here is an example how to change the invoice() method in Billable.php:

/**
     * Invoice the billable entity outside of regular billing cycle.
     *
     * @return StripeInvoice|bool
     */
    public function invoice()
    {
        if ($this->stripe_id) {
            try {
                return StripeInvoice::create(['customer' => $this->stripe_id, 'tax_percent' => $this->taxPercentage()], $this->getStripeKey())->pay();
            } catch (StripeErrorInvalidRequest $e) {
                return false;
            }
        }

        return true;
    }

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 23 (7 by maintainers)

Most upvoted comments

@Mr-Anonymous Well, technically you don’t have to do this in the Billable Trait itself, but you can just define your own swap method in the Model that is billable. In my instance I have a custom swap method in my Tenant model, because I exclusively bill tenants:

public function swapWLPlan($plan)
    {
        $subscription = $this->asStripeCustomer()->subscriptions->retrieve($this->subscription('main')->stripe_id);

        $subscription->plan = $plan;

        $subscription->prorate = true;

        if (! is_null($this->subscription('main')->billingCycleAnchor)) {
            $subscription->billingCycleAnchor = $this->subscription('main')->billingCycleAnchor;
        }

        // If no specific trial end date has been set, the default behavior should be
        // to maintain the current trial state, whether that is "active" or to run
        // the swap out with the exact number of days left on this current plan.
        if ($this->onTrial()) {
            $subscription->trial_end = $this->subscription('main')->trial_ends_at->getTimestamp();
        } else {
            $subscription->trial_end = 'now';
        }

        // Again, if no explicit quantity was set, the default behaviors should be to
        // maintain the current quantity onto the new plan. This is a sensible one
        // that should be the expected behavior for most developers with Stripe.
        if ($this->subscription('main')->quantity) {
            $subscription->quantity = $this->subscription('main')->quantity;
        }

        $subscription->tax_percent = $this->taxPercentage();

        $subscription->save();

        if ($this->stripe_id) {
            try {
                $proration_invoice = StripeInvoice::create(['customer' => $this->stripe_id, 'tax_percent' => $subscription->tax_percent], $this->getStripeKey())->pay();
            } catch (StripeErrorInvalidRequest $e) {
                $proration_invoice = false;
            }
        }

        $this->subscription('main')->fill([
            'stripe_plan' => $plan,
            'ends_at' => null,
        ])->save();

        return $this;
    }

Obviously this needs to be maintained when an update breaks with the previous Billable Trait. Thats why I opened this issue, so it could be fixed with the next version.

I’ve sent in a PR which should fix the issue from @emergingdzns and provide @jlmmns with a way to add the tax_percent to one off invoices: https://github.com/laravel/cashier/pull/598

I see. Thanks for researching this. The proper way to solve this is to create an invoice method on the Subscription model I believe. And let the swap and incrementAndInvoice methods call those instead. This will be the cleanest solution.

I can send a PR for this later, otherwise feel free to send one in already.

Noted and I understand. Thank you though and I apologise if it went off topic.