integrallis / stripe_event

Stripe webhook integration for Rails applications.
https://rubygems.org/gems/stripe_event
MIT License
841 stars 107 forks source link

account.updated event results in 401 status code #62

Closed patrickslin closed 8 years ago

patrickslin commented 8 years ago

Hi,

I'm trying to test the account.updated webhook, but my subscriber objects are not called and the status is 401.

15:50:32 log.1    | Started POST "/stripe/webhooks" for 54.187.216.72 at 2016-01-12 15:50:32 -0800
15:50:32 log.1    | Cannot render console from 54.187.216.72! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
15:50:32 log.1    | Value for params[:data][:object][:verification][:fields_needed] was set to nil, because it was one of [], [null] or [null, null, ...]. Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation for more information.
15:50:32 log.1    | Processing by StripeEvent::WebhookController#event as XML
15:50:32 log.1    |   Parameters: {"id"=>"evt_17Sbu8ALH9ylSV0DbMbDtR0r", "object"=>"event", "api_version"=>"2015-10-16", "created"=>1452642624, "data"=>{"object"=>{"id"=>"acct_17SVByALH9ylSV0D", "object"=>"account", "business_logo"=>nil, "business_name"=>"ABC Store", "business_url"=>nil, "charges_enabled"=>true, "country"=>"US", "currencies_supported"=>["usd", "aed", "afn", "all", "amd", "ang", "aoa", "ars", "aud", "awg", "azn", "bam", "bbd", "bdt", "bgn", "bif", "bmd", "bnd", "bob", "brl", "bsd", "bwp", "bzd", "cad", "cdf", "chf", "clp", "cny", "cop", "crc", "cve", "czk", "djf", "dkk", "dop", "dzd", "egp", "etb", "eur", "fjd", "fkp", "gbp", "gel", "gip", "gmd", "gnf", "gtq", "gyd", "hkd", "hnl", "hrk", "htg", "huf", "idr", "ils", "inr", "isk", "jmd", "jpy", "kes", "kgs", "khr", "kmf", "krw", "kyd", "kzt", "lak", "lbp", "lkr", "lrd", "lsl", "ltl", "mad", "mdl", "mga", "mkd", "mnt", "mop", "mro", "mur", "mvr", "mwk", "mxn", "myr", "mzn", "nad", "ngn", "nio", "nok", "npr", "nzd", "pab", "pen", "pgk", "php", "pkr", "pln", "pyg", "qar", "ron", "rsd", "rub", "rwf", "sar", "sbd", "scr", "sek", "sgd", "shp", "sll", "sos", "srd", "std", "svc", "szl", "thb", "tjs", "top", "try", "ttd", "twd", "tzs", "uah", "ugx", "uyu", "uzs", "vnd", "vuv", "wst", "xaf", "xcd", "xof", "xpf", "yer", "zar", "zmw"], "default_currency"=>"usd", "details_submitted"=>false, "display_name"=>nil, "email"=>nil, "managed"=>true, "statement_descriptor"=>nil, "support_phone"=>nil, "timezone"=>"Etc/UTC", "transfers_enabled"=>true, "debit_negative_balances"=>false, "decline_charge_on"=>{"avs_failure"=>false, "cvc_failure"=>false}, "external_accounts"=>{"object"=>"list", "data"=>[{"id"=>"ba_17SWBzALH9ylSV0DmWrXWXiv", "object"=>"bank_account", "account"=>"acct_17SVByALH9ylSV0D", "bank_name"=>"STRIPE TEST BANK", "country"=>"US", "currency"=>"usd", "default_for_currency"=>true, "fingerprint"=>"RHmpw2FNYY8tV7jp", "last4"=>"6789", "metadata"=>{}, "name"=>nil, "routing_number"=>"110000000", "status"=>"new"}], "has_more"=>false, "total_count"=>1, "url"=>"/v1/accounts/acct_17SVByALH9ylSV0D/external_accounts"}, "legal_entity"=>{"additional_owners"=>nil, "address"=>{"city"=>"Cupertino", "country"=>"US", "line1"=>"1 Infinite Loop", "line2"=>nil, "postal_code"=>"95014", "state"=>"CA"}, "business_name"=>"ABC Store", "dob"=>{"day"=>4, "month"=>4, "year"=>1990}, "first_name"=>"ABC", "last_name"=>"Developer", "personal_address"=>{"city"=>"Cupertino", "country"=>"US", "line1"=>"1 Infinite Loop", "line2"=>nil, "postal_code"=>"95014", "state"=>"CA"}, "personal_id_number_provided"=>false, "ssn_last_4_provided"=>false, "type"=>"company", "verification"=>{"details"=>nil, "details_code"=>nil, "document"=>nil, "status"=>"unverified"}}, "metadata"=>{}, "product_description"=>nil, "tos_acceptance"=>{"date"=>1452037418, "ip"=>"127.0.0.1", "user_agent"=>nil}, "transfer_schedule"=>{"delay_days"=>2, "interval"=>"weekly", "weekly_anchor"=>"monday"}, "verification"=>{"disabled_reason"=>nil, "due_by"=>nil, "fields_needed"=>nil}}, "previous_attributes"=>{"business_name"=>"ABC Developer Store"}}, "livemode"=>false, "pending_webhooks"=>1, "request"=>"req_7i1yoOdJ9idSi9", "type"=>"account.updated", "user_id"=>"acct_17SVByALH9ylSV0D", "webhook"=>{"id"=>"evt_17Sbu8ALH9ylSV0DbMbDtR0r", "object"=>"event", "api_version"=>"2015-10-16", "created"=>1452642624, "data"=>{"object"=>{"id"=>"acct_17SVByALH9ylSV0D", "object"=>"account", "business_logo"=>nil, "business_name"=>"ABC Store", "business_url"=>nil, "charges_enabled"=>true, "country"=>"US", "currencies_supported"=>["usd", "aed", "afn", "all", "amd", "ang", "aoa", "ars", "aud", "awg", "azn", "bam", "bbd", "bdt", "bgn", "bif", "bmd", "bnd", "bob", "brl", "bsd", "bwp", "bzd", "cad", "cdf", "chf", "clp", "cny", "cop", "crc", "cve", "czk", "djf", "dkk", "dop", "dzd", "egp", "etb", "eur", "fjd", "fkp", "gbp", "gel", "gip", "gmd", "gnf", "gtq", "gyd", "hkd", "hnl", "hrk", "htg", "huf", "idr", "ils", "inr", "isk", "jmd", "jpy", "kes", "kgs", "khr", "kmf", "krw", "kyd", "kzt", "lak", "lbp", "lkr", "lrd", "lsl", "ltl", "mad", "mdl", "mga", "mkd", "mnt", "mop", "mro", "mur", "mvr", "mwk", "mxn", "myr", "mzn", "nad", "ngn", "nio", "nok", "npr", "nzd", "pab", "pen", "pgk", "php", "pkr", "pln", "pyg", "qar", "ron", "rsd", "rub", "rwf", "sar", "sbd", "scr", "sek", "sgd", "shp", "sll", "sos", "srd", "std", "svc", "szl", "thb", "tjs", "top", "try", "ttd", "twd", "tzs", "uah", "ugx", "uyu", "uzs", "vnd", "vuv", "wst", "xaf", "xcd", "xof", "xpf", "yer", "zar", "zmw"], "default_currency"=>"usd", "details_submitted"=>false, "display_name"=>nil, "email"=>nil, "managed"=>true, "statement_descriptor"=>nil, "support_phone"=>nil, "timezone"=>"Etc/UTC", "transfers_enabled"=>true, "debit_negative_balances"=>false, "decline_charge_on"=>{"avs_failure"=>false, "cvc_failure"=>false}, "external_accounts"=>{"object"=>"list", "data"=>[{"id"=>"ba_17SWBzALH9ylSV0DmWrXWXiv", "object"=>"bank_account", "account"=>"acct_17SVByALH9ylSV0D", "bank_name"=>"STRIPE TEST BANK", "country"=>"US", "currency"=>"usd", "default_for_currency"=>true, "fingerprint"=>"RHmpw2FNYY8tV7jp", "last4"=>"6789", "metadata"=>{}, "name"=>nil, "routing_number"=>"110000000", "status"=>"new"}], "has_more"=>false, "total_count"=>1, "url"=>"/v1/accounts/acct_17SVByALH9ylSV0D/external_accounts"}, "legal_entity"=>{"additional_owners"=>nil, "address"=>{"city"=>"Cupertino", "country"=>"US", "line1"=>"1 Infinite Loop", "line2"=>nil, "postal_code"=>"95014", "state"=>"CA"}, "business_name"=>"ABC Store", "dob"=>{"day"=>4, "month"=>4, "year"=>1990}, "first_name"=>"ABC", "last_name"=>"Developer", "personal_address"=>{"city"=>"Cupertino", "country"=>"US", "line1"=>"1 Infinite Loop", "line2"=>nil, "postal_code"=>"95014", "state"=>"CA"}, "personal_id_number_provided"=>false, "ssn_last_4_provided"=>false, "type"=>"company", "verification"=>{"details"=>nil, "details_code"=>nil, "document"=>nil, "status"=>"unverified"}}, "metadata"=>{}, "product_description"=>nil, "tos_acceptance"=>{"date"=>1452037418, "ip"=>"127.0.0.1", "user_agent"=>nil}, "transfer_schedule"=>{"delay_days"=>2, "interval"=>"weekly", "weekly_anchor"=>"monday"}, "verification"=>{"disabled_reason"=>nil, "due_by"=>nil, "fields_needed"=>nil}}, "previous_attributes"=>{"business_name"=>"ABC Developer Store"}}, "livemode"=>false, "pending_webhooks"=>1, "request"=>"req_7i1yoOdJ9idSi9", "type"=>"account.updated", "user_id"=>"acct_17SVByALH9ylSV0D"}}
15:50:32 log.1    | Geokit is using the domain: ngrok.io
15:50:32 log.1    | Completed 401 Unauthorized in 212ms (ActiveRecord: 0.0ms)
15:50:32 web.1    | [94107] 54.187.216.72 - - [12/Jan/2016:15:50:32 -0800] "POST / HTTP/1.1" 401 - 0.2298

