Package: aa-stripe
Stripe integration for Django-based projectsThis project’s target is to make the Stripe API easier to use in Django-based applications.
At the moment the library supports:charging usersplanssubscriptionswebhooksSupport for Python 2.7 has been dropped since aa-stripe 0.6.0.InstallationAddaa_stripeto your app’sINSTALLED_APPS, and also setSTRIPE_API_KEYin project settings. After all please migrate the app (./manage.py migrate aa_stripe).
AddSTRIPE_WEBHOOK_ENDPOINT_SECRETinto your settings from stripe webhooks configuration to enable webhooks.
AddSTRIPE_USER_MODELif it is different than settings.AUTH_USER_MODEL. In example when CC is connected to office not person.STRIPE_USER_MODELdefaults to AUTH_USER_MODEL.Addaa_stripe.api_urlsinto your url conf.UsageCreating a token for userUse stripe.js (https://stripe.com/docs/stripe.js) to get single use token (stripe.js->createToken) and send it to API using/aa-stripe/customersto create Customer for the user. It runs:customer = stripe.Customer.create(source=data["id"]) # data is the response dictionary from Stripe API (in front-end)
token = StripeToken.objects.create(user=request.user, content=data,
                                 customer_id=customer["id"])This endpoint requires authenticated user. In case you need diferent implementation (like one call with register) you’ll have to adjust your code.ChargingFirst of all, make sure to obtain Stripe user token from the Stripe API, and then save it toaa_stripe.models.StripeToken, for example:import stripe
from aa_stripe.models import StripeToken

customer = stripe.Customer.create(source=data["id"]) # data is the response dictionary from Stripe API (in front-end)
token = StripeToken.objects.create(user=request.user, content=data,
                                   customer_id=customer["id"])To charge users, create an instance ofaa_stripe.models.StripeChargemodel and then call thecharge()method:c = StripeCharge.objects.create(user=user, token=token, amount=500,  # in cents
                                description="Charge for stuff",  # sent to Stripe
                                comment="Comment for internal information",
                                statement_descriptor="My Company" # sent to Stripe
)
c.charge()Upon successfull charge also sends signal,stripe_charge_succeededwith instance as single parameter.If charge fails due to CardError,charge_attept_failedis set to True and this charge will not be automatically retried bycharge_stripecommand. Signalstripe_charge_card_exceptionwith instance and exception will be send.There is also a management command calledcharge_stripein case you need to process all the remaining charges or to run it by cron.Subscriptions supportWith Stripe user token already obtained you can create subscription.import stripe
from aa_stripe.models import StripeSubscription

subscription = StripeSubscription.objects.create(
  customer=self.customer,
  user=self.user,
  plan=self.plan,
  metadata={"name": "test subscription"},
)The newly created object is not sent to Stripe just yet.subscription_data = subscription.create_at_stripe()The command above returns whole subscription data send by stripe, including, in example, discounts.https://stripe.com/docs/api#subscriptionsUtility functions for subscriptionssubscription.refresh_from_stripe() - gets updated subscription data from Stripe. Example usage: parsing webhooks - when webhook altering subscription is received it is good practice to verify the subscription at Stripe before making any actions.subscription.cancel() - cancels subscription at Stripe.StripeSubscription.get_subcriptions_for_cancel() - returns all subscriptions that should be canceled. Stripe does not support end date for subscription so it is up the user to implement expiration mechanism. Subscription has end_date that can be used for that.StripeSubscription.end_subscriptions() - cancels all subscriptions on Stripe that has passed end date. Use with caution, check internal comments.management command: end_subscription.py. Terminates outdated subscriptions in a safe way. In case of error returns it at the end, using Sentry if available or in console. Should be used in cron script. By default sets at_period_end=True.Subscription PlansSubscription Plans can be created using Stripe UI however there are cases when those needs to be created using API.import stripe
from aa_stripe.models import StripeSubscriptionPlan

plan = StripeSubscriptionPlan.objects.create(
  source={"a": "b"},
  amount=5000,
  name="gold-basic",
  interval=StripeSubscriptionPlan.INTERVAL_MONTH,
  interval_count=3,
)As with Subscription, the object has to be sent to stripe.plan_data = plan.create_at_stripe()The command above returns whole plan data send by stripe.https://stripe.com/docs/api#plansCoupons SupportStripe coupons can be created both in the Stripe Dashboard and using theaa_stripe.models.StripeCouponmodel, and also if webhooks are properly configured in your app, you will be able to see all changes related to coupons made in the Stripe Dashboard.
This works both ways, if a coupon was created, edited or deleted on the application side, the list of coupons in Stripe will be updated respectively.from aa_stripe.models import StripeCoupon

coupon = StripeCoupon.objects.create(
    coupon_id="SALE10",
    duration=StripeCoupon.DURATION_FOREVER,
    currency="usd",
    amount_off=10,  # in dollars
)
# coupon was created at Stripe
coupon.delete()
# coupon was deleted from Stripe, but the StripeCoupon object is kept
print(coupon.is_deleted)  # TrueImportant:When updating coupon data, do not use theStripeCoupon.objects.update()method, because it does not call theStripeCoupon.save()method, and therefore the coupon will not be updated at Stripe.The refresh_coupons management commandTo make sure your app is always up to date with Stripe, therefresh_couponsmanagement command should be run chronically.
It allows to periodically verify if all coupons are correctly stored in your app and no new coupons were created or deleted at Stripe.For more information about coupons, see:https://stripe.com/docs/api#couponsWebhooks supportAll webhooks should be sent to/aa-stripe/webhooksurl. AddSTRIPE_WEBHOOK_ENDPOINT_SECRETto your settings to enable webhook verifications. Each received webhook is saved as StripeWebhook object in database. User need to add parsing webhooks depending on the project.
Be advised. There might be times that Webhooks will not arrive because of some error or arrive in incorrect order. When parsing webhook it is also good to download the refered object to verify it’s state.Stripe has the weird tendency to stop sending webhooks, and they have not fixed it yet on their side. To make sure all events have arrived into your system, thecheck_pending_webhooksmanagement command should be run chronically.
In case there is more pending webhooks than specified in theSTRIPE_PENDING_WEBHOOKS_THRESHOLDvariable in your settings (default:20), an email to project admins will be sent with ids of the pending events, and also the command will fail raising an exception,
so if you have some kind of error tracking service configured on your servers (for example:Sentry), you will be notified. Also ifENV_PREFIXis specified in your settings file, it will be included in the email to admins to indicate on which server the fail occurred.By default the site used in thecheck_pending_webhookscommand is the firstdjango.contrib.sites.models.Siteobject from the database, but in case you need to use some other site, please use the--siteparameter to pass your site’s id.Parsing webhooksTo parse webhooks, you can connect to theaa_stripe.models.webhook_pre_parsesignal, which is sent each time aStripeWebhookobject is parsed.Sample usage:from aa_stripe.models import StripeWebhook, webhook_pre_parse

def stripewebhook_pre_parse(sender, instance, event_type, event_model, event_action, **kwargs):
    if not instance.is_parsed:
        # parse

webhook_pre_parse.connect(stripewebhook_pre_parse, sender=StripeWebhook)Arguments:sender - theStripeWebhookclassinstance - theStripeWebhookevent objectevent_type - Stripe event type (for example:coupon.created,invoice.payment_failed,ping, etc., see:https://stripe.com/docs/api#event_types)event_model - the model which created the event (for example:coupon,invoice,charge.dispute, etc.)event_action - the action done on theevent_model(for example:created,updated,payment_failed, etc.)Bothevent_modelandevent_actionequal toNoneifevent_typeis apingevent.Updating customer card dataStripeCustomer.sources list is updated after receiving Webhook from Stripe about updating the customer object. It is a list ofStripe sourceobjects.Another way of updating the credit card information is to run therefresh_customersmanagement command in cron.SupportDjango 2.2-3.2Python 3.6-3.9