JosephK
JosephK

Reputation: 678

How to parse Stripe JSON response after Customer.create?

I've read other threads which use this version of the Stripe API, and the question of actually parsing the nested JSON was never answered (ex: How to parse Stripe JSON response after credit card creation?); or marked as duplicate (ex: How to read the stripe webhook response), though the 'orig of the duplicate' is very different, and doesn't give me a clue.

So here is what I've got. This part works

customer = Stripe::Customer.create(
    :card  => params[:stripeToken],
    :plan => params[:stripe_plan_id],
    :email => current_user.email
  )

... and gets me a JSON response which looks like this:

"id": "cus_4ab7wXjPrnoBvm",
"object": "customer",
"created": 1408029243,
"livemode": false,
"description": null,
"email": "[email protected]",
"delinquent": false,
"metadata": {},
"subscriptions": {"object":"list","total_count":1,"has_more":false,"url":"/v1/customers/cus_4ab7wXjPrnoBvm/subscriptions","data":[{"id":"sub_4ab7tOTkirRQ8r","plan":{"id":"gold","interval":"month","name":"Gold Plan","created":1408013865,"amount":399,"currency":"usd","object":"plan","livemode":false,"interval_count":1,"trial_period_days":null,"metadata":{},"statement_description":null},"object":"subscription","start":1408029243,"status":"active","customer":"cus_4ab7wXjPrnoBvm","cancel_at_period_end":false,"current_period_start":1408029243,"current_period_end":1410707643,"ended_at":null,"trial_start":null,"trial_end":null,"canceled_at":null,"quantity":1,"application_fee_percent":null,"discount":null,"metadata":{}}]},
"discount": null,
"account_balance": 0,
"currency": "usd",
"cards": {"object":"list","total_count":1,"has_more":false,"url":"/v1/customers/cus_4ab7wXjPrnoBvm/cards","data":[{"id":"card_14RPvP4WgFgXeu1koPs2f9Zd","object":"card","last4":"5904","brand":"Diners Club","funding":"credit","exp_month":2,"exp_year":2015,"fingerprint":"XTb65AiBJVROg4FA","country":null,"name":"[email protected]","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,"customer":"cus_4ab7wXjPrnoBvm"}]},
"default_card": "card_14RPvP4WgFgXeu1koPs2f9Zd"
}

So I parse this to a hash with:

stripe_customer_params = JSON.parse customer.to_s

Which gets this:

{"id"=>"cus_4abKeDBM5EGfy6", "object"=>"customer", "created"=>1408030013, "livemode"=>false, "description"=>nil, "email"=>"[email protected]", "delinquent"=>false, "metadata"=>{}, "subscriptions"=>{
    "object"=>"list", "total_count"=>1, "has_more"=>false, "url"=>"/v1/customers/cus_4abKeDBM5EGfy6/subscriptions", "data"=>[{
        "id"=>"sub_4abKNsI4WqeZYS", "plan"=>{
            "id"=>"gold", "interval"=>"month", "name"=>"Gold Plan", "created"=>1408013865, "amount"=>399, "currency"=>"usd", "object"=>"plan", "livemode"=>false, "interval_count"=>1, "trial_period_days"=>nil, "metadata"=>{}, "statement_description"=>nil
            }, 
            "object"=>"subscription", "start"=>1408030013, "status"=>"active", "customer"=>"cus_4abKeDBM5EGfy6", "cancel_at_period_end"=>false, "current_period_start"=>1408030013, "current_period_end"=>1410708413, "ended_at"=>nil, "trial_start"=>nil, "trial_end"=>nil, "canceled_at"=>nil, "quantity"=>1, "application_fee_percent"=>nil, "discount"=>nil, "metadata"=>{}
        }
    ]}, 
"discount"=>nil, "account_balance"=>0, "currency"=>"usd", "cards"=>{
    "object"=>"list", "total_count"=>1, "has_more"=>false, "url"=>"/v1/customers/cus_4abKeDBM5EGfy6/cards", "data"=>[{
        "id"=>"card_14RQ7p4WgFgXeu1kOETsWaqN", "object"=>"card", "last4"=>"5556", "brand"=>"Visa", "funding"=>"debit", "exp_month"=>4, "exp_year"=>2015, "fingerprint"=>"PDbelzu2DLr2A1C3", "country"=>"US", "name"=>"[email protected]", "address_line1"=>nil, "address_line2"=>nil, "address_city"=>nil, "address_state"=>nil, "address_zip"=>nil, "address_country"=>nil, "cvc_check"=>"pass", "address_line1_check"=>nil, "address_zip_check"=>nil, "customer"=>"cus_4abKeDBM5EGfy6"
        }]
    }, 
"default_card"=>"card_14RQ7p4WgFgXeu1kOETsWaqN"}

But these are nil when inspected:

stripe_customer_params[:id]
stripe_customer_params[:cards]

The first should get me the id from the JSON, and the latter should have a subset of the full-hash. Where am I going wrong?

------EDIT Ok, I was so close. It is that when parsing json to hash, you have to use quotes like this:

stripe_customer_params['id']
stripe_customer_params['cards']

So now I get "no implicit conversion of String into Integer" on this:

stripe_customer_params['cards']['data']['last4']

The DB field is a string, and the hash value is quoted as a string, so, some bit with the nested array of hashes to figure out still.

--------Edit 2

OK, the answer is:

stripe_customer_params['cards']['data'].first['last4']

... because 'data' is an array of hashes (though only 1 hash is in it).

-------Edit 3 For clarification as to why I get JSON back, rather than an object; I am using the javascript-generated pop-up form. The form is generated inline with:

  <script
    src="https://checkout.stripe.com/checkout.js" class="stripe-button" 
    data-key="pk_test_foo"
    data-label="Submit" 
    data-email="<%=current_user.email%>" 
    data-image="/square-image.png" 
    data-name="mysite.com" 
    data-description="Payment Plan 1" 
    data-amount="1000">
  </script>

This creates a button, with text "Submit" (data-label, above). When clicked, the pop-up form appears.

I have the Ruby-JSON-parsing syntax figured out, so it is working now. But if there is some other 'data-foo' I can add to get an object back, instead of JSON, that would be good to know for simplicity's sake.

Upvotes: 4

Views: 6165

Answers (3)

BoomShadow
BoomShadow

Reputation: 962

I had the exact same problem. I was using the Stripe Checkout and having trouble parsing their response. Here is the solution I used to save specific credit card information:

# Create a Customer
customer = Stripe::Customer.create(
  :source => token,
  :plan => "gold",
  :email => @user.email
)

# Grab the response data from Stripe:
card = customer.sources.first


# Save their Stripe ID:
@user.stripe_customer_id = customer.id

# Save their credit card details:
@user.card_id = card.id
@user.card_brand = card.brand
@user.card_last4 = card.last4
@user.card_expiration = Date.new(card.exp_year, card.exp_month, 1)

Then, you save it all to your database with a simple:

@user.save

Upvotes: 2

JosephK
JosephK

Reputation: 678

Newbie to parsing JSON - I had missing Quotes around values - should be this:

stripe_customer_params['id']
stripe_customer_params['cards']

And the 'data' element is an array, so for that one you use:

stripe_customer_params['cards']['data'].first['last4']

Try the response by Bongs above, first. Depending on how you implement Stripe, that may work.

Upvotes: 0

Bongs
Bongs

Reputation: 5592

Quite simple:

customer = Stripe::Customer.create(
  :card  => params[:stripeToken],
  :plan => params[:stripe_plan_id],
  :email => current_user.email
)

And then

customer.id # will return id and similarly you can access other attributes

Upvotes: 0

Related Questions