Stripe Subscription使用stripe.Subscription.create函数在Django中不提供client_secret。

huangapple go评论68阅读模式
英文:

Stripe Subscription using stripe.Subscription.create function does not provide client_secret with Django

问题

以下是您要翻译的代码部分:

As suggested [here][1], I am using stripe.Subscription.create function to create a subscription for the users in my Django DRM and expect to have a client secret that is associated with the subscription and the related payment_intent.

However following is the error that I get :

customer.clientsecret=stripe_subscription.latest_invoice.payment_intent.client_secret
AttributeError: 'NoneType' object has no attribute 'client_secret'

Below is the code that I am executing in the backend :

stripe_customer = stripe.Customer.create(email=instance.email)
customer.product = Product.objects.get(plan=0) # Free plan price id
customer.stripe_customer_id = stripe_customer['id']
stripe_subscription = stripe.Subscription.create(
                customer=customer.stripe_customer_id,
                items=[{"price": customer.product.stripe_plan_id},],
                payment_behavior='default_incomplete',
                payment_settings={'save_default_payment_method': 'on_subscription'},
                expand=['latest_invoice.payment_intent'],
)
customer.clientsecret=stripe_subscription.latest_invoice.payment_intent.client_secret

希望这有所帮助。如果您需要进一步的翻译或解释,请随时提出。

英文:

As suggested here , I am using stripe.Subscription.create function to create a subscription for the users in my Django DRM and expect to have a client secret that is associated with the subscription and the related payment_intent.

However following is the error that I get :

customer.clientsecret=stripe_subscription.latest_invoice.payment_intent.client_secret

AttributeError: 'NoneType' object has no attribute 'client_secret'

Below is the code that I am executing in the backend :

stripe_customer = stripe.Customer.create(email=instance.email)
customer.product = Product.objects.get(plan=0) # Free plan price id
customer.stripe_customer_id = stripe_customer['id']
stripe_subscription = stripe.Subscription.create(
                customer=customer.stripe_customer_id,
                items=[{"price": customer.product.stripe_plan_id},],
                payment_behavior='default_incomplete',
                payment_settings={'save_default_payment_method': 'on_subscription'},
                expand=['latest_invoice.payment_intent'],
)
customer.clientsecret=stripe_subscription.latest_invoice.payment_intent.client_secret

Here below is the definition for Customer model :

