Fastest django app you'll ever user that provides paypal, stripe and cryptocurrency ( bitcoin) payment for your django drf saas app subscription and billings. supports normal, Flat rate: Good-better-best, usage billing based on https://github.com/ydaniels/drf-django-flexible-subscriptions
- Python (2.7, 3.3, 3.4+)
- Django (1.6, 1.7, 1.8+)
- Django REST Framework (2.4, 3.0, 3.1+)
Install using pip
…
$ pip install django-saas-billing
# settings.py
INSTALLED_APPS = [
...,
'rest_framework',
'subscriptions_api',
'cryptocurrency_payment', #for crypto payments
'saas_billing'
]
SUBSCRIPTIONS_API_SUBSCRIPTIONTRANSACTION_MODEL = 'saas_billing.SubscriptionTransaction'
SAAS_BILLING_MODELS = {
'stripe': {
'plan': 'saas_billing.StripeSubscriptionPlan',
'cost': 'saas_billing.StripeSubscriptionPlanCost',
'subscription': 'saas_billing.StripeSubscription'
},
'paypal': {
'plan': 'saas_billing.PaypalSubscriptionPlan',
'cost': 'saas_billing.PaypalSubscriptionPlanCost',
'subscription': 'saas_billing.PaypalSubscription'
}
}
SAAS_BILLING_AUTH = {
'stripe': {
'PUBLISHABLE_KEY': 'Your Publishable Key',
'LIVE_KEY': 'You Live key can be test or live',
'CANCEL_URL': 'Where you want to redirect to if user cancels payment',
'SUCCESS_URL': ' Where to redirect to if subscription is successful'
},
'paypal': {
'CLIENT_ID': 'Your paypal rest client id',
'CLIENT_SECRET': 'Your paypal rest secret id',
'TOKEN': None,
'ENV': 'live|development',
'CANCEL_URL': 'Where to redirect to if subscription fails',
'SUCCESS_URL': 'Where to redirect to if subscription is successful',
'WEB_HOOK_ID': 'Your paypal rest webhook id'
}
}
CRYPTOCURRENCY_PAYMENT = {
"BITCOIN": {
"CODE": "btc",
"BACKEND": "merchant_wallet.backends.btc.BitcoinBackend",
"FEE": 0.00,
"REFRESH_PRICE_AFTER_MINUTE": 15,
"REUSE_ADDRESS": False,
"ACTIVE": True,
"MASTER_PUBLIC_KEY": 'PUT_YOUR_WALLET_MASTER_PUBLIC_KEY',
"CANCEL_UNPAID_PAYMENT_HRS": 24,
"CREATE_NEW_UNDERPAID_PAYMENT": True,
"IGNORE_UNDERPAYMENT_AMOUNT": 10,
"IGNORE_CONFIRMED_BALANCE_WITHOUT_SAVED_HASH_MINS": 20,
"BALANCE_CONFIRMATION_NUM": 1,
"ALLOW_ANONYMOUS_PAYMENT": False,
"DERIVATION_PATH": "m/0",
"ADDRESS_TYPE": "p2wpkh"
}
}
DFS_DEFAULT_PLAN_COST_ID = 'Optional Put plan cost id here for new user to be automatically subscribed to this plan or subscription to be downgraded here'
path('', include('saas_billing.webhook_urls')) #Compulsory for webhook register url webhook on paypal and stripe
#create webhook url https://yourdomain.com/billing/stripe/webhook/
#https://yourdomain.com/billing/paypal/webhook/
path('api/subscriptions/', include('subscriptions_api.urls')),
path('api/', include('saas_billing.urls')),
- Regsiter webhook urls on paypal and stripe
https://yourdomain/billing/stripe/webhook/ #Please use ngrok on localhost
https://yourdomain/billing/paypal/webhook/
- Register signal in apps.py for crypto payments to activate subscription when crypto payment gets paid
#apps.py
class MyAppConfig(AppConfig):
def ready(self):
import saas_billing.signals
python manage.py migrate
- Create Your Plans and PlanCost from django admin
from subscription_api.models import SubscriptionPlan, PlanCost, MONTH
free_plan = SubscriptionPlan(plan_name='Free Plan', features='{"can_perform_action": false, "token_limit": 3}', group=optional_already_created_group_obj_user_will_be_added_to)
free_plan.save()
pro_plan = SubscriptionPlan(plan_name='Pro Plan', features='{"can_perform_action": true, "token_limit": 10}', group=already_created_group_obj).save()
pro_plan.save()
PlanCost(plan=pro_plan, recurrence_unit=MONTH, cost=30, min_subscription_quantity=20).save() #30$/month #min_subscription_quantity user must subscribe upto quantity to use this cost
#In your code or views you can use
if not user.subscription.plan.can_perform_action:
print('I am a free user')
else:
print('I am a pro user')
# features is a json dict that can be accessed from plan and group is normal django group that user will belong to
# You should be able to implement most subscriptions access and permissions with the feautures and django groups
- Generate Paypal and Stripe Plans and Pricing by using command below
python manage.py billing gateway all # Create all plans on stripe.com and paypal.com
python manage.py billing gateway <paypal|stripe> # Create only on paypal.com or Stripe.com
python manage.py billing gateway <paypal|stripe> --action <activate|deactivate> # Activate or Deactivate plans
subscription = request.user.subscriptions.filter(active=True).first() #if you only allow a subscription per user
subscription.transactions.all() #returns all transaction payment of this subscriptions
request.user.subscriptions.filter(active=True).all() #for all subscriptions if you allow multiple subscription per user
transactions = request.user.subscription_transactions.all() #Returns all payment trasnsaction for this user
from saas_billing.models import SubscriptionTransaction #import this to show crypto payments
from subscriptions_api.base_models import BaseSubscriptionTransaction # use this to only show paypal & stripe payment
class BillingView(ListView):
model = BaseSubscriptionTransaction
context_object_name = 'payment_transactions'
template_name = 'transactions.html'
def get_queryset(self):
return self.request.user.subscription_transactions.order_by('-date_transaction')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['active_subscription'] = self.request.user.subscriptions.filter(active=True).first()
return context
<!-- transactions.html -->
<table class="table table-bordernone display" id="basic-1">
<thead>
<tr>
<th scope="col">Date</th>
<th scope="col">Subscription</th>
<th scope="col">Amount</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
{% for tran in payment_transactions %}
<tr>
<td>{{ tran.payment_transactions }}</td>
<td>
<div class="product-name">{{ tran.subscription_name }}
</div>
</td>
<td>${{ tran.amount }}</td>
<td>Paid</td>
</tr>
{% endfor %}
</tbody>
</table>
-Send a post request using ajax or axios with data { gateway: <stripe|paypal|bitcoin>, quantity: 1 } to url below where ${id} is the plan cost id under subscriptions plans and quantity is optional for usage pricing
- For paypal redirect user to payment_link value from returned data
$.ajax({url: '/api/plan-costs/${id-of-cost}/init_gateway_subscription/', { gateway: 'paypal', quantity: 1 }}).then((post_return_data) => {
window.open(post_return_data.payment_link, '_blank').focus();
})
- For stripe start session with session id returned from post requsest using stripe javascript sdk
(post_return_data) => {
var stripe = window.Stripe(YOUR_STRIPE_PUBLIC_KEY)
return stripe.redirectToCheckout({ sessionId: post_return_data.session_id })
}
Thats all you need to start accepting subscriptions, subscriptions are activated or deactivated automatically and notification are sent to users automatically
'/api/subscriptions/subscription-plans/' #Get all plans to display in frontend
'/api/subscriptions/get_active_subscription/' # Returns active UserSubscription Object for the current logged in user
'/api/subscriptions/${id}/unsubscribe_user/' # Unsubscribe user from subscription with ${id}
'/api/transactions/' # Get payment transactions
'/api/transactions/${id}/' # Get single payment transaction with ${id}
Install testing requirements.
$ pip install -r requirements.txt
Run with runtests.
$ ./runtests.py
You can also use the excellent tox testing tool to run the tests against all supported versions of Python and Django. Install tox globally, and then simply run:
$ tox
To build the documentation, you’ll need to install mkdocs
.
$ pip install mkdocs
To preview the documentation:
$ mkdocs serve
Running at: http://127.0.0.1:8000/
To build the documentation:
$ mkdocs build