Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stripe Billing and Invoicing [FEATURE] #174

Open
cgsmith opened this issue Mar 22, 2023 · 7 comments · May be fixed by #180
Open

Stripe Billing and Invoicing [FEATURE] #174

cgsmith opened this issue Mar 22, 2023 · 7 comments · May be fixed by #180
Assignees
Labels
enhancement New feature or request

Comments

@cgsmith
Copy link
Contributor

cgsmith commented Mar 22, 2023

Is your feature request related to a problem? Please describe.
Billing right now is partly done through Stripe and manually done through Quickbooks. I want to use Stripe for everything billing out of Shipwise. The current integration is fairly broken and just adds credit cards. It also handles the invoicing but doesn't enroll them in the subscription.

Describe the solution you'd like
No migrations are necessary as I will be informing the customers of the new subscriptions and terms. They will then choose a plan and be subscribed.

I created a subscription for testing in Stripe under the test mode. Test subscription

  • Users will need a subscription to use Shipwise
  • We should leverage Stripe as much as possible for the integration. We can store the info returned in our database if necessary
  • We will be billing usage amounts to the customer
  • Customer will be billed a minimum of $70 per month plus $0.10 per order created. Stripe Product is configured to only charge after 100 order entries which is normal. You may see this in testing.
  1. A user will need a subscription to access Shipwise after registration. Related to this Add a getting started flow for customers and users to sign up for Shipwise #78
  2. If a subscription is cancelled. Shipwise will need to have an endpoint to listen for this and then stop any active integrations
  3. Create usage records on a scheduled basis reference Subscription lifecycle

Additional context
Useful documentation:

Stripe Subscription Documentation
Stripe Customer Portals

Loom explanation for @bohdan-vorona Video

@cgsmith cgsmith added the enhancement New feature or request label Mar 22, 2023
@bohdan-vorona
Copy link
Contributor

@cgsmith Pushed some latest changes - master...feature/stripe-billing-and-invoicing Docs are updated. // FYI

I'm going to finish the webhooks implementation and the {payment/subscription management} via the customer portal.


I added logic for working with Stripe webhooks, but, since we already have similar logic for Shopify, it would be great to combine some parts. I've created #177 for this. Once, these two branches are merged, I will implement this.

@bohdan-vorona
Copy link
Contributor

  • Updated SubscriptionService
  • Implemented the logic with subscription history
  • Removed some other Stripe logic and values
  • Upgraded StripeCheckoutSessionCompletedJob

Working on:

  • Changes for the /subscription page based on the changes for subscription history (active subscription is stored here)
  • Catching changes on Stripe's subscription side
  • Subscription cancel webhook

@bohdan-vorona
Copy link
Contributor

@cgsmith

  • Implemented the /subscription page (screenshot below)
  • Implemented the ability to get the latest invoice (screenshot below)
  • Added the ability to use the Customer Portal (screenshot below)

Working on:

  • Cancel subscription using the Customer Portal
  • Different switches: from trial to active, pause/resume, failed payment, etc. It's a bit time-consuming to handle these states)

curr-subs

@cgsmith
Copy link
Contributor Author

cgsmith commented Apr 5, 2023

Thanks @bohdan-vorona let me review what you currently have. I think you might be adding more of a direct integration instead of leveraging their customer portal.

No problem if you did!

@bohdan-vorona
Copy link
Contributor

bohdan-vorona commented Apr 6, 2023

Check - Stripe (webhooks + Dashboard):

  • Trial period starts (by user)
  • Trial period ends (automatically)
  • Cancel trial period (by user)
  • Switching from trial period to "real" subscription
  • Cancel "real" subscription (by user)
  • Unpaid "real" subscription (by user)
  • "Real" subscription update (by user)
  • Dashboard -> Delete customer
  • Dashboard -> Delete customer -> Delete subscription via webhook -> Delete subscription on the website
  • Dashboard -> Delete subscription -> Delete subscription via webhook -> Delete subscription on the website
  • Dashboard -> Update subscription -> Update subscription via webhook -> Update subscription on the website
  • Dashboard -> Add subscription -> Add subscription via webhook -> Add subscription on the website
  • Change plan from monthly to yearly or yearly-monthly
  • per unit

Check - website:

  • Pricing table subscription
  • Invoice
  • Customer portal
  • Cron -> Make inactive past-due subscriptions

@bohdan-vorona
Copy link
Contributor

bohdan-vorona commented Apr 10, 2023

@cgsmith In general, I've finished the main part of Stripe integration. Implemented the following webhooks: customer.deleted, checkout.session.completed, customer.subscription.created, customer.subscription.trial_will_end, customer.subscription.deleted, customer.subscription.updated.

I'm working on usage-based measurement.

Some moments I need help with:

  1. For the moment, to get the current customer I use this mock code:
$customer = Customer::findOne(1); // I find the first customer
$subscriptionService = new SubscriptionService($customer);

How shall I determine the current customer? As I see, in the User model we have such code:

    public function getCustomerId()
    {
        return $this->customer_id;
    }

But also, as I see, one user can have several customers:

    public function getCustomerIds()
    {
        return ArrayHelper::getColumn(
            $this->hasMany('frontend\models\UserCustomer', ['user_id' => 'id'])
                ->select('customer_id')
                ->asArray()
                ->all(),
            'customer_id');
    }

So, shall I use the field customer_id from the user table or ...?

  1. There was old billing logic I used:
        if (!Yii::$app->session->has($module->switchIdentitySessionKey) &&
            !Yii::$app->user->identity->isAdmin &&
            Yii::$app->user->identity->isDirectCustomer()) {
                // code...
        }

I left all these checks for my logic too. Is it correct? It means that I will check the current active subscription only if it's not an admin and is a direct customer and it's not switching between users.

  1. Please have a look at the screenshots below. Let me know if you want something to change or add.

I can propose not showing our header and footer when the user sees the pricing widget. Just add a neat button Back + Logo or something like that.


Menu:

stripe-menu

Subscription page:

stripe-subscribe

Active trial:

stripe-trial

Active subscription:

stripe-active

Thx for subscribing:

stripe-thx

Redirect if no active subscription:

stripe-redirect

@bohdan-vorona
Copy link
Contributor

Stripe qty usage:

stripe-usage

@bohdan-vorona bohdan-vorona linked a pull request Apr 12, 2023 that will close this issue
@bohdan-vorona bohdan-vorona linked a pull request Apr 12, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants