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

Billing for company organizations #11986

Merged
merged 135 commits into from Sep 14, 2022
Merged

Billing for company organizations #11986

merged 135 commits into from Sep 14, 2022

Conversation

sterbo and others added 30 commits July 19, 2022 08:45
- Configure environment variables
- Two new services to get/delete
- Bug fix to delete_organization
- Add tests for get/delete services
- Add support to test_delete_organization
- Fix stripe-mock api base url
- Add remaining billing tests
- Add remaining subscription tests
- Assortment of bugs squashed along the way
Search is only supported on API version 2020-08-27 or later.
- Specify Stripe `api_version` in tests
- Fix mismatched parameters for `create_checkout_session`
- Fix mismatched parameters for `create_portal_session`
- Fix mismatched parameters for `update_price`
- Fix mismatched parameters for `webhook_received`
- Update test for `add_routes`
- Update test for `webhook_received`
We currently have one metered per-seat price. This is a placeholder for
supporting an additional base price as @ewdurbin described in pypi#11986. We
will leave implementation of an additional base price for another PR.
@divbzero
Copy link
Contributor Author

@ewdurbin I think this is ready for review except for base + usage billing which we will try for but think I’d prefer leaving for a separate pull request. I have left a placeholder in commit bccf804 to support base + usage billing on the backend. On the frontend I am still investigating whether it is most straightforward to implement pricing selection as a Stripe pricing page, a Stripe checkout option, or a pricing page in Warehouse.

Copy link
Member

@ewdurbin ewdurbin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is in a good spot. One request to update the "name" for the Customer object that will end up in stripe.

One thing I'm struggling to decide on how to handle is what email address to associate with the Stripe Customer object, as this is where invoices will be sent.

I think we should consider adding a "Billing Email" to the Organization object and collecting it during signup. We need to consider the experience for Community projects when signing up though. As is, It's kind of abrupt and surprising that after a Corp project signs up, they're immediately sent into stripe checkout. Perhaps an interstitial for the Corp projects to collect any new information (there may be more) and tell them what's about to happen would be good.

This interstitial could initially just be a simple page/form saying "Hey we need to collect your billing info (email), you won't be charged, and we're about to send you to stripe checkout".

Create the Customer resource via Billing API with the given name and description
"""
return self.api.Customer.create(
name=name,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like for us to give the customers objects in Stripe names like "PyPI Organization - " since the account is shared between other PSF usage (namely pycon).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added customer name prefix in commit f292504.

Differentiate between PyPI and other customers as @ewdurbin described in
pull request pypi#11986.
@divbzero
Copy link
Contributor Author

divbzero commented Aug 19, 2022

@ewdurbin The way it’s set up right now, the billing email is collected on the Stripe Checkout page, associated with the customer in Stripe, and can be updated on the Stripe customer portal page. Is that sufficient for what we need? Or would we want to store this in the organization_stripe_customers database table as well?

@divbzero
Copy link
Contributor Author

@ewdurbin Could the interstitial be a confirmation modal or do we prefer a separate page?

@ewdurbin
Copy link
Member

@ewdurbin The way it’s set up right now, the billing email is collected on the Stripe Checkout page, associated with the customer in Stripe, and can be updated on the Stripe customer portal page. Is that sufficient for what we need? Or would we want to store this in the organization_stripe_customers database table as well?

I think it should be stored on the Organization object itself, set via the Stripe API, and blocked from change in the customer portal. I'm concerned that this particular field will be very confusing if someone is trying to change it and doesn't know to go to the Stripe billing portal.

@ewdurbin
Copy link
Member

@ewdurbin Could the interstitial be a confirmation modal or do we prefer a separate page?

Since I think we may want other functionality (like a form to collect any pertinent information, and namely billing email for now) it needs too be its own view.

sterbo and others added 16 commits September 8, 2022 09:51
- Modify `add_subscription` to include billing email
- New service for updating billing email
- Changes to `checkout.session.completed` event
- Handle `customer.updated` event
- Test model update
- Tweaks to current tests
- New tests for `customer.updated` event
- Abstract out into its own model
- Changes to interfaces and services in support of refactor
Stripe API searches product name by exact or substring match. An
additional check is needed to ensure we have an exact match.
Pluralize relation between StripeCustomer and StripeSubscription.
Conflicts resolved manually:

    requirements/lint.txt
    warehouse/locale/messages.pot
Copy link
Member

@ewdurbin ewdurbin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should get us to a functional state sufficient for another round of user testing! Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants