Reputation: 545
Currently have this code for one of the subscriptions that I have available on my site. The code checks to see if the user has a plan already, if they don't, the else statement is run (works fine) and if they do, the code for updating their current subscription is replaced with the new subscription.(not working)
@login_required
def charge(request):
user_info = request.user.profile
email = user_info.inbox
if request.method == 'POST':
#returns card token in terminal
print('Data:', request.POST)
user_plan = request.user.profile.current_plan
if user_plan != 'None':
'''if they have a plan already, override that plan
with this new plan this is using an already created
user'''
#this throws an error right now
new_plan = stripe.Subscription.modify(
#the current plan(wanting to change)
user_info.subscription_id,
cancel_at_period_end=True,
proration_behavior='create_prorations',
#the new subscription
items=[{'plan':'price_HHU1Y81pU1wrNp',}]
)
user_info.subscription_id = new_plan.id
#if they don't have a subscription already
else:
amount = 10
customer = stripe.Customer.create(
email=email,
source=request.POST['stripeToken'],
description=user_info.genre_one,
)
charge = stripe.Subscription.create(
customer=customer.id,#email of logged in person
items = [{"plan": "price_HHU1Y81pU1wrNp"}],#change plan id depending on plan chosen
)
#updates users current plan with its id and other info
user_info.subscription_id = charge.id
user_info.customer_id = customer.id
user_info.current_plan = 'B'
user_info.save()
return redirect(reverse('success', args=[amount]))
When I try and update the users subscription to the new one I get this runtime error:
Request req_kK2v51jnhuuKsW: Cannot add multiple subscription items with the same plan: price_HHU1Y81pU1wrNp
The Account that I am testing with has a plan that is different than the one that im trying to update to. (this code is for basic plan, the account has the standard plan enabled).
All help is greatly appreciated!
Edit: This is the model data, I tried changing all the 'None' values to something else to see if it would change the error but it didn't.
SUB_PLANS = [
('None','None'),
('B','Basic Plan'),
('S', 'Standard Plan'),
('P', 'Premium Plan'),
]
GENRE_CHOICES = [
('1','None'),
('2','Adventure'),
('3','Action'),
('4','Puzzle'),
('5','Story Based'),
]
# Create your models here.
class Profile(models.Model):
User = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
username = models.CharField(max_length=30)
#where games are sent
inbox = models.EmailField(max_length = 50)
current_plan = models.CharField(max_length = 4, choices = SUB_PLANS, default='None')
#genres they like
genre_one = models.CharField(max_length = 20, choices = GENRE_CHOICES, default = 'None')
genre_two = models.CharField(max_length = 20, choices = GENRE_CHOICES, default = 'None')
genre_three = models.CharField(max_length = 20, choices = GENRE_CHOICES, default = 'None')
subscription_id = models.CharField(max_length = 40, default="None")
customer_id = models.CharField(max_length = 40, default = "None")
'''on account creation plan == null, then once they buy one,
plan is added as a dropdown that they can edit easy'''
def __str__(self):
return self.username
Upvotes: 6
Views: 3938
Reputation: 3105
The trick here is that if you're updating an existing Subscription that already has a single item, then you'll need to pass the ID for that SubscriptionItem when updating so that the API knows you're not attempting to add a second SubscriptionItem with the same plan.
Based on that error message, it seems the Plan was already updated on that Subscription, but likely not in the way you're expecting. If the Subscription started out on the "standard" plan, then your code above was executed, it likely added the "basic" plan in addition to the existing standard. I bet they are subscribed to both basic
and standard
now. In order to update as you expect, you'll want to delete the standard SubscriptionItem and add the basic SubscriptionItem which I'll show code for below. Alternatively, you can update the SubscriptionItem directly to swap the plan.
Note that if you have multiple plans per Subscription, this example will need to be modified to find the correct SubscriptionItem ID. Here's one way to do this:
current_subscription = stripe.Subscription.retrieve(user_info.subscription_id)
new_plan = stripe.Subscription.modify(
user_info.subscription_id,
cancel_at_period_end=True,
proration_behavior='create_prorations',
#the new subscription
items=[{
'id': current_subscription['items'].data[0].id, # note if you have more than one Plan per Subscription, you'll need to improve this. This assumes one plan per sub.
'deleted': True,
}, {
'plan': 'price_HHU1Y81pU1wrNp'
}]
)
Upvotes: 15