Using the stripe events gem I am trying to update a Stripe subscription on the event unsubscribe. My events are not firing even though they are receiving the webhook.
I am running my endpoint on ngrok and using the stripe-events gem. I have installed the stripe cli so I can see that the webhook events are firing.
My thinking is that there is a problem with the code I am trying to use
#user = User.find_by_stripe_id(event.data.object.customer) however I got this code from a thread on GoRails. Chris Oliver said that it looked correct and I have repurposed it for my app so that makes me think it might be something else.
# config/initializers/stripe_events.rb
Stripe.api_key = Rails.application.credentials.stripe_publishable_key
Stripe.api_key = Rails.application.credentials.stripe_signing_secret
StripeEvent.configure do |events|
events.subscribe "customer.subscription.updated" do |event|
#user = User.find_by_stripe_id(event.data.object.customer)
logger.info "Processing the request..."
if DateTime.now >= #user.subscription_end_date
logger.info "if statement is running..."
#user.update_attribute(subscribed: false)
#user.save!
end
end
end
I am not sure if this is needed but here is the method that triggers the webhook. I have added the DateTime.now-1 for testing if the webhook so that it simulates an expired subscription.
# app/controllers/subscriptions_controller.rb
def destroy
if Rails.env.production?
Stripe.api_key = Rails.application.credentials.stripe_live_api
else
Stripe.api_key = Rails.application.credentials.stripe_api_key
end
customer = Stripe::Customer.retrieve(current_user.stripe_id)
customer.subscriptions.retrieve(current_user.stripe_subscription_id)
Stripe::Subscription.update(current_user.stripe_subscription_id,:cancel_at_period_end => true)
##current_user.update(subscription_end_date: Time.at(customer.subscriptions[:data].first[:current_period_end]))
current_user.update(subscription_end_date: DateTime.now-1)
redirect_to root_path, notice: "Your subscription has been cancelled"
end
I tested the response from the stripe webhook
{
"object": {
"id": "sub_FqLLZZ4pKhlM0y",
"object": "subscription",
"application_fee_percent": null,
"billing": "charge_automatically",
"billing_cycle_anchor": 1568957293,
"billing_thresholds": null,
"cancel_at": 1571549293,
"cancel_at_period_end": true,
"canceled_at": 1568957302,
"collection_method": "charge_automatically",
"created": 1568957293,
"current_period_end": 1571549293,
"current_period_start": 1568957293,
"customer": "cus_FqLLXYHyVl7mJq",
"days_until_due": null,
"default_payment_method": null,
"default_source": null,
"default_tax_rates": [
],
"discount": null,
"ended_at": null,
"items": {
"object": "list",
"data": [
{
"id": "si_FqLLngQNhxl5p4",
"object": "subscription_item",
"billing_thresholds": null,
"created": 1568957293,
"metadata": {
},
"plan": {
"id": "plan_FYHrCVDopLPS37",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 2900,
"amount_decimal": "2900",
"billing_scheme": "per_unit",
"created": 1564792787,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {
},
"nickname": "Uproar Basic",
"product": "prod_FYHpmwiftJrqpC",
"tiers": null,
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"quantity": 1,
"subscription": "sub_FqLLZZ4pKhlM0y",
"tax_rates": [
]
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/subscription_items?subscription=sub_FqLLZZ4pKhlM0y"
},
"latest_invoice": "in_1FKefBJCkfo4YGOMvdEjZ3ny",
"livemode": false,
"metadata": {
},
"pending_setup_intent": null,
"plan": {
"id": "plan_FYHrCVDopLPS37",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 2900,
"amount_decimal": "2900",
"billing_scheme": "per_unit",
"created": 1564792787,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {
},
"nickname": "Uproar Basic",
"product": "prod_FYHpmwiftJrqpC",
"tiers": null,
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"quantity": 1,
"schedule": null,
"start": 1568957302,
"start_date": 1568957293,
"status": "active",
"tax_percent": null,
"trial_end": null,
"trial_start": null
},
"previous_attributes": {
"cancel_at": null,
"cancel_at_period_end": false,
"canceled_at": null,
"start": 1568957293
}
}
I'm not sure code in config/initializers/stripe_events.rb can have access to app/controllers once your app is launched.
You should call a service :
config/initializers/stripe_events.rb
StripeEvent.configure do |events|
events.subscribe "customer.subscription.updated" do |event|
StripeUdpateSubscription.new
end
end
app/services/stripe_update_subscription.rb
class StripeUpdateSubscription
def call(event)
..// you code here
end
end
Related
Im trying to implement stripe webhooks in my rails app. The webhook send this json data.
{ "created": 1326853478, "livemode": false, "id": "evt_00000000000000", "type": "invoice.payment_succeeded", "object": "event", "request": null, "pending_webhooks": 1, "api_version": "2017-06-05", "data": {
"object": {
"id": "in_00000000000000",
"object": "invoice",
"amount_due": 500,
"application_fee": null,
"attempt_count": 1,
"attempted": true,
"charge": "_00000000000000",
"closed": true,
"currency": "usd",
"customer": "cus_00000000000000",
"date": 1501950408,
"description": null,
"discount": null,
"ending_balance": 0,
"forgiven": false,
"lines": {
"data": [
{
"id": "sub_BLXcTSekdHflq5",
"object": "line_item",
"amount": 500,
"currency": "usd",
"description": null,
"discountable": true,
"livemode": true,
"metadata": {
},
"period": {
"start": 1507246341,
"end": 1509924741
},
"plan": {
"id": "Subscriber",
"object": "plan",
"amount": 500,
"created": 1501901993,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {
},
"name": "Subscriber",
"statement_descriptor": "WatchBuddie Stream sub",
"trial_period_days": null
},
"proration": false,
"quantity": 1,
"subscription": null,
"subscription_item": "si_1AyqWnFr5iCt1Tv7n23zDLOM",
"type": "subscription"
}
],
"total_count": 1,
"object": "list",
"url": "/v1/invoices/in_1AnV6yFr5iCt1Tv7PnqZ0EUA/lines"
},
"livemode": false,
"metadata": {
},
"next_payment_attempt": null,
"paid": true,
"period_end": 1501950408,
"period_start": 1501950408,
"receipt_number": null,
"starting_balance": 0,
"statement_descriptor": null,
"subscription": "sub_00000000000000",
"subtotal": 500,
"tax": null,
"tax_percent": null,
"total": 500,
"webhooks_delivered_at": 1501950409
} } }
webhook method
def webhooks
begin
event_json = JSON.parse(request.body.read)
event_object = event_json['data']['object']
#refer event types here https://stripe.com/docs/api#event_types
case event_json['type']
when 'invoice.payment_succeeded'
#Update the total subscription total
#Send in email to the user telling them that they resubbed
logger.debug event_object['lines']['id']
end
My question is how do I get the "id": "sub_BLXcTSekdHflq5" I tried
logger.debug event_object['lines']['id']
It doesn't seem to be working what am I doing wrong? I'm sure its just a syntax thing that I am not understanding.
Thanks for all the help!
Figured it out the lines data was in a hash so you had to iterate over it. This is what I did for anyone who comes across this.
event_object['lines']['data'].each{ |i|
sub_id = i['id']
logger.debug sub_id
}
Hi i have the below response for Stripe in my Grails 2.5.1 application , how i can read and manipulate it using Grails .
Response :
<com.stripe.model.Charge#1467160391 id=ch_17bcduFKvYH0sAt4OMSKjOzA> JSON: { "amount": 7200, "created": 1454790414, "currency": "egp", "id": "ch_17bcduFKvYH0sAt4OMSKjOzA", "livemode": false, "paid": true, "refunded": false, "disputed": null, "captured": true, "description": "customer#sample.org", "statement_description": null, "failure_message": null, "failure_code": null, "amount_refunded": 0, "customer": null, "invoice": null, "refunds": { "data": [], "total_count": 0, "has_more": false, "url": "/v1/charges/ch_17bcduFKvYH0sAt4OMSKjOzA/refunds", "count": null }, "card": null, "dispute": null, "balance_transaction": "txn_17bcduFKvYH0sAt4qSSDZ7Bj", "metadata": {} }
i have the being fetched, i need to read whats inside data under sources
"id": "cus_7nDkZw63KvTuy5",
"object": "customer",
"account_balance": 0,
"created": 1453839669,
"currency": "usd",
"default_source": "card_17XdJE2eZvKYlo2CBNnle4YM",
"delinquent": false,
"description": null,
"discount": null,
"email": "someone#example.com",
"livemode": false,
"metadata": {
},
"shipping": null,
"sources": {
"object": "list",
"data": [
{
"id": "card_17XdJE2eZvKYlo2CBNnle4YM",
"object": "card",
"address_city": null,
"address_country": null,
"address_line1": null,
"address_line1_check": null,
"address_line2": null,
"address_state": null,
"address_zip": null,
"address_zip_check": null,
"brand": "Visa",
"country": "US",
"customer": "cus_7nDkZw63KvTuy5",
"cvc_check": "pass",
"dynamic_last4": null,
"exp_month": 12,
"exp_year": 2016,
"funding": "credit",
"last4": "4242",
"metadata": {
},
"name": "someone#example.com",
"tokenization_method": null
}
],
"has_more": false,
"total_count": 1,
"url": "/v1/customers/cus_7nDkZw63KvTuy5/sources"
},
"subscriptions": {
"object": "list",
"data": [
],
"has_more": false,
"total_count": 0,
"url": "/v1/customers/cus_7nDkZw63KvTuy5/subscriptions"
}
}
Try this code you will get array
[[[[result objectForKey:#"sources"] objectForKey:#"data"] objectAtIndex:0] objectForKey:#"country"];
you will get US as answer.
I am trying to save the Stripe's user current_period_end to the database. When I create a new subscription the value saves as 0 instead of the actual date their subscription ends.
Is there something I'm missing?
It should be saving as:
"current_period_end": 1441292360
Subscription.rb:
def save_with_stripe_payment
customer = Stripe::Customer.create(description: email, plan: plan_id, card: stripe_card_token)
self.stripe_customer_token = customer.id
self.cancellation_date = customer.subscriptions.first.current_period_end
save!
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating customer: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
It's possible that this could be an issue with the type of data you're receiving and how you're storing it in your database. Based on the information you have given I would expect you have the wrong field type.
Your code is correct so I would double check to see if your field is a integer.
When Strip creates a new customer it returns the object posted at the bottom of this question.
To access the current_period_end you would need to do customer.subscriptions.data.first["current_period_end"]
{
"object": "customer",
"created": 1409190039,
"id": "cus_4fdAW5ftNQow1a",
"livemode": false,
"description": "new_paying_customer",
"email": null,
"delinquent": false,
"metadata": {},
"subscriptions": {
"object": "list",
"total_count": 1,
"has_more": false,
"url": "/v1/customers/cus_4fdAW5ftNQow1a/subscriptions",
"data": [
{
"id": "sub_4fdAS9IlSOFfiv",
"plan": {
"interval": "month",
"name": "Basic Plan",
"created": 1409178429,
"amount": 1200,
"currency": "usd",
"id": "basic",
"object": "plan",
"livemode": false,
"interval_count": 1,
"trial_period_days": null,
"metadata": {},
"statement_description": null
},
"object": "subscription",
"start": 1409190039,
"status": "active",
"customer": "cus_4fdAW5ftNQow1a",
"cancel_at_period_end": false,
"current_period_start": 1409190039,
"current_period_end": 1411868439,
"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_4fdAW5ftNQow1a/cards",
"data": [
{
"id": "card_14WHtz4rPA98z9GRTW1QMenU",
"object": "card",
"last4": "4242",
"brand": "Visa",
"funding": "unknown",
"exp_month": 1,
"exp_year": 2015,
"fingerprint": "0qYXzA0d9EZtsgQ6",
"customer": "cus_4fdAW5ftNQow1a"
}
]
},
"default_card": "card_14WHtz4rPA98z9GRTW1QMenU"
}
This is just a shot in the dark (because I don't know the format of your cancellation_date field or the database you are using), but are you sure you are handling the returned timestamp correctly?
If cancellation_date is a DateTime field, I believe you have to do something like:
cpe = customer.subscriptions.first.current_period_end
self.cancellation_date = Time.at(cpe).to_datetime
If that isn't the problem then I'd use the console and/or the server output to make sure current_period_end is returning what you expect it to when you call Stripe::Customer.create (like others have suggested). You really need to determine when the "switch to 0" is happening, so I'd check (in this order):
The response from Stripe when you create the customer
The value of customer.subscriptions.first.current_period_end
The value of self.cancellation_date after assignment but before saving
There may also be validations or before_save filters that are messing with this field before hitting the database.
That's all my ideas for now :)
Hope this helps!
If there is one record in request.json the below code works
class BookController {
def save = {
def book = new Book(JSON.parse(yourJson))
book.save(flush:true)
}
}
But how to get bookList if there is multiple records in my request.JSON like:
[{
"id": 3,
"name": "MYNAME",
"description": "test",
"category": 1,
"venue": null,
"status": "Published",
"deleted": false,
"pricingPolicy": null
}, {
"id": 6,
"name": "YZ",
"description": "test6",
"category": 2,
"venue": null,
"status": "Unpublished",
"deleted": false,
"pricingPolicy": null
}, {
"id": 9,
"name": "YZ",
"description": "test6",
"category": 1,
"venue": null,
"status": "Published",
"deleted": false,
"pricingPolicy": null
}]
request.JSON.each{ new Book( it ).save() }
should do