4

I finally figured out how to implement Stripes Monthly Billing using this tutorial.

So far, A User can Create & Delete their Subscription with Stripe. But I am having trouble calling the hashes inside the API to have the User change his credit card information.

Question: How do I call/pass the child parameters in the documentation to update the Credit Card Fields using the method I have created update_card?

This is my Code with Comments:

CONTROLLER

class SubscriptionsController < ApplicationController

  def update
    @subscription = current_user.subscription

    ### I use the method update_card to update the customer's card
    @subscription.update_card  

     if @subscription.update_card
      redirect_to edit_subscription_path, :success => 'Updated Card.' 
    else
      flash.alert = 'Unable to update card.'
      render :edit 
    end
  end

end

MODELS

class Subscription < ActiveRecord::Base
  attr_accessible :plan_id, :user_id, :email, :stripe_customer_token, :last_4_digits,
              :card_token, :card_name, :exp_month, :exp_year, :stripe_card_token

  attr_accessor :stripe_card_token

  belongs_to :plan
  belongs_to :user

  ### How can this work with my edit form. Would I need to store each person's new card?
  def token
    token = Stripe::Token.create(
       :card => {
       :number => "4242424242424242",
       :exp_month => 1,
       :exp_year => 2015,
       :cvc => "314"
      },
    )
  end

  def update_card
    customer = Stripe::Customer.retrieve(stripe_customer_token)
    customer.email = "myteam@gmail.com"
    customer.description = "Unlimited"
    customer.card = token.id
    customer.save
  rescue Stripe::StripeError => e 
    logger.error "Stripe Error: " + e.message 
    errors.add :base, "#{e.message}." 
    false
  end

Here is Stripe's Documentation Example Response

#<Stripe::Customer id=cus_3OWtLd5pirU4te 0x00000a> JSON: {
  "object": "customer",
  "created": 1390946171,
  "id": "cus_3OWtLd5pirU4te",
  "livemode": false,
  "description": "Customer for test@example.com",
  "email": null,
  "delinquent": false,
  "metadata": {
  },
  "subscription": null,
  "discount": null,
  "account_balance": 0,
  "currency": "usd",

  ###I need to be able to update the data inside the customers card
  "cards": {
    "object": "list",
    "count": 1,
    "url": "/v1/customers/cus_3OWtLd5pirU4te/cards",
    "data": [
      {
        "id": "card_103OWt2eZvKYlo2CgyXLaqcd",
        "object": "card",
        "last4": "4242",
        "type": "Visa",
        "exp_month": 9,
        "exp_year": 2015,
        "fingerprint": "Xt5EWLLDS7FJjR1c",
        "customer": "cus_3OWtLd5pirU4te",
        "country": "US",
        "name": "Brendan Lynch",
        "address_line1": null,
        "address_line2": null,
        "address_city": null,
        "address_state": null,
        "address_zip": null,
        "address_country": null,
        "cvc_check": "pass",
        "address_line1_check": null,
        "address_zip_check": null
      }
    ]
  },
  "default_card": "card_103OWt2eZvKYlo2CgyXLaqcd"
}

Reference: Stripe Documentation for Ruby

js.coffee

jQuery ->
  Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
  subscription.setupForm()

subscription =
  setupForm: ->
    $('#new_subscription').submit ->
      $('input[type=submit]').attr('disabled', true)
      if $('#card_number').length
        subscription.processCard()
        false
      else
        true

  processCard: ->
    card =
      {number: $('#card_number').val(),
      cvc: $('#card_code').val(),
      expMonth: $('#card_month').val(),
      expYear: $('#card_year').val()}

    Stripe.createToken(card, subscription.handleStripeResponse)

  handleStripeResponse: (status, response) ->
    if status == 200
      $('#subscription_stripe_card_token').val(response.id)
      $('#new_subscription')[0].submit()
    else
      $('#stripe_error').text(response.error.message)
      $('input[type=submit]').attr('disabled', false)

LOGS

Started PUT "/subscriptions/5" for 127.0.0.1 at 2014-01-30 01:53:35 -0800
Processing by SubscriptionsController#update as HTML

  Parameters: {"utf8"=>"✓", "authenticity_token"=>"ehyUD17CbH7MMOe98s+Kqkh+wGghntWkG4OpoqbnQaA=", 
"subscription"=>{"plan_id"=>"1", "user_id"=>"1", "stripe_card_token"=>""}, 
"commit"=>"Update My Credit Card", "id"=>"5"}

User Load (1.0ms)  SELECT "users".* FROM "users" 
WHERE "users"."remember_token" = 'xEeu1X6IK9gUAsna9b6Mow' 
LIMIT 1
Subscription Load (0.5ms)  SELECT "subscriptions".* 
FROM "subscriptions" WHERE "subscriptions"."user_id" = 1 LIMIT 1

Stripe Error: You passed an empty string for 'card'. We assume empty values
are an attempt to unset a parameter; however 'card' cannot be unset. You 
should remove 'card' from your request or supply a non-empty value
Serge Pedroza
  • 2,160
  • 3
  • 28
  • 41

1 Answers1

7

either you can create a new card and delete the old one that will make the new card default_card for that customer or you can also achieve it by updating the customer and passing card details as mentioned here(check card field and its child parameters) https://stripe.com/docs/api#update_customer

Edit:

Do it like this

require "stripe"
Stripe.api_key = "sk_test_BQokikJOvBiI2HlWgH4olfQ2"

token = Stripe::Token.create(
   :card => {
   :number => "4242424242424242",
   :exp_month => 1,
   :exp_year => 2015,
   :cvc => "314"
   },
)
cu = Stripe::Customer.retrieve("cus_3Ok02kebTNsPDJ")
cu.card = token.id
cu.save
abhas
  • 5,193
  • 1
  • 32
  • 56
  • I don't know if that works. the update_card method only seems to update the year, month, name, address, but not the actual credit card number. – Serge Pedroza Jan 29 '14 at 04:50
  • i understand that i could do it by updating the customer. What I am having trouble with is calling/passing the child parameters. Can you provide an example on how to do that? Ive tried doing customer.cards.data =....But i don't think i am doing it correctly because it doesn't work. – Serge Pedroza Jan 29 '14 at 11:30
  • 1
    edited the answer...either you can create the token as mentioned above or in UI if you have included Stripe.js it gives you token id on change of card that you can directly assign to `cu.card` – abhas Jan 29 '14 at 12:02
  • Okay, I have fixed the code above and now the credit card is being updated because I have created a token, but how would this work from my edit_form. So that the token information is gathered from the Edit Form since ill have multiple users.....? Sorry I am new at working with APIs – Serge Pedroza Jan 30 '14 at 01:52
  • 1
    when your edit form is submitted or completed, through jquery create the token and then send it to server with other attributes – abhas Jan 30 '14 at 05:00
  • I think I am getting it finally. I have started a new question since the question has changed since you've helped me. Would you mind taking a look :) http://stackoverflow.com/questions/21450993/update-stripe-credit-card-with-coffeescript – Serge Pedroza Jan 30 '14 at 08:42
  • check your rails log if `stripe_card_token` is getting passed to action or not – abhas Jan 30 '14 at 09:09
  • I have posted the rails logs above. i still don't understand why the string is blank. :/ – Serge Pedroza Jan 30 '14 at 09:58
  • try changing this `$('#subscription_stripe_card_token').val(response.id)` with `$('#subscription_stripe_card_token').val(response['id'])` and `status === 200` – abhas Jan 30 '14 at 10:03
  • i get the same error for some reason. Would showing the html help? – Serge Pedroza Jan 30 '14 at 10:36