Marko
Marko

Reputation: 545

Issues with changin/updating stripe subscription (django)

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

Answers (1)

cjav_dev
cjav_dev

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

Related Questions