Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Stripe-Version:
- 2024-12-18.acacia
User-Agent:
- Stripe/v1 PythonBindings/11.4.1
X-Stripe-Client-User-Agent:
- '{"bindings_version": "11.4.1", "lang": "python", "publisher": "stripe", "httplib":
"requests", "lang_version": "3.12.8", "platform": "Linux-6.10.14-linuxkit-aarch64-with-glibc2.36",
"uname": "Linux f69fe8d5c257 6.10.14-linuxkit #1 SMP Fri Nov 29 17:22:03 UTC
2024 aarch64 "}'
method: GET
uri: https://api.stripe.com/v1/subscriptions/djfos?expand%5B0%5D=latest_invoice&expand%5B1%5D=customer&expand%5B2%5D=customer.invoice_settings.default_payment_method&expand%5B3%5D=customer.tax_ids
response:
body:
string: "{\n \"error\": {\n \"code\": \"resource_missing\",\n \"doc_url\":
\"https://stripe.com/docs/error-codes/resource-missing\",\n \"message\":
\"No such subscription: 'djfos'\",\n \"param\": \"id\",\n \"request_log_url\":
\"https://dashboard.stripe.com/test/logs/req_fCLmExiHliLLAy?t=1738274612\",\n
\ \"type\": \"invalid_request_error\"\n }\n}\n"
headers:
Access-Control-Allow-Credentials:
- 'true'
Access-Control-Allow-Methods:
- GET, HEAD, PUT, PATCH, POST, DELETE
Access-Control-Allow-Origin:
- '*'
Access-Control-Expose-Headers:
- Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required,
X-Stripe-Privileged-Session-Required
Access-Control-Max-Age:
- '300'
Cache-Control:
- no-cache, no-store
Connection:
- keep-alive
Content-Length:
- '324'
Content-Security-Policy:
- base-uri 'none'; default-src 'none'; form-action 'none'; frame-ancestors 'none';
img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'; upgrade-insecure-requests;
report-uri https://q.stripe.com/csp-violation?q=JU_aZLssk7a3_VZEeiDM3UWQN0mgWJiEG8zz5aFpDfoiI4Itt-XeW-vHYyCYd8ZJIklaArUO0YdslYml
Content-Type:
- application/json
Cross-Origin-Opener-Policy-Report-Only:
- same-origin; report-to="coop"
Date:
- Thu, 30 Jan 2025 22:03:32 GMT
Report-To:
- '{"group":"coop","max_age":8640,"endpoints":[{"url":"https://q.stripe.com/coop-report"}],"include_subdomains":true}'
Reporting-Endpoints:
- coop="https://q.stripe.com/coop-report"
Request-Id:
- req_fCLmExiHliLLAy
Server:
- nginx
Strict-Transport-Security:
- max-age=63072000; includeSubDomains; preload
Stripe-Version:
- 2024-12-18.acacia
Vary:
- Origin
X-Content-Type-Options:
- nosniff
X-Stripe-Priority-Routing-Enabled:
- 'true'
X-Stripe-Routing-Context-Priority-Tier:
- api-testmode
X-Wc:
- AB
status:
code: 404
message: Not Found
version: 1
53 changes: 44 additions & 9 deletions api/internal/tests/views/test_account_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,42 @@


class MockSubscription(object):
def __init__(self, subscription_params):
def __init__(self, subscription_params: dict):
self.items = {"data": [{"id": "abc"}]}
self.cancel_at_period_end = False
self.current_period_end = 1633512445
self.latest_invoice = subscription_params["latest_invoice"]
self.latest_invoice = subscription_params.get(
"latest_invoice",
{
"id": "in_123",
"status": "complete",
},
)

default_payment_method = {
"id": "pm_123",
"card": {
"brand": "visa",
"exp_month": 12,
"exp_year": 2024,
"last4": "abcd",
},
}
self.customer = {
"invoice_settings": {
"default_payment_method": subscription_params["default_payment_method"]
"default_payment_method": subscription_params.get(
"default_payment_method", default_payment_method
)
},
"id": "cus_LK&*Hli8YLIO",
"discount": None,
"email": None,
}
self.schedule = subscription_params["schedule_id"]
self.collection_method = subscription_params["collection_method"]
self.schedule = subscription_params.get("schedule_id")
self.status = subscription_params.get("status", "active")
self.collection_method = subscription_params.get(
"collection_method", "charge_automatically"
)
self.trial_end = subscription_params.get("trial_end")

