diff --git a/.env.test b/.env.test index afa4e58c1d..a52a6b10b4 100644 --- a/.env.test +++ b/.env.test @@ -6,6 +6,7 @@ STRIPE_SECRET_TEST_API_KEY="bogus_key" STRIPE_CUSTOMER="bogus_customer" STRIPE_ACCOUNT="bogus_account" STRIPE_CLIENT_ID="bogus_client_id" +STRIPE_PUBLIC_TEST_API_KEY="bogus_stripe_publishable_key" SITE_URL="test.host" diff --git a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml index 4808014362..49aef67136 100644 --- a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml +++ b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_fails/destroys_the_record_and_notifies_Bugsnag.yml @@ -32,7 +32,7 @@ http_interactions: Server: - nginx Date: - - Tue, 19 Dec 2023 12:55:29 GMT + - Thu, 21 Dec 2023 10:45:56 GMT Content-Type: - application/json; charset=utf-8 Content-Length: @@ -54,22 +54,22 @@ http_interactions: Referrer-Policy: - strict-origin-when-cross-origin Request-Id: - - req_1v8IG0ihHAhDnR + - req_5I7fo8ZIT4iiOD Set-Cookie: - __Host-session=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure; SameSite=None - __stripe_orig_props=%7B%22referrer%22%3A%22%22%2C%22landing%22%3A%22https%3A%2F%2Fconnect.stripe.com%2Foauth%2Fdeauthorize%22%7D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:56 GMT; secure; HttpOnly; SameSite=Lax - - machine_identifier=nsadMhesm4x1GYVPmQcxGxkwOEHT0uGESxaoxop6tgOLhu%2BvkqpSkkKcxxRvqqlpa%2BQ%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + - machine_identifier=QgNDMZHR38PElyy9q592gsCebE6wwZpG2yGY42Pr9eBKa8VgTy3D6hYV68qrQ22Ss6M%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:56 GMT; secure; HttpOnly; SameSite=Lax - - private_machine_identifier=5MctxMzB3oEJsWQPiwovzvt6vy1pHt5g4lYzkFr0hY3jCZZPQz%2F6jU71Ye8gqtUCUkE%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:29 GMT; secure; + - private_machine_identifier=I5FD6ty3P%2Fu3NcPXx%2FQWf0rlSSmmseIhF3Jjh1k0VDaE0r9pST2zC0QF5zOrj9mL8xU%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:56 GMT; secure; HttpOnly; SameSite=None - site-auth=; domain=stripe.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure - - stripe.csrf=ivC9DH1gR7jYwuuHUpqqkApanZ79wswQZMBVKfzfaLr1n5rf_HwKb4sv66YdBNDs03Zq1H_JeHyOjBZ1rENh4jw-AYTZVJxQjKfvlBDZNhjvEvPk5QdyiiBil-k2Op8FixB9Mw4lkg%3D%3D; + - stripe.csrf=3pBovX-WeRInaYekIenxBP4HZPJUKPIapUKWzkq61RZGXY_L4XNwm0d3kPOaWycuCWRVZPILZHIl0E1ajDrp9jw-AYTZVJw3W5vZuecF9T6yl15939IAMLnS4TPsJz7sL-g2uJ-hMA%3D%3D; domain=stripe.com; path=/; secure; HttpOnly; SameSite=None Strict-Transport-Security: - max-age=63072000; includeSubDomains; preload @@ -79,17 +79,17 @@ http_interactions: Stripe-Parent-Id: - '0000000000000000' Stripe-Span-Id: - - 1317edffcd8f0941 + - c9754f0ed47ef010 Www-Authenticate: - Bearer realm="Stripe" X-Apiori-Intentional-Latency: - 0s X-Apiori-Reqid: - - dub2DISD22ogqObCRqkyYRE + - dub1DIXA8nWJL2tSW8r7Vtw X-Apiori-Server-Duration-Ms: - - '126' + - '118' X-Apiori-Upstream-Duration: - - 126.447763ms + - 118.447951ms X-Apiori-Upstream-Name: - manage-srv X-Apiori-Upstream-Region: @@ -99,21 +99,21 @@ http_interactions: X-Envoy-Attempt-Count: - '1' X-Envoy-Upstream-Service-Time: - - '248' + - '235' X-Robots-Tag: - none X-Stripe-Bg-Intended-Route-Color: - - green + - blue X-Stripe-C-Cost: - '2' X-Stripe-Client-Envoy-Start-Time-Us: - - '1702990529582694' + - '1703155556322583' X-Stripe-Rpc-C-Cost-Report: - Cg0IARIJY2VsbF8wMDA3Cg8IARILZ2xvYmFsX2NlbGw= X-Stripe-Server-Envoy-Start-Time-Us: - - '1702990529583695' + - '1703155556323654' X-Stripe-Server-Envoy-Upstream-Service-Time-Ms: - - '123' + - '115' body: encoding: UTF-8 string: |- @@ -121,5 +121,5 @@ http_interactions: "error": "invalid_client", "error_description": "No such application: 'bogus_client_id'" } - recorded_at: Tue, 19 Dec 2023 12:55:29 GMT + recorded_at: Thu, 21 Dec 2023 10:45:56 GMT recorded_with: VCR 6.2.0 diff --git a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml index 0c8489a0f3..03de8ad4e2 100644 --- a/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml +++ b/spec/fixtures/vcr_cassettes/Stripe-v10.3.0/StripeAccount/deauthorize_and_destroy/when_the_Stripe_API_disconnect_succeeds/destroys_the_record.yml @@ -2,10 +2,10 @@ http_interactions: - request: method: post - uri: https://connect.stripe.com/oauth/deauthorize + uri: https://api.stripe.com/v1/accounts body: encoding: UTF-8 - string: stripe_user_id=&client_id=ca_MzG1xs6tZFDztUlak7uFxoUM36G6307W + string: type=standard&country=AU&email=jumping.jack%40example.com headers: User-Agent: - Stripe/v1 RubyBindings/10.3.0 @@ -26,17 +26,219 @@ http_interactions: - "*/*" response: status: - code: 401 - message: Unauthorized + code: 200 + message: OK headers: Server: - nginx Date: - - Tue, 19 Dec 2023 12:55:30 GMT + - Thu, 21 Dec 2023 10:45:58 GMT Content-Type: - - application/json; charset=utf-8 + - application/json Content-Length: - - '164' + - '2916' + Connection: + - keep-alive + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Methods: + - GET,HEAD,PUT,PATCH,POST,DELETE + Access-Control-Allow-Origin: + - "*" + Access-Control-Expose-Headers: + - Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, + X-Stripe-Privileged-Session-Required + Access-Control-Max-Age: + - '300' + Cache-Control: + - no-cache, no-store + Content-Security-Policy: + - report-uri https://q.stripe.com/csp-report?p=v1%2Faccounts; block-all-mixed-content; + default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; + img-src 'self'; script-src 'self' 'report-sample'; style-src 'self' + Idempotency-Key: + - 4faf7619-9abc-418c-82ab-d4c1b0b2f5ca + Original-Request: + - req_akFJPnmmxbaXxd + Request-Id: + - req_akFJPnmmxbaXxd + Stripe-Should-Retry: + - 'false' + Stripe-Version: + - '2023-10-16' + Vary: + - Origin + X-Stripe-Routing-Context-Priority-Tier: + - api-testmode + Strict-Transport-Security: + - max-age=63072000; includeSubDomains; preload + body: + encoding: UTF-8 + string: |- + { + "id": "acct_1OPjlJQKtA57Vnxb", + "object": "account", + "business_profile": { + "mcc": null, + "name": null, + "product_description": null, + "support_address": null, + "support_email": null, + "support_phone": null, + "support_url": null, + "url": null + }, + "business_type": null, + "capabilities": {}, + "charges_enabled": false, + "controller": { + "is_controller": true, + "type": "application" + }, + "country": "AU", + "created": 1703155558, + "default_currency": "aud", + "details_submitted": false, + "email": "jumping.jack@example.com", + "external_accounts": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "/v1/accounts/acct_1OPjlJQKtA57Vnxb/external_accounts" + }, + "future_requirements": { + "alternatives": [], + "current_deadline": null, + "currently_due": [], + "disabled_reason": null, + "errors": [], + "eventually_due": [], + "past_due": [], + "pending_verification": [] + }, + "metadata": {}, + "payouts_enabled": false, + "requirements": { + "alternatives": [], + "current_deadline": null, + "currently_due": [ + "business_profile.product_description", + "business_profile.support_phone", + "business_profile.url", + "external_account", + "tos_acceptance.date", + "tos_acceptance.ip" + ], + "disabled_reason": "requirements.past_due", + "errors": [], + "eventually_due": [ + "business_profile.product_description", + "business_profile.support_phone", + "business_profile.url", + "external_account", + "tos_acceptance.date", + "tos_acceptance.ip" + ], + "past_due": [ + "external_account", + "tos_acceptance.date", + "tos_acceptance.ip" + ], + "pending_verification": [] + }, + "settings": { + "bacs_debit_payments": { + "display_name": null, + "service_user_number": null + }, + "branding": { + "icon": null, + "logo": null, + "primary_color": null, + "secondary_color": null + }, + "card_issuing": { + "tos_acceptance": { + "date": null, + "ip": null + } + }, + "card_payments": { + "decline_on": { + "avs_failure": false, + "cvc_failure": false + }, + "statement_descriptor_prefix": null, + "statement_descriptor_prefix_kana": null, + "statement_descriptor_prefix_kanji": null + }, + "dashboard": { + "display_name": null, + "timezone": "Etc/UTC" + }, + "payments": { + "statement_descriptor": null, + "statement_descriptor_kana": null, + "statement_descriptor_kanji": null + }, + "payouts": { + "debit_negative_balances": true, + "schedule": { + "delay_days": 2, + "interval": "daily" + }, + "statement_descriptor": null + }, + "sepa_debit_payments": {} + }, + "tos_acceptance": { + "date": null, + "ip": null, + "user_agent": null + }, + "type": "standard" + } + recorded_at: Thu, 21 Dec 2023 10:45:58 GMT +- request: + method: post + uri: https://connect.stripe.com/oauth/deauthorize + body: + encoding: UTF-8 + string: stripe_user_id=acct_1OPjlJQKtA57Vnxb&client_id=ca_MzG1xs6tZFDztUlak7uFxoUM36G6307W + headers: + User-Agent: + - Stripe/v1 RubyBindings/10.3.0 + Authorization: + - Bearer + Content-Type: + - application/x-www-form-urlencoded + X-Stripe-Client-Telemetry: + - '{"last_request_metrics":{"request_id":"req_akFJPnmmxbaXxd","request_duration_ms":1906}}' + Stripe-Version: + - '2023-10-16' + X-Stripe-Client-User-Agent: + - '{"bindings_version":"10.3.0","lang":"ruby","lang_version":"3.1.4 p223 (2023-03-30)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux + version 6.2.0-39-generic (buildd@lcy02-amd64-045) (x86_64-linux-gnu-gcc-11 + (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) + #40~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 16 10:53:04 UTC 2","hostname":"ff-LAT"}' + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx + Date: + - Thu, 21 Dec 2023 10:45:59 GMT + Content-Type: + - application/json + Content-Length: + - '47' Connection: - keep-alive Cache-Control: @@ -54,22 +256,22 @@ http_interactions: Referrer-Policy: - strict-origin-when-cross-origin Request-Id: - - req_pGBBuPOXb6xMly + - req_GI4KuC138PCJAi Set-Cookie: - __Host-session=; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure; SameSite=None - __stripe_orig_props=%7B%22referrer%22%3A%22%22%2C%22landing%22%3A%22https%3A%2F%2Fconnect.stripe.com%2Foauth%2Fdeauthorize%22%7D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:59 GMT; secure; HttpOnly; SameSite=Lax - - machine_identifier=JJUOdPN1UTC9yKxG3Cief9mNanXTKM9y3VmUcEzfmFXEB%2FViV5jXpnxq0kFsEjoKyyg%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + - machine_identifier=HKDeDB5hKqj4clQzAFDSsv1CYfwTn24qrrs%2BEPZII8GCVRJ%2FXlImUJxiAZyJEtIZ%2Fmw%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:59 GMT; secure; HttpOnly; SameSite=Lax - - private_machine_identifier=qnLLWHsR2kIkVnuEZbUabBmPGOMmgoa%2B2t%2Bt82Sn41uVMChBI%2FF%2FmVlhmFtmb9%2Fnd70%3D; - domain=stripe.com; path=/; expires=Wed, 18 Dec 2024 12:55:30 GMT; secure; + - private_machine_identifier=MtWBDVmUQlK99LHORT57Q4I%2BFQVz1NgOm8YwuEQ1hcLBZg%2B0065RWGEpjtHqd73XO9g%3D; + domain=stripe.com; path=/; expires=Fri, 20 Dec 2024 10:45:59 GMT; secure; HttpOnly; SameSite=None - site-auth=; domain=stripe.com; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; secure - - stripe.csrf=aIL_e_YV7LaxFPnsyZHeK9DsuQ7sm4bYeawhyIBlivow1bC0KAoKCaoR0E-WklLxlvDMXwX1_tY7Aa5l_gJ-zzw-AYTZVJwtl69iWowmC5Gcjqp-_ni03g1Mcx1Hbz6xqEXSGCKfKg%3D%3D; + - stripe.csrf=2JHhBnTu9M9rT2X5ddKYKiGrldjy1_TlDZkBH0QYBxLbuX5pF9u2LvZHkuwLr3S96XXp0ZHdgqJRzdhyPTMYmDw-AYTZVJziZaudEZeavUdznjQfqSpNTprhJdapun0wOEWmMxs7zQ%3D%3D; domain=stripe.com; path=/; secure; HttpOnly; SameSite=None Strict-Transport-Security: - max-age=63072000; includeSubDomains; preload @@ -79,17 +281,15 @@ http_interactions: Stripe-Parent-Id: - '0000000000000000' Stripe-Span-Id: - - abaf119f94aa71c4 - Www-Authenticate: - - Bearer realm="Stripe" + - 7c70338af8eb59d9 X-Apiori-Intentional-Latency: - 0s X-Apiori-Reqid: - - dub1DISD299L0WxB0Akf1uq + - dub1DIXA981iCMFaeUWou2O X-Apiori-Server-Duration-Ms: - - '138' + - '226' X-Apiori-Upstream-Duration: - - 137.918128ms + - 225.729973ms X-Apiori-Upstream-Name: - manage-srv X-Apiori-Upstream-Region: @@ -99,27 +299,28 @@ http_interactions: X-Envoy-Attempt-Count: - '1' X-Envoy-Upstream-Service-Time: - - '257' + - '347' X-Robots-Tag: - none X-Stripe-Bg-Intended-Route-Color: - - green + - blue X-Stripe-C-Cost: - - '4' + - '22' X-Stripe-Client-Envoy-Start-Time-Us: - - '1702990530466139' + - '1703155559193296' X-Stripe-Rpc-C-Cost-Report: - - Cg0IAxIJY2VsbF8wMDA3Cg8IARILZ2xvYmFsX2NlbGw= + - Cg0IFBIJY2VsbF8wMDA3Cg8IAhILZ2xvYmFsX2NlbGw= X-Stripe-Server-Envoy-Start-Time-Us: - - '1702990530466931' + - '1703155559194276' X-Stripe-Server-Envoy-Upstream-Service-Time-Ms: - - '135' + - '223' + Stripe-Action-Id: + - dub1DIXA981iCMFaeUWou2O body: encoding: UTF-8 string: |- { - "error": "invalid_client", - "error_description": "This application is not connected to stripe account , or that account does not exist." + "stripe_user_id": "acct_1OPjlJQKtA57Vnxb" } - recorded_at: Tue, 19 Dec 2023 12:55:30 GMT + recorded_at: Thu, 21 Dec 2023 10:45:59 GMT recorded_with: VCR 6.2.0 diff --git a/spec/models/stripe_account_spec.rb b/spec/models/stripe_account_spec.rb index 374f7ee640..d890152bb7 100644 --- a/spec/models/stripe_account_spec.rb +++ b/spec/models/stripe_account_spec.rb @@ -9,13 +9,13 @@ describe StripeAccount do let!(:enterprise2) { create(:enterprise) } let(:client_id) { ENV.fetch('STRIPE_CLIENT_ID', nil) } let(:stripe_user_id) { ENV.fetch('STRIPE_ACCOUNT', nil) } + let(:stripe_publishable_key) { ENV.fetch('STRIPE_PUBLIC_TEST_API_KEY', nil) } + let(:secret) { ENV.fetch('STRIPE_SECRET_TEST_API_KEY', nil) } let!(:stripe_account) { create(:stripe_account, enterprise:, stripe_user_id:) } - let(:secret) { ENV.fetch('STRIPE_SECRET_TEST_API_KEY', nil) } - before do Stripe.api_key = secret end @@ -25,7 +25,7 @@ describe StripeAccount do it "destroys the record and notifies Bugsnag" do # returns status 401 - expect(Bugsnag).to receive(:notify) + expect(Bugsnag).to receive(:notify) # and receives Bugsnag notification expect { stripe_account.deauthorize_and_destroy }.to change( @@ -35,16 +35,26 @@ describe StripeAccount do end context "when the Stripe API disconnect succeeds" do - before { Stripe.client_id = client_id } + let!(:connected_account) do + Stripe::Account.create({ + type: 'standard', + country: 'AU', + email: 'jumping.jack@example.com' + }) + end + + before do + Stripe.client_id = client_id + stripe_account.update!(stripe_publishable_key:, stripe_user_id: connected_account.id) + end it "destroys the record" do # returns status 200 - expect(Bugsnag).to_not receive(:notify) - stripe_account.deauthorize_and_destroy + expect(Bugsnag).to_not receive(:notify) # and does not receive Bugsnag notification expect { stripe_account.deauthorize_and_destroy }.to change( - StripeAccount.where(stripe_user_id:), :count + StripeAccount.where(stripe_user_id: connected_account.id), :count ).from(1).to(0) end end