You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

401 lines
12 KiB
Python

from datetime import timedelta
from django.test import TestCase, RequestFactory
from django.contrib.auth.models import User
5 years ago
from payments.models import Payment, Subscription
from payments.backends import StripeBackend
5 years ago
def MockSession(id):
class MockSession(dict):
def __init__(self, args):
args['id'] = id
super().__init__(args)
@classmethod
def create(cls, **kwargs):
c = MockSession(kwargs)
cls._INST = c
return c
return MockSession
class MockWebhook:
@classmethod
def construct_event(cls, payload, sig, key):
assert sig == "hewwo", sig
assert key == "test_wh_key", key
assert payload == b"opak", payload
return cls.evt
class StripeBackendTest(TestCase):
def setUp(self):
self.user = User.objects.create_user('test', 'test_user@example.com', None)
def test_stripe(self):
payment = Payment.objects.create(
user=self.user,
time=timedelta(days=30),
backend_id='stripe',
amount=300
)
5 years ago
payment.save()
sess_id = 'cs_test_UKHmmetjaiperdu0wxGppeerrdduuhSslYaaaaaa0eU6aaaaaaaaaWSX'
settings = dict(
secret_key='test_secret_key',
public_key='test_public_key',
wh_key='test_wh_key',
currency='EUR',
name='Test Name',
)
5 years ago
backend = StripeBackend(settings)
assert backend.backend_enabled
backend.stripe = type('Stripe', (object, ), {
'checkout': type('checkout', (object, ), {
'Session': MockSession(sess_id),
}),
'Webhook': MockWebhook,
'error': type('error', (object, ), {
'InvalidRequestError': type('', (Exception, ), {}),
'SignatureVerificationError': type('', (Exception, ), {}),
'CardError': type('CardError', (Exception, ), {}),
}),
})
with self.settings(ROOT_URL='root'):
form_html = backend.new_payment(payment)
5 years ago
assert 'test_public_key' in form_html
sess = backend.stripe.checkout.Session._INST
self.assertEqual(sess['success_url'], 'root/payments/view/%d' % payment.id)
self.assertEqual(sess['line_items'][0]['amount'], payment.amount)
request = RequestFactory().post('', 'opak', content_type='text/plain', HTTP_STRIPE_SIGNATURE="hewwo")
backend.stripe.Webhook.evt = CHECKOUT_SESSION_COMPLETED__ONE
backend.webhook(request)
payment = Payment.objects.get(id=payment.id)
self.assertEqual(payment.status, 'confirmed')
self.assertEqual(payment.paid_amount, 300)
self.assertEqual(payment.backend_extid, sess_id)
def test_stripe_sub(self):
sub = Subscription.objects.create(
user=self.user,
period='3m',
backend_id='stripe',
)
settings = dict(
secret_key='test_secret_key',
public_key='test_public_key',
wh_key='test_wh_key',
currency='EUR',
name='Test Name',
)
backend = StripeBackend(settings)
assert backend.backend_enabled
backend.stripe = type('Stripe', (object, ), {
5 years ago
'checkout': type('checkout', (object, ), {
'Session': MockSession("in_FjSMAw7ufaEBOG"),
}),
5 years ago
'Webhook': MockWebhook,
'error': type('error', (object, ), {
5 years ago
'InvalidRequestError': type('', (Exception, ), {}),
'SignatureVerificationError': type('', (Exception, ), {}),
'CardError': type('CardError', (Exception, ), {}),
}),
})
5 years ago
with self.settings(ROOT_URL='root'):
form_html = backend.new_subscription(sub)
assert 'test_public_key' in form_html
sess = backend.stripe.checkout.Session._INST
self.assertEqual(sess['success_url'], 'root/payments/return_subscr/%d' % sub.id)
self.assertEqual(sess['subscription_data']['items'][0]['plan'], 'ccvpn_3m')
request = RequestFactory().post('', 'opak', content_type='text/plain', HTTP_STRIPE_SIGNATURE="hewwo")
backend.stripe.Webhook.evt = checkout_session_completed__sub(sub)
backend.webhook(request)
backend.stripe.Webhook.evt = INVOICE_PAYMENT_SUCCEEDED
backend.webhook(request)
sub = Subscription.objects.get(id=sub.id)
payment = sub.payment_set.all()[0]
self.assertEqual(sub.status, 'active')
self.assertEqual(payment.status, 'confirmed')
self.assertEqual(payment.paid_amount, 900)
self.assertEqual(payment.backend_extid, 'in_FjSMAw7ufaEBOG')
CHECKOUT_SESSION_COMPLETED__ONE = {
"id": "evt_FkzwrsBSh0da66",
"object": "event",
"api_version": "2019-08-14",
"created": 1567705834,
"data": {
"object": {
"id": "cs_test_UKHmmetjaiperdu0wxGppeerrdduuhSslYaaaaaa0eU6aaaaaaaaaWSX",
"object": "checkout.session",
"billing_address_collection": None,
"cancel_url": "https://test/payments/cancel/19",
"client_reference_id": None,
"customer": "cus_FgusdomerZ8gdP",
"customer_email": None,
"display_items": [
{
"amount": 300,
"currency": "eur",
"custom": {
"description": "One month for admin",
"images": None,
"name": "VPN Payment"
},
"quantity": 1,
"type": "custom"
}
],
"livemode": False,
"locale": None,
"mode": "payment",
"payment_intent": "pi_0FmmmmmmmmmmmmmmmpyplM53",
"payment_method_types": [
"card"
],
"setup_intent": None,
"submit_type": None,
"subscription": None,
"success_url": "https://test/payments/view/19"
}
},
"livemode": False,
"pending_webhooks": 1,
"request": {
"id": None,
"idempotency_key": None
},
"type": "checkout.session.completed"
}
5 years ago
def checkout_session_completed__sub(sub):
return {
"id": "evt_FjSIjKT3MvONr8",
"object": "event",
"api_version": "2019-08-14",
"created": 1567368634,
"data": {
"object": {
"id": "cs_test_03aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"object": "checkout.session",
"billing_address_collection": None,
"cancel_url": "https://test/payments/view/2",
"client_reference_id": "sub_%d" % sub.id,
"customer": "cus_FkSIg5BNIdrv6v",
"customer_email": None,
"display_items": [
{
"amount": 900,
"currency": "eur",
"plan": {
"id": "ccvpn_3m",
"object": "plan",
"active": True,
"aggregate_usage": None,
"amount": 900,
"amount_decimal": "900",
"billing_scheme": "per_unit",
"created": 1557830755,
"currency": "eur",
"interval": "month",
"interval_count": 3,
"livemode": False,
"metadata": {
},
"nickname": None,
"product": "prod_F062eB2kCukpUX",
"tiers": None,
"tiers_mode": None,
"transform_usage": None,
"trial_period_days": None,
"usage_type": "licensed"
},
"quantity": 1,
"type": "plan"
}
],
"livemode": False,
"locale": None,
"mode": "subscription",
"payment_intent": None,
"payment_method_types": [
"card"
],
"setup_intent": None,
"submit_type": None,
"subscription": "sub_Fjmeowmeowmeow",
"success_url": "https://test/payments/return/2"
}
},
"livemode": False,
"pending_webhooks": 1,
"request": {
"id": "req_xQY51312421312",
"idempotency_key": None
},
"type": "checkout.session.completed"
}
5 years ago
INVOICE_PAYMENT_SUCCEEDED = {
"id": "evt_FjSMpT5zIn8G9z",
"object": "event",
"api_version": "2019-08-14",
"created": 1567368905,
"data": {
"object": {
"id": "in_FjSMAw7ufaEBOG",
"object": "invoice",
"account_country": "FR",
"account_name": "Cognitive Cryptography",
"amount_due": 900,
"amount_paid": 900,
"amount_remaining": 0,
"application_fee_amount": None,
"attempt_count": 1,
"attempted": True,
"auto_advance": False,
"billing": "charge_automatically",
"billing_reason": "subscription_create",
"charge": "ch_FjSMFp6fbsc45t",
"collection_method": "charge_automatically",
"created": 1567368904,
"currency": "eur",
"custom_fields": None,
"customer": "cus_FjSMgbAnXmL4Go",
"customer_address": None,
"customer_email": "test2@test.test",
"customer_name": None,
"customer_phone": None,
"customer_shipping": None,
"customer_tax_exempt": "none",
"customer_tax_ids": [
],
"default_payment_method": None,
"default_source": None,
"default_tax_rates": [
],
"description": None,
"discount": None,
"due_date": None,
"ending_balance": 0,
"footer": None,
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_wmhbGo7OofOofOofOofOofOofd",
"invoice_pdf": "https://pay.stripe.com/invoice/invst_wmhbGo7OofOofOofOofOofOofd/pdf",
"lines": {
"object": "list",
"data": [
{
"id": "sli_c20baf5dcf8472",
"object": "line_item",
"amount": 900,
"currency": "eur",
"description": "1 × VPN Subscription (3m) (at €9.00 / every 3 months)",
"discountable": True,
"livemode": False,
"metadata": {
},
"period": {
"end": 1575231304,
"start": 1567368904
},
"plan": {
"id": "ccvpn_3m",
"object": "plan",
"active": True,
"aggregate_usage": None,
"amount": 900,
"amount_decimal": "900",
"billing_scheme": "per_unit",
"created": 1557830755,
"currency": "eur",
"interval": "month",
"interval_count": 3,
"livemode": False,
"metadata": {
},
"nickname": None,
"product": "prod_F46LeBpkCuRpUX",
"tiers": None,
"tiers_mode": None,
"transform_usage": None,
"trial_period_days": None,
"usage_type": "licensed"
},
"proration": False,
"quantity": 1,
"subscription": "sub_Fjmeowmeowmeow",
"subscription_item": "si_FjSMgsAsZURoWf",
"tax_amounts": [
],
"tax_rates": [
],
"type": "subscription"
}
],
"has_more": False,
"total_count": 1,
"url": "/v1/invoices/in_FjSMAw7ufaEBOG/lines"
},
"livemode": False,
"metadata": {
},
"next_payment_attempt": None,
"number": "AD4E509A-0001",
"paid": True,
"payment_intent": "pi_0FDzS0UmBGT3Of2k4ol85K2G",
"period_end": 1567368904,
"period_start": 1567368904,
"post_payment_credit_notes_amount": 0,
"pre_payment_credit_notes_amount": 0,
"receipt_number": None,
"starting_balance": 0,
"statement_descriptor": None,
"status": "paid",
"status_transitions": {
"finalized_at": 1567368904,
"marked_uncollectible_at": None,
"paid_at": 1567368905,
"voided_at": None
},
"subscription": "sub_Fjmeowmeowmeow",
"subtotal": 900,
"tax": None,
"tax_percent": None,
"total": 900,
"total_tax_amounts": [
],
"webhooks_delivered_at": None
}
},
"livemode": False,
"pending_webhooks": 1,
"request": {
"id": "req_6O128256512102",
"idempotency_key": None
},
"type": "invoice.payment_succeeded"
}