From d8d874f7eab5ea97a923e86b1e6cde05df070c68 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Thu, 21 Dec 2023 10:47:24 +0000 Subject: [PATCH] Creates a connected account and tests OFN code for disconnecting it Re-records cassettes Creates a bogus publishable key We need to feed some value to the ENV variables which are picked up from the local test environment, for the build to run. We could also store them all as environment secrets on our repo, but I don'r think this is necessary, as we only run recorderd API/VCR calls on our build, and never real API calls. --- .env.test | 1 + ...stroys_the_record_and_notifies_Bugsnag.yml | 36 +-- .../destroys_the_record.yml | 261 ++++++++++++++++-- spec/models/stripe_account_spec.rb | 24 +- 4 files changed, 267 insertions(+), 55 deletions(-) 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