But, other events, such as charge.succeeded work with no problem.

15:42:35 log.1    | Started POST "/stripe/webhooks" for 54.187.216.72 at 2016-01-12 15:42:35 -0800
15:42:35 log.1    | Cannot render console from 54.187.216.72! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
15:42:35 log.1    | Value for params[:data][:object][:refunds][:data] was set to nil, because it was one of [], [null] or [null, null, ...]. Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation for more information.
15:42:35 log.1    | Processing by StripeEvent::WebhookController#event as XML
15:42:35 log.1    |   Parameters: {"id"=>"evt_17SbmQGRxo80gNumHix3Ut6y", "object"=>"event", "api_version"=>"2015-10-16", "created"=>1452642146, "data"=>{"object"=>{"id"=>"ch_17SbmPGRxo80gNumukbaoHrB", "object"=>"charge", "amount"=>99, "amount_refunded"=>0, "application_fee"=>"fee_7i1qWN24rvCXIx", "balance_transaction"=>"txn_17SbmPGRxo80gNumP1nLgbcn", "captured"=>true, "created"=>1452642145, "currency"=>"usd", "customer"=>nil, "description"=>nil, "destination"=>"acct_17BAkdB2ypFVGqS2", "dispute"=>nil, "failure_code"=>nil, "failure_message"=>nil, "fraud_details"=>{}, "invoice"=>nil, "livemode"=>false, "metadata"=>{}, "paid"=>true, "receipt_email"=>nil, "receipt_number"=>nil, "refunded"=>false, "refunds"=>{"object"=>"list", "data"=>nil, "has_more"=>false, "total_count"=>0, "url"=>"/v1/charges/ch_17SbmPGRxo80gNumukbaoHrB/refunds"}, "shipping"=>nil, "source"=>{"id"=>"card_17SbmKGRxo80gNumk8gnMXL1", "object"=>"card", "address_city"=>nil, "address_country"=>nil, "address_line1"=>nil, "address_line1_check"=>nil, "address_line2"=>nil, "address_state"=>nil, "address_zip"=>nil, "address_zip_check"=>nil, "brand"=>"Visa", "country"=>"US", "customer"=>nil, "cvc_check"=>"pass", "dynamic_last4"=>nil, "exp_month"=>11, "exp_year"=>2016, "fingerprint"=>"s8DNQYfXI7bbYeRi", "funding"=>"credit", "last4"=>"4242", "metadata"=>{}, "name"=>nil, "tokenization_method"=>nil}, "statement_descriptor"=>nil, "status"=>"succeeded", "transfer"=>"tr_17SbmPGRxo80gNumgIzYFWYP"}}, "livemode"=>false, "pending_webhooks"=>1, "request"=>"req_7i1qYloeVk3PYk", "type"=>"charge.succeeded", "webhook"=>{"id"=>"evt_17SbmQGRxo80gNumHix3Ut6y", "object"=>"event", "api_version"=>"2015-10-16", "created"=>1452642146, "data"=>{"object"=>{"id"=>"ch_17SbmPGRxo80gNumukbaoHrB", "object"=>"charge", "amount"=>99, "amount_refunded"=>0, "application_fee"=>"fee_7i1qWN24rvCXIx", "balance_transaction"=>"txn_17SbmPGRxo80gNumP1nLgbcn", "captured"=>true, "created"=>1452642145, "currency"=>"usd", "customer"=>nil, "description"=>nil, "destination"=>"acct_17BAkdB2ypFVGqS2", "dispute"=>nil, "failure_code"=>nil, "failure_message"=>nil, "fraud_details"=>{}, "invoice"=>nil, "livemode"=>false, "metadata"=>{}, "paid"=>true, "receipt_email"=>nil, "receipt_number"=>nil, "refunded"=>false, "refunds"=>{"object"=>"list", "data"=>nil, "has_more"=>false, "total_count"=>0, "url"=>"/v1/charges/ch_17SbmPGRxo80gNumukbaoHrB/refunds"}, "shipping"=>nil, "source"=>{"id"=>"card_17SbmKGRxo80gNumk8gnMXL1", "object"=>"card", "address_city"=>nil, "address_country"=>nil, "address_line1"=>nil, "address_line1_check"=>nil, "address_line2"=>nil, "address_state"=>nil, "address_zip"=>nil, "address_zip_check"=>nil, "brand"=>"Visa", "country"=>"US", "customer"=>nil, "cvc_check"=>"pass", "dynamic_last4"=>nil, "exp_month"=>11, "exp_year"=>2016, "fingerprint"=>"s8DNQYfXI7bbYeRi", "funding"=>"credit", "last4"=>"4242", "metadata"=>{}, "name"=>nil, "tokenization_method"=>nil}, "statement_descriptor"=>nil, "status"=>"succeeded", "transfer"=>"tr_17SbmPGRxo80gNumgIzYFWYP"}}, "livemode"=>false, "pending_webhooks"=>1, "request"=>"req_7i1qYloeVk3PYk", "type"=>"charge.succeeded"}}
15:42:35 log.1    | Geokit is using the domain: ngrok.io
15:42:35 log.1    | AccountUpdated event: evt_17SbmQGRxo80gNumHix3Ut6y
15:42:35 log.1    | StripeEvent event: charge.succeeded
15:42:35 log.1    | got here
15:42:35 log.1    | Completed 200 OK in 217ms (ActiveRecord: 0.0ms)

I am using ngrok to expose my local server to Stripe for the webhook endpoints. But, I don't believe that this is causing any issue. Could it be due to this being a "managed account"? Does that matter?

Thanks, Patrick

patrickslin commented 8 years ago

I found that this is due to stripe_event not supporting managed accounts. To retrieve the event for those accounts, the "stripe_account" needs to be specified.

event = Stripe::Event.retrieve({params[:id]},{:stripe_account => "acct_xxxx"})

Any plans on supporting this? Thanks.

benissimo commented 8 years ago

In practice, it seems like it's sufficient to conditionally pass params[:user_id] through as a :stripe_account argument when present:

StripeEvent.event_retriever = lambda do |params|
  api_key = # whatever's needed to lookup api key for top level account
  stripe_opts = {api_key: api_key}
  stripe_opts.merge! stripe_account: params[:user_id] if params[:user_id]
  Stripe::Event.retrieve({id: params[:id]}, stripe_opts)
end

If your webhook receives events for "connected" accounts, a :user_id param will be present. Instead if your webhook receives events for the top-level (standalone) account, the :user_id param will not be present.

patrickslin commented 8 years ago

Yes. Thanks. This is just what I have done. It's working now.