customer_coupon = subscription_params.get("customer_coupon")
Expand Down Expand Up @@ -1104,6 +1125,7 @@ def test_update_payment_method_without_body(self):
response = self.client.patch(url, format="json")
assert response.status_code == status.HTTP_400_BAD_REQUEST

@patch("services.billing.StripeService._is_unverified_payment_method")
@patch("services.billing.stripe.Subscription.retrieve")
@patch("services.billing.stripe.PaymentMethod.attach")
@patch("services.billing.stripe.Customer.modify")
Expand All @@ -1114,12 +1136,15 @@ def test_update_payment_method(
modify_customer_mock,
attach_payment_mock,
retrieve_subscription_mock,
is_unverified_payment_method_mock,
):
self.current_owner.stripe_customer_id = "flsoe"
self.current_owner.stripe_subscription_id = "djfos"
self.current_owner.save()
f = open("./services/tests/samples/stripe_invoice.json")

is_unverified_payment_method_mock.return_value = False

default_payment_method = {
"card": {
"brand": "visa",
Expand Down Expand Up @@ -1435,14 +1460,15 @@ def test_update_can_change_name_and_email(self):
assert self.current_owner.name == expected_name
assert self.current_owner.email == expected_email

@patch("services.billing.stripe.Subscription.retrieve")
@patch("services.billing.StripeService.modify_subscription")
def test_update_handles_stripe_error(self, modify_sub_mock):
def test_update_handles_stripe_error(self, retrieve_sub_mock, modify_sub_mock):
code, message = 402, "Not right, wrong in fact"
desired_plan = {"value": PlanName.CODECOV_PRO_MONTHLY.value, "quantity": 12}
self.current_owner.stripe_customer_id = "flsoe"
self.current_owner.stripe_subscription_id = "djfos"
self.current_owner.save()

retrieve_sub_mock.return_value = MockSubscription({})
modify_sub_mock.side_effect = StripeError(message=message, http_status=code)

response = self._update(
Expand All @@ -1456,9 +1482,12 @@ def test_update_handles_stripe_error(self, modify_sub_mock):
assert response.status_code == code
assert response.data["detail"] == message

@patch("services.billing.stripe.Subscription.retrieve")
@patch("api.internal.owner.serializers.send_sentry_webhook")
@patch("services.billing.StripeService.modify_subscription")
def test_update_sentry_plan_monthly(self, modify_sub_mock, send_sentry_webhook):
def test_update_sentry_plan_monthly(
self, modify_sub_mock, send_sentry_webhook, retrieve_sub_mock
):
desired_plan = {"value": PlanName.SENTRY_MONTHLY.value, "quantity": 12}
self.current_owner.stripe_customer_id = "flsoe"
self.current_owner.stripe_subscription_id = "djfos"
Expand Down Expand Up @@ -1499,9 +1528,15 @@ def test_update_sentry_plan_monthly_with_users_org(
)
send_sentry_webhook.assert_called_once_with(self.current_owner, org)

@patch("services.billing.stripe.Subscription.retrieve")
@patch("api.internal.owner.serializers.send_sentry_webhook")
@patch("services.billing.StripeService.modify_subscription")
def test_update_sentry_plan_annual(self, modify_sub_mock, send_sentry_webhook):
def test_update_sentry_plan_annual(
self,
modify_sub_mock,
send_sentry_webhook,
retrieve_sub_mock,
):
desired_plan = {"value": PlanName.SENTRY_YEARLY.value, "quantity": 12}
self.current_owner.stripe_customer_id = "flsoe"
self.current_owner.stripe_subscription_id = "djfos"
Expand Down
2 changes: 2 additions & 0 deletions billing/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class StripeWebhookEvents:
"customer.updated",
"invoice.payment_failed",
"invoice.payment_succeeded",
"payment_intent.succeeded",
"setup_intent.succeeded",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO - these need to be turned on in Stripe dashboard

"subscription_schedule.created",
"subscription_schedule.released",
"subscription_schedule.updated",
Expand Down
Loading
Loading