def test_user_edit_with_subscription_info(mock1, mock2, test_user): """The user has already signed up for a subscription and now the user edit page contains information about that from Stripe.""" mock1.side_effect = mock_get_stripe_customer mock2.side_effect = mock_get_stripe_subscription_info # We need to fake the User.subscriber_number because the # 'get_stripe_subscription_info' is faked so the signals that set it are # never happening in this context. UserSubscription.set_active(test_user, "sub_123456789") # sanity check test_user.refresh_from_db() assert test_user.subscriber_number == 1 client = Client() client.force_login(test_user) response = client.post( reverse("users.user_edit", args=[test_user.username]), HTTP_HOST=settings.WIKI_HOST, ) assert response.status_code == 200 page = pq(response.content) assert page("#subscription h2").text() == "You are MDN member number 1" assert not page(".stripe-error").size() assert "MagicCard ending in 4242" in page(".card-info p").text()
def test_account_settings_delete_with_subscription( mocked_stripe, mock_create_or_update_newsletter_contact_delay, user_client, wiki_user, ): subscription_id = "sub_1234" mock_subscription = mock.MagicMock() mock_subscription.id = subscription_id mock_customer = mock.MagicMock() mock_customer.subscriptions.data.__iter__.return_value = [ mock_subscription ] mocked_stripe.Customer.retrieve.return_value = mock_customer mocked_stripe.Subscription.retrieve.return_value = mock_subscription # Also, pretend that the user has a rich profile wiki_user.stripe_customer_id = "cus_12345" wiki_user.save() UserSubscription.set_active(wiki_user, subscription_id) wiki_user.is_newsletter_subscribed = False wiki_user.save() username = wiki_user.username response = user_client.delete(reverse("api.v1.settings")) assert response.status_code == 200 assert not User.objects.filter(username=username).exists() assert not UserSubscription.objects.filter( stripe_subscription_id="sub_1234")
def test_user_edit_with_subscription_info(mock1, mock2, test_user): """The user has already signed up for a subscription and now the user edit page contains information about that from Stripe.""" mock1.side_effect = mock_get_stripe_customer mock2.side_effect = mock_get_stripe_subscription_info # We need to fake the User.subscriber_number because the # 'get_stripe_subscription_info' is faked so the signals that set it are # never happening in this context. UserSubscription.set_active(test_user, "sub_123456789") # sanity check test_user.refresh_from_db() assert test_user.subscriber_number == 1
def test_whoami_is_subscriber( user_client, wiki_user, ): """Test responses for logged-in users and whether they have an active subscription.""" url = reverse("api.v1.whoami") response = user_client.get(url) assert response.status_code == 200 assert response.json()["is_subscriber"] is False UserSubscription.set_active(wiki_user, "abc123") response = user_client.get(url) assert response.status_code == 200 assert response.json()["is_subscriber"] is True UserSubscription.set_canceled(wiki_user, "abc123") response = user_client.get(url) assert response.status_code == 200 assert response.json()["is_subscriber"] is False
def test_stripe_subscription_canceled(mock1, client): mock1.return_value = SimpleNamespace( type="customer.subscription.deleted", data=SimpleNamespace( object=SimpleNamespace(customer="cus_mock_testuser", id="sub_123456789") ), ) testuser = user( save=True, username="******", email="*****@*****.**", stripe_customer_id="cus_mock_testuser", ) UserSubscription.set_active(testuser, "sub_123456789") response = client.post( reverse("api.v1.stripe_hooks"), content_type="application/json", data={}, ) assert response.status_code == 200 (user_subscription,) = UserSubscription.objects.filter(user=testuser) assert user_subscription.canceled
def recurring_payment_management(request): context = { "support_mail_link": "mailto:" + settings.CONTRIBUTION_SUPPORT_EMAIL + "?Subject=Recurring%20payment%20support", "support_mail": settings.CONTRIBUTION_SUPPORT_EMAIL, "cancel_request": False, "cancel_success": False, } if request.user.stripe_customer_id and "stripe_cancel_subscription" in request.POST: context["cancel_request"] = True cancel_success = False try: for subscription_id in cancel_stripe_customer_subscription( request.user.stripe_customer_id): UserSubscription.set_canceled(request.user, subscription_id) except StripeError: log.exception( "Stripe subscription cancellation: Stripe error for %s [%s]", request.user.username, request.user.email, ) else: cancel_success = True context["cancel_success"] = cancel_success if request.user.stripe_customer_id: data = {"active_subscriptions": False} try: data = get_stripe_customer_data(request.user.stripe_customer_id) except StripeError: log.exception( "Stripe subscription data: Stripe error for %s [%s]", request.user.username, request.user.email, ) context.update(data) return render(request, "payments/management.html", context)
def stripe_hooks(request): try: payload = json.loads(request.body) except ValueError: return HttpResponseBadRequest("Invalid JSON payload") try: event = stripe.Event.construct_from(payload, stripe.api_key) except stripe.error.StripeError: raven_client.captureException() return HttpResponseBadRequest() # Generally, for this list of if-statements, see the create_missing_stripe_webhook # function. # The list of events there ought to at least minimally match what we're prepared # to deal with here. if event.type == "invoice.payment_succeeded": invoice = event.data.object _send_payment_received_email(invoice, request.LANGUAGE_CODE) track_event( CATEGORY_MONTHLY_PAYMENTS, ACTION_SUBSCRIPTION_CREATED, f"{settings.CONTRIBUTION_AMOUNT_USD:.2f}", ) elif event.type == "customer.subscription.deleted": obj = event.data.object for user in User.objects.filter(stripe_customer_id=obj.customer): UserSubscription.set_canceled(user, obj.id) track_event(CATEGORY_MONTHLY_PAYMENTS, ACTION_SUBSCRIPTION_CANCELED, "webhook") else: return HttpResponseBadRequest( f"We did not expect a Stripe webhook of type {event.type!r}") return HttpResponse()