class Customer(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    stripe_customer_id = models.CharField(max_length=40, default="")
    product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
    
    stripe_subscription_id = models.CharField(max_length=40, default="")
    clientsecret = models.CharField(max_length=80, default="")
    active = models.BooleanField(default=True)

    @property
    def get_created_date(self):
        subscription = stripe.Subscription.retrieve(self.stripe_subscription_id)
        return datetime.fromtimestamp(subscription.created)

    @property
    def get_next_billing_date(self):
        subscription = stripe.Subscription.retrieve(self.stripe_subscription_id)
        return datetime.fromtimestamp(subscription.current_period_end)

    def __str__(self):
        return self.user.username

The customers are created and associated with users when a new user signs up :

def post_save_customer_create(sender, instance, created, *args, **kwargs):
    customer, created = Customer.objects.get_or_create(user=instance)
    ...

And here is the question : "How can I get a valid client_secret for the subscription that I create ?"

The value of the stripe_subscription is as below, and as you can see that latest_invoice is there, but payment_intent is null :

{
"application": null,
"application_fee_percent": null,
"automatic_tax": {
"enabled": false
},
"billing_cycle_anchor": 1677632660,
"billing_thresholds": null,
"cancel_at": null,
"cancel_at_period_end": false,
"canceled_at": null,
"collection_method": "charge_automatically",
"created": 1677632660,
"currency": "usd",
"current_period_end": 1680311060,
"current_period_start": 1677632660,
"customer": "cus_NRX9a1XQtjWJPd",
"days_until_due": null,
"default_payment_method": null,
"default_source": null,
"default_tax_rates": [],
"description": null,
"discount": null,
"ended_at": null,
"id": "sub_1Mge5gLS6SANVcyCOTRj2dLw",
"items": {
"data": [
{
"billing_thresholds": null,
"created": 1677632660,
"id": "si_NRXAdvOPbsuzfz",
"metadata": {},
"object": "subscription_item",
"plan": {
"active": true,
"aggregate_usage": null,
"amount": 0,
"amount_decimal": "0",
"billing_scheme": "per_unit",
"created": 1673957019,
"currency": "usd",
"id": "price_1MRDt9LS6SANVcyCvUMav5Fr",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"nickname": "Free",
"object": "plan",
"product": "prod_NBb5jZ3Sg3Knrl",
"tiers": null,
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"price": {
"active": true,
"billing_scheme": "per_unit",
"created": 1673957019,
"currency": "usd",
"custom_unit_amount": null,
"id": "price_1MRDt9LS6SANVcyCvUMav5Fr",
"livemode": false,
"lookup_key": null,
"metadata": {},
"nickname": "Free",
"object": "price",
"product": "prod_NBb5jZ3Sg3Knrl",
"recurring": {
"aggregate_usage": null,
"interval": "month",
"interval_count": 1,
"trial_period_days": null,
"usage_type": "licensed"
},
"tax_behavior": "unspecified",
"tiers_mode": null,
"transform_quantity": null,
"type": "recurring",
"unit_amount": 0,
"unit_amount_decimal": "0"
},
"quantity": 1,
"subscription": "sub_1Mge5gLS6SANVcyCOTRj2dLw",
"tax_rates": []
}
],
"has_more": false,
"object": "list",
"total_count": 1,
"url": "/v1/subscription_items?subscription=sub_1Mge5gLS6SANVcyCOTRj2dLw"
},
"latest_invoice": {
"account_country": "GB",
"account_name": "Su Technology Ltd",
"account_tax_ids": null,
"amount_due": 0,
"amount_paid": 0,
"amount_remaining": 0,
"amount_shipping": 0,
"application": null,
"application_fee_amount": null,
"attempt_count": 0,
"attempted": true,
"auto_advance": false,
"automatic_tax": {
"enabled": false,
"status": null
},
"billing_reason": "subscription_create",
"charge": null,
"collection_method": "charge_automatically",
"created": 1677632660,
"currency": "usd",
"custom_fields": null,
"customer": "cus_NRX9a1XQtjWJPd",
"customer_address": null,
"customer_email": "bulkanutku@gmail.com",
"customer_name": null,
"customer_phone": null,
"customer_shipping": null,
"customer_tax_exempt": "none",
"customer_tax_ids": [],
"default_payment_method": null,
"default_source": null,
"default_tax_rates": [],
"description": null,
"discount": null,
"discounts": [],
"due_date": null,
"ending_balance": 0,
"footer": null,
"from_invoice": null,
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_1GJetwLS6SANVcyC/test_YWNjdF8xR0pldHdMUzZTQU5WY3lDLF9OUlhBQjBaaVZMQk5FSFFFcTBydVB5bzNpVnlORWk1LDY4MTczNDYw0200gE9zTwdN?s=ap",
"id": "in_1Mge5gLS6SANVcyCtGvBkugu",
"invoice_pdf": "https://pay.stripe.com/invoice/acct_1GJetwLS6SANVcyC/test_YWNjdF8xR0pldHdMUzZTQU5WY3lDLF9OUlhBQjBaaVZMQk5FSFFFcTBydVB5bzNpVnlORWk1LDY4MTczNDYw0200gE9zTwdN/pdf?s=ap",
"last_finalization_error": null,
"latest_revision": null,
"lines": {
"data": [
{
"amount": 0,
"amount_excluding_tax": 0,
"currency": "usd",
"description": "1 \u00d7 videoo.io (at $0.00 / month)",
"discount_amounts": [],
"discountable": true,
"discounts": [],
"id": "il_1Mge5gLS6SANVcyCTgQ4Jyt4",
"livemode": false,
"metadata": {},
"object": "line_item",
"period": {
"end": 1680311060,
"start": 1677632660
},
"plan": {
"active": true,
"aggregate_usage": null,
"amount": 0,
"amount_decimal": "0",
"billing_scheme": "per_unit",
"created": 1673957019,
"currency": "usd",
"id": "price_1MRDt9LS6SANVcyCvUMav5Fr",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"nickname": "Free",
"object": "plan",
"product": "prod_NBb5jZ3Sg3Knrl",
"tiers": null,
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"price": {
"active": true,
"billing_scheme": "per_unit",
"created": 1673957019,
"currency": "usd",
"custom_unit_amount": null,
"id": "price_1MRDt9LS6SANVcyCvUMav5Fr",
"livemode": false,
"lookup_key": null,
"metadata": {},
"nickname": "Free",
"object": "price",
"product": "prod_NBb5jZ3Sg3Knrl",
"recurring": {
"aggregate_usage": null,
"interval": "month",
"interval_count": 1,
"trial_period_days": null,
"usage_type": "licensed"
},
"tax_behavior": "unspecified",
"tiers_mode": null,
"transform_quantity": null,
"type": "recurring",
"unit_amount": 0,
"unit_amount_decimal": "0"
},
"proration": false,
"proration_details": {
"credited_items": null
},
"quantity": 1,
"subscription": "sub_1Mge5gLS6SANVcyCOTRj2dLw",
"subscription_item": "si_NRXAdvOPbsuzfz",
"tax_amounts": [],
"tax_rates": [],
"type": "subscription",
"unit_amount_excluding_tax": "0"
}
],
"has_more": false,
"object": "list",
"total_count": 1,
"url": "/v1/invoices/in_1Mge5gLS6SANVcyCtGvBkugu/lines"
},
"livemode": false,
"metadata": {},
"next_payment_attempt": null,
"number": "E86AFCCB-0313",
"object": "invoice",
"on_behalf_of": null,
"paid": true,
"paid_out_of_band": false,
"payment_intent": null,
"payment_settings": {
"default_mandate": null,
"payment_method_options": null,
"payment_method_types": null
},
"period_end": 1677632660,
"period_start": 1677632660,
"post_payment_credit_notes_amount": 0,
"pre_payment_credit_notes_amount": 0,
"quote": null,
"receipt_number": null,
"rendering_options": null,
"shipping_cost": null,
"shipping_details": null,
"starting_balance": 0,
"statement_descriptor": null,
"status": "paid",
"status_transitions": {
"finalized_at": 1677632660,
"marked_uncollectible_at": null,
"paid_at": 1677632660,
"voided_at": null
},
"subscription": "sub_1Mge5gLS6SANVcyCOTRj2dLw",
"subtotal": 0,
"subtotal_excluding_tax": 0,
"tax": null,
"tax_percent": null,
"test_clock": null,
"total": 0,
"total_discount_amounts": [],
"total_excluding_tax": 0,
"total_tax_amounts": [],
"transfer_data": null,
"webhooks_delivered_at": 1677632660
},
"livemode": false,
"metadata": {},
"next_pending_invoice_item_invoice": null,
"object": "subscription",
"on_behalf_of": null,
"pause_collection": null,
"payment_settings": {
"payment_method_options": null,
"payment_method_types": null,
"save_default_payment_method": "on_subscription"
},
"pending_invoice_item_interval": null,
"pending_setup_intent": "seti_1Mge5gLS6SANVcyCiD2a3pQM",
"pending_update": null,
"plan": {
"active": true,
"aggregate_usage": null,
"amount": 0,
"amount_decimal": "0",
"billing_scheme": "per_unit",
"created": 1673957019,
"currency": "usd",
"id": "price_1MRDt9LS6SANVcyCvUMav5Fr",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"nickname": "Free",
"object": "plan",
"product": "prod_NBb5jZ3Sg3Knrl",
"tiers": null,
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"quantity": 1,
"schedule": null,
"start_date": 1677632660,
"status": "active",
"tax_percent": null,
"test_clock": null,
"transfer_data": null,
"trial_end": null,
"trial_settings": {
"end_behavior": {
"missing_payment_method": "create_invoice"
}
},
"trial_start": null
}

答案1

得分: 1

因为发票金额为$0,所以没有需要支付的内容,因此没有PaymentIntent。

根据您尝试完成的任务,您可以改为使用“pending_setup_intent”和该对象上的“client_secret”,然后在前端使用“stripe.confirmCardSetup(…)”来收集付款详细信息,而无需收费。

https://stripe.com/docs/billing/subscriptions/overview#using-setupintents

英文:

> and as you can see that latest_invoice is there, but payment_intent is null

Because the Invoice is for $0 so there is nothing to pay, so no PaymentIntent.

Depending on what you're trying to do, you can use the pending_setup_intent instead and the client_secret of that object on the frontend with stripe.confirmCardSetup(...) to collect payment details without charging them.

https://stripe.com/docs/billing/subscriptions/overview#using-setupintents

huangapple
  • 本文由 发表于 2023年3月1日 08:49:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75598670.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定