mirror of https://github.com/zulip/zulip.git
billing: Move most Stripe code to its own file.
We'll handle the error-handling in a separate commit, as it's still entangled with the view function.
This commit is contained in:
parent
5feb31a957
commit
0b81762350
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
import stripe
|
||||||
|
from stripe.error import CardError, RateLimitError, InvalidRequestError, \
|
||||||
|
AuthenticationError, APIConnectionError, StripeError
|
||||||
|
|
||||||
|
from zerver.lib.logging_util import log_to_file
|
||||||
|
from zerver.models import Realm, UserProfile
|
||||||
|
from zilencer.models import Customer
|
||||||
|
from zproject.settings import get_secret
|
||||||
|
|
||||||
|
STRIPE_SECRET_KEY = get_secret('stripe_secret_key')
|
||||||
|
STRIPE_PUBLISHABLE_KEY = get_secret('stripe_publishable_key')
|
||||||
|
stripe.api_key = STRIPE_SECRET_KEY
|
||||||
|
|
||||||
|
BILLING_LOG_PATH = os.path.join('/var/log/zulip'
|
||||||
|
if not settings.DEVELOPMENT
|
||||||
|
else settings.DEVELOPMENT_LOG_DIRECTORY,
|
||||||
|
'billing.log')
|
||||||
|
billing_logger = logging.getLogger('zilencer.stripe')
|
||||||
|
log_to_file(billing_logger, BILLING_LOG_PATH)
|
||||||
|
log_to_file(logging.getLogger('stripe'), BILLING_LOG_PATH)
|
||||||
|
|
||||||
|
def count_stripe_cards(realm: Realm) -> int:
|
||||||
|
try:
|
||||||
|
customer_obj = Customer.objects.get(realm=realm)
|
||||||
|
cards = stripe.Customer.retrieve(customer_obj.stripe_customer_id).sources.all(object="card")
|
||||||
|
return len(cards["data"])
|
||||||
|
except Customer.DoesNotExist:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def save_stripe_token(user: UserProfile, token: str) -> int:
|
||||||
|
"""Returns total number of cards."""
|
||||||
|
# The card metadata doesn't show up in Dashboard but can be accessed
|
||||||
|
# using the API.
|
||||||
|
card_metadata = {"added_user_id": user.id, "added_user_email": user.email}
|
||||||
|
try:
|
||||||
|
customer_obj = Customer.objects.get(realm=user.realm)
|
||||||
|
customer = stripe.Customer.retrieve(customer_obj.stripe_customer_id)
|
||||||
|
billing_logger.info("Adding card on customer %s: source=%r, metadata=%r",
|
||||||
|
customer_obj.stripe_customer_id, token, card_metadata)
|
||||||
|
card = customer.sources.create(source=token, metadata=card_metadata)
|
||||||
|
customer.default_source = card.id
|
||||||
|
customer.save()
|
||||||
|
return len(customer.sources.all(object="card")["data"])
|
||||||
|
except Customer.DoesNotExist:
|
||||||
|
customer_metadata = {"string_id": user.realm.string_id}
|
||||||
|
# Description makes it easier to identify customers in Stripe dashboard
|
||||||
|
description = "{} ({})".format(user.realm.name, user.realm.string_id)
|
||||||
|
billing_logger.info("Creating customer: source=%r, description=%r, metadata=%r",
|
||||||
|
token, description, customer_metadata)
|
||||||
|
customer = stripe.Customer.create(source=token,
|
||||||
|
description=description,
|
||||||
|
metadata=customer_metadata)
|
||||||
|
|
||||||
|
card = customer.sources.all(object="card")["data"][0]
|
||||||
|
card.metadata = card_metadata
|
||||||
|
card.save()
|
||||||
|
Customer.objects.create(realm=user.realm, stripe_customer_id=customer.id)
|
||||||
|
return 1
|
|
@ -1,6 +1,4 @@
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
from typing import Any, Dict, Optional, Text, Union, cast
|
from typing import Any, Dict, Optional, Text, Union, cast
|
||||||
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
@ -10,13 +8,9 @@ from django.shortcuts import render
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.views.decorators.http import require_GET
|
from django.views.decorators.http import require_GET
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
import stripe
|
|
||||||
from stripe.error import CardError, RateLimitError, InvalidRequestError, \
|
|
||||||
AuthenticationError, APIConnectionError, StripeError
|
|
||||||
|
|
||||||
from zerver.decorator import require_post, zulip_login_required
|
from zerver.decorator import require_post, zulip_login_required
|
||||||
from zerver.lib.exceptions import JsonableError
|
from zerver.lib.exceptions import JsonableError
|
||||||
from zerver.lib.logging_util import log_to_file
|
|
||||||
from zerver.lib.push_notifications import send_android_push_notification, \
|
from zerver.lib.push_notifications import send_android_push_notification, \
|
||||||
send_apple_push_notification
|
send_apple_push_notification
|
||||||
from zerver.lib.request import REQ, has_request_variables
|
from zerver.lib.request import REQ, has_request_variables
|
||||||
|
@ -24,20 +18,9 @@ from zerver.lib.response import json_error, json_success
|
||||||
from zerver.lib.validator import check_int
|
from zerver.lib.validator import check_int
|
||||||
from zerver.models import UserProfile, Realm
|
from zerver.models import UserProfile, Realm
|
||||||
from zerver.views.push_notifications import validate_token
|
from zerver.views.push_notifications import validate_token
|
||||||
from zilencer.models import RemotePushDeviceToken, RemoteZulipServer, Customer
|
from zilencer.lib.stripe import STRIPE_PUBLISHABLE_KEY, count_stripe_cards, \
|
||||||
from zproject.settings import get_secret
|
save_stripe_token, CardError, StripeError, billing_logger
|
||||||
|
from zilencer.models import RemotePushDeviceToken, RemoteZulipServer
|
||||||
STRIPE_SECRET_KEY = get_secret('stripe_secret_key')
|
|
||||||
STRIPE_PUBLISHABLE_KEY = get_secret('stripe_publishable_key')
|
|
||||||
stripe.api_key = STRIPE_SECRET_KEY
|
|
||||||
|
|
||||||
BILLING_LOG_PATH = os.path.join('/var/log/zulip'
|
|
||||||
if not settings.DEVELOPMENT
|
|
||||||
else settings.DEVELOPMENT_LOG_DIRECTORY,
|
|
||||||
'billing.log')
|
|
||||||
billing_logger = logging.getLogger('zilencer.stripe')
|
|
||||||
log_to_file(billing_logger, BILLING_LOG_PATH)
|
|
||||||
log_to_file(logging.getLogger('stripe'), BILLING_LOG_PATH)
|
|
||||||
|
|
||||||
def validate_entity(entity: Union[UserProfile, RemoteZulipServer]) -> None:
|
def validate_entity(entity: Union[UserProfile, RemoteZulipServer]) -> None:
|
||||||
if not isinstance(entity, RemoteZulipServer):
|
if not isinstance(entity, RemoteZulipServer):
|
||||||
|
@ -121,44 +104,6 @@ def remote_server_notify_push(request: HttpRequest, entity: Union[UserProfile, R
|
||||||
|
|
||||||
return json_success()
|
return json_success()
|
||||||
|
|
||||||
def count_stripe_cards(realm: Realm) -> int:
|
|
||||||
try:
|
|
||||||
customer_obj = Customer.objects.get(realm=realm)
|
|
||||||
cards = stripe.Customer.retrieve(customer_obj.stripe_customer_id).sources.all(object="card")
|
|
||||||
return len(cards["data"])
|
|
||||||
except Customer.DoesNotExist:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def save_stripe_token(user: UserProfile, token: str) -> int:
|
|
||||||
"""Returns total number of cards."""
|
|
||||||
# The card metadata doesn't show up in Dashboard but can be accessed
|
|
||||||
# using the API.
|
|
||||||
card_metadata = {"added_user_id": user.id, "added_user_email": user.email}
|
|
||||||
try:
|
|
||||||
customer_obj = Customer.objects.get(realm=user.realm)
|
|
||||||
customer = stripe.Customer.retrieve(customer_obj.stripe_customer_id)
|
|
||||||
billing_logger.info("Adding card on customer %s: source=%r, metadata=%r",
|
|
||||||
customer_obj.stripe_customer_id, token, card_metadata)
|
|
||||||
card = customer.sources.create(source=token, metadata=card_metadata)
|
|
||||||
customer.default_source = card.id
|
|
||||||
customer.save()
|
|
||||||
return len(customer.sources.all(object="card")["data"])
|
|
||||||
except Customer.DoesNotExist:
|
|
||||||
customer_metadata = {"string_id": user.realm.string_id}
|
|
||||||
# Description makes it easier to identify customers in Stripe dashboard
|
|
||||||
description = "{} ({})".format(user.realm.name, user.realm.string_id)
|
|
||||||
billing_logger.info("Creating customer: source=%r, description=%r, metadata=%r",
|
|
||||||
token, description, customer_metadata)
|
|
||||||
customer = stripe.Customer.create(source=token,
|
|
||||||
description=description,
|
|
||||||
metadata=customer_metadata)
|
|
||||||
|
|
||||||
card = customer.sources.all(object="card")["data"][0]
|
|
||||||
card.metadata = card_metadata
|
|
||||||
card.save()
|
|
||||||
Customer.objects.create(realm=user.realm, stripe_customer_id=customer.id)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
@zulip_login_required
|
@zulip_login_required
|
||||||
def add_payment_method(request: HttpRequest) -> HttpResponse:
|
def add_payment_method(request: HttpRequest) -> HttpResponse:
|
||||||
user = request.user
|
user = request.user
|
||||||
|
|
Loading…
Reference in New Issue