diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e92eca6cc..c57d66e452 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: build: name: Build and test - # TODO: this step is not compatible with ubuntu 24 LTS, so we pin the version here instead of using ubuntu-latest + # TODO: this step is not compatible with ubuntu 24 LTS, so we pin the version here instead of using ubuntu-latest runs-on: ubuntu-22.04 steps: @@ -46,7 +46,48 @@ jobs: - name: Build Release run: dotnet build src -c Release /p:ContinuousIntegrationBuild=true + - name: Determine OpenAPI versions and extract specs + run: | + set -e -o pipefail + + CURL_OPTS=(--retry 3 \ + --retry-all-errors \ + --fail \ + --verbose \ + --no-progress-meter \ + --show-error) + + LATEST_OPENAPI_VERSION=$(curl https://api.github.com/repos/stripe/openapi/releases/latest -s | jq .name -r) + CURRENT_OPENAPI_VERSION=$(cat OPENAPI_VERSION) + if [[ "$PR_BODY" == *"TEST USING LATEST OPENAPI"* ]]; then + OPENAPI_VERSION=$LATEST_OPENAPI_VERSION + else + OPENAPI_VERSION=$CURRENT_OPENAPI_VERSION + fi + + CURRENT_OPENAPI_SPEC=$(realpath latest.yaml) + CURRENT_OPENAPI_SPEC_JSON=${CURRENT_OPENAPI_SPEC%.yaml}.json + CURRENT_FIXTURES_JSON=${CURRENT_OPENAPI_SPEC%/*}/fixtures.json + + SPEC_NAME="spec3.sdk.yaml" + FIXTURES_NAME="fixtures3.json" + if [[ "$GITHUB_BASE" == *"b"* ]]; then + SPEC_NAME="spec3.beta.sdk.yaml" + FIXTURES_NAME="fixtures3.beta.json" + fi + curl "${CURL_OPTS[@]}" https://raw.githubusercontent.com/stripe/openapi/$OPENAPI_VERSION/openapi/${SPEC_NAME%.yaml}.json -o $CURRENT_OPENAPI_SPEC_JSON + curl "${CURL_OPTS[@]}" https://raw.githubusercontent.com/stripe/openapi/$OPENAPI_VERSION/openapi/$FIXTURES_NAME -o $CURRENT_FIXTURES_JSON + + env: + PR_BODY: ${{ github.event.pull_request.body }} + GITHUB_BASE: ${{ github.base_ref || github.ref_name }} + - uses: stripe/openapi/actions/stripe-mock@master + with: + # Used to determine if stripe-mock runs in beta mode + base: ${{ github.base_ref || github.ref_name }} + fixtures: "/workspace/fixtures.json" + spec_path: "/workspace/latest.json" - name: Run test suite run: just ci-test diff --git a/src/StripeTests/Entities/BalanceTransactions/BalanceTransactionTest.cs b/src/StripeTests/Entities/BalanceTransactions/BalanceTransactionTest.cs index a11a9d2e2b..db6dd9111c 100644 --- a/src/StripeTests/Entities/BalanceTransactions/BalanceTransactionTest.cs +++ b/src/StripeTests/Entities/BalanceTransactions/BalanceTransactionTest.cs @@ -15,7 +15,7 @@ public BalanceTransactionTest(StripeMockFixture stripeMockFixture) [Fact] public void Deserialize() { - string json = this.GetFixture("/v1/balance/history/txn_123"); + var json = GetResourceAsString("api_fixtures.balance_transaction.json"); var balanceTransaction = JsonConvert.DeserializeObject(json); Assert.NotNull(balanceTransaction); Assert.IsType(balanceTransaction); diff --git a/src/StripeTests/Entities/BankAccounts/BankAccountTest.cs b/src/StripeTests/Entities/BankAccounts/BankAccountTest.cs index cf6d3cab57..7dddbc77ff 100644 --- a/src/StripeTests/Entities/BankAccounts/BankAccountTest.cs +++ b/src/StripeTests/Entities/BankAccounts/BankAccountTest.cs @@ -25,7 +25,7 @@ public void DeserializeForAccount() [Fact] public void DeserializeForCustomer() { - string json = this.GetFixture("/v1/customers/cus_123/bank_accounts/ba_123"); + var json = GetResourceAsString("api_fixtures.bank_account.json"); var bankAccount = JsonConvert.DeserializeObject(json); Assert.NotNull(bankAccount); Assert.IsType(bankAccount); @@ -36,12 +36,7 @@ public void DeserializeForCustomer() [Fact] public void DeserializeWithExpansionsForCustomer() { - string[] expansions = - { - "customer", - }; - - string json = this.GetFixture("/v1/customers/cus_123/bank_accounts/ba_123", expansions); + var json = GetResourceAsString("api_fixtures.bank_account_with_expansion.json"); var bankAccount = JsonConvert.DeserializeObject(json); Assert.NotNull(bankAccount); Assert.IsType(bankAccount); diff --git a/src/StripeTests/Entities/Cards/CardTest.cs b/src/StripeTests/Entities/Cards/CardTest.cs index 2f2c825a05..4e81c9b236 100644 --- a/src/StripeTests/Entities/Cards/CardTest.cs +++ b/src/StripeTests/Entities/Cards/CardTest.cs @@ -14,7 +14,7 @@ public CardTest(StripeMockFixture stripeMockFixture) [Fact] public void Deserialize() { - string json = this.GetFixture("/v1/customers/cus_123/cards/card_123"); + var json = GetResourceAsString("api_fixtures.customer_card.json"); var card = JsonConvert.DeserializeObject(json); Assert.NotNull(card); Assert.IsType(card); @@ -25,12 +25,7 @@ public void Deserialize() [Fact] public void DeserializeWithExpansions() { - string[] expansions = - { - "customer", - }; - - string json = this.GetFixture("/v1/customers/cus_123/cards/card_123", expansions); + var json = GetResourceAsString("api_fixtures.customer_card_with_expansion.json"); var card = JsonConvert.DeserializeObject(json); Assert.NotNull(card); Assert.IsType(card); diff --git a/src/StripeTests/Entities/SubscriptionSchedules/SubscriptionScheduleTest.cs b/src/StripeTests/Entities/SubscriptionSchedules/SubscriptionScheduleTest.cs index eb17c46705..bbe2426779 100644 --- a/src/StripeTests/Entities/SubscriptionSchedules/SubscriptionScheduleTest.cs +++ b/src/StripeTests/Entities/SubscriptionSchedules/SubscriptionScheduleTest.cs @@ -14,7 +14,7 @@ public SubscriptionScheduleTest(StripeMockFixture stripeMockFixture) [Fact] public void Deserialize() { - string json = this.GetFixture("/v1/subscription_schedules/sub_sched_123"); + var json = GetResourceAsString("api_fixtures.subscription_schedule.json"); var schedule = JsonConvert.DeserializeObject(json); Assert.NotNull(schedule); Assert.IsType(schedule); @@ -25,16 +25,7 @@ public void Deserialize() [Fact] public void DeserializeWithExpansions() { - // TODO: support expanding "phases.coupon" and "phases.plans.plan" and others with stripe-mock - string[] expansions = - { - "customer", - "default_settings.default_payment_method", - "phases.plans.plan", - "subscription", - }; - - string json = this.GetFixture("/v1/subscription_schedules/sub_sched_123", expansions); + var json = GetResourceAsString("api_fixtures.subscription_schedule_with_expansions.json"); var schedule = JsonConvert.DeserializeObject(json); Assert.NotNull(schedule); Assert.IsType(schedule); diff --git a/src/StripeTests/Entities/Subscriptions/SubscriptionTest.cs b/src/StripeTests/Entities/Subscriptions/SubscriptionTest.cs index 799afcb696..382cd58a9e 100644 --- a/src/StripeTests/Entities/Subscriptions/SubscriptionTest.cs +++ b/src/StripeTests/Entities/Subscriptions/SubscriptionTest.cs @@ -14,7 +14,7 @@ public SubscriptionTest(StripeMockFixture stripeMockFixture) [Fact] public void Deserialize() { - string json = this.GetFixture("/v1/subscriptions/sub_123"); + var json = GetResourceAsString("api_fixtures.subscription.json"); var subscription = JsonConvert.DeserializeObject(json); Assert.NotNull(subscription); Assert.IsType(subscription); @@ -25,15 +25,7 @@ public void Deserialize() [Fact] public void DeserializeWithExpansions() { - string[] expansions = - { - "customer", - "default_payment_method", - "latest_invoice", - "pending_setup_intent", - }; - - string json = this.GetFixture("/v1/subscriptions/sub_123", expansions); + var json = GetResourceAsString("api_fixtures.subscription_with_expansions.json"); var subscription = JsonConvert.DeserializeObject(json); Assert.NotNull(subscription); Assert.IsType(subscription); diff --git a/src/StripeTests/Resources/api_fixtures/balance_transaction.json b/src/StripeTests/Resources/api_fixtures/balance_transaction.json new file mode 100644 index 0000000000..f6b23b847d --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/balance_transaction.json @@ -0,0 +1,8 @@ +{ + "id": "txn_123", + "object": "balance_transaction", + "source": { + "id": "random", + "object": "unknown_object" + } +} diff --git a/src/StripeTests/Resources/api_fixtures/bank_account.json b/src/StripeTests/Resources/api_fixtures/bank_account.json new file mode 100644 index 0000000000..a44dabdd65 --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/bank_account.json @@ -0,0 +1,16 @@ +{ + "account_holder_name": "Jane Austen", + "account_holder_type": "company", + "account_type": null, + "bank_name": "STRIPE TEST BANK", + "country": "US", + "currency": "usd", + "customer": null, + "fingerprint": "AuoSJ18zsVWV9SPc", + "id": "ba_123", + "last4": "6789", + "metadata": {}, + "object": "bank_account", + "routing_number": "110000000", + "status": "new" +} diff --git a/src/StripeTests/Resources/api_fixtures/bank_account_with_expansion.json b/src/StripeTests/Resources/api_fixtures/bank_account_with_expansion.json new file mode 100644 index 0000000000..431f839e8c --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/bank_account_with_expansion.json @@ -0,0 +1,83 @@ +{ + "account_holder_name": "Jane Austen", + "account_holder_type": "company", + "account_type": null, + "bank_name": "STRIPE TEST BANK", + "country": "US", + "currency": "usd", + "customer": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "balance": 0, + "created": 1234567890, + "currency": "usd", + "default_source": null, + "delinquent": false, + "description": null, + "discount": { + "checkout_session": null, + "coupon": { + "amount_off": null, + "created": 1028554472, + "currency": null, + "duration": "forever", + "duration_in_months": null, + "id": "obj_123", + "livemode": true, + "max_redemptions": null, + "metadata": null, + "name": null, + "object": "coupon", + "percent_off": null, + "redeem_by": null, + "times_redeemed": 990066668, + "valid": true + }, + "customer": null, + "end": null, + "id": "obj_123", + "invoice": null, + "invoice_item": null, + "object": "discount", + "promotion_code": null, + "start": 109757538, + "subscription": null, + "subscription_item": null + }, + "email": null, + "id": "cus_123", + "invoice_prefix": "7FE1103", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "footer": null, + "rendering_options": { + "amount_tax_display": null, + "template": null + } + }, + "livemode": false, + "metadata": {}, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": {}, + "tax_exempt": "none", + "test_clock": null + }, + "fingerprint": "AuoSJ18zsVWV9SPc", + "id": "ba_123", + "last4": "6789", + "metadata": {}, + "object": "bank_account", + "routing_number": "110000000", + "status": "new" +} diff --git a/src/StripeTests/Resources/api_fixtures/customer_card.json b/src/StripeTests/Resources/api_fixtures/customer_card.json new file mode 100644 index 0000000000..d791892785 --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/customer_card.json @@ -0,0 +1,26 @@ +{ + "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": null, + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 8, + "exp_year": 2025, + "fingerprint": "AOB934RVNwzk6xtn", + "funding": "credit", + "id": "card_123", + "last4": "4242", + "metadata": {}, + "name": "Jenny Rosen", + "object": "card", + "regulated_status": null, + "tokenization_method": null +} diff --git a/src/StripeTests/Resources/api_fixtures/customer_card_with_expansion.json b/src/StripeTests/Resources/api_fixtures/customer_card_with_expansion.json new file mode 100644 index 0000000000..b0c7958aa2 --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/customer_card_with_expansion.json @@ -0,0 +1,93 @@ +{ + "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": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "balance": 0, + "created": 1234567890, + "currency": "usd", + "default_source": null, + "delinquent": false, + "description": null, + "discount": { + "checkout_session": null, + "coupon": { + "amount_off": null, + "created": 1028554472, + "currency": null, + "duration": "forever", + "duration_in_months": null, + "id": "obj_123", + "livemode": true, + "max_redemptions": null, + "metadata": null, + "name": null, + "object": "coupon", + "percent_off": null, + "redeem_by": null, + "times_redeemed": 990066668, + "valid": true + }, + "customer": null, + "end": null, + "id": "obj_123", + "invoice": null, + "invoice_item": null, + "object": "discount", + "promotion_code": null, + "start": 109757538, + "subscription": null, + "subscription_item": null + }, + "email": null, + "id": "cus_123", + "invoice_prefix": "7FE1103", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "footer": null, + "rendering_options": { + "amount_tax_display": null, + "template": null + } + }, + "livemode": false, + "metadata": {}, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": {}, + "tax_exempt": "none", + "test_clock": null + }, + "cvc_check": "pass", + "dynamic_last4": null, + "exp_month": 8, + "exp_year": 2025, + "fingerprint": "AOB934RVNwzk6xtn", + "funding": "credit", + "id": "card_123", + "last4": "4242", + "metadata": {}, + "name": "Jenny Rosen", + "object": "card", + "regulated_status": null, + "tokenization_method": null +} diff --git a/src/StripeTests/Resources/api_fixtures/subscription.json b/src/StripeTests/Resources/api_fixtures/subscription.json new file mode 100644 index 0000000000..17385b3328 --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/subscription.json @@ -0,0 +1,157 @@ +{ + "application": null, + "application_fee_percent": null, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": { + "type": "account" + } + }, + "billing_cycle_anchor": 1234567890, + "billing_cycle_anchor_config": { + "day_of_month": 1361669285, + "hour": null, + "minute": null, + "month": null, + "second": null + }, + "cancel_at": 1234567890, + "cancel_at_period_end": false, + "canceled_at": 1234567890, + "cancellation_details": { + "comment": null, + "feedback": null, + "reason": null + }, + "collection_method": "charge_automatically", + "created": 1234567890, + "currency": "usd", + "customer": "cus_QXg1o8vcGmoR32", + "days_until_due": null, + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discounts": [], + "ended_at": 1234567890, + "id": "sub_123", + "invoice_settings": { + "account_tax_ids": null, + "issuer": { + "type": "self" + } + }, + "items": { + "data": [ + { + "created": 1721954060, + "current_period_end": 976287773, + "current_period_start": 1896570518, + "discounts": [], + "id": "si_QXhVBoJ7NQdNXh", + "metadata": {}, + "object": "subscription_item", + "price": { + "active": true, + "billing_scheme": "per_unit", + "created": 1721948530, + "currency": "usd", + "custom_unit_amount": { + "maximum": null, + "minimum": null, + "preset": null + }, + "id": "price_1PgafmB7WZ01zgkW6dKueIc5", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_QXg1hqf4jFNsqG", + "recurring": { + "interval": "month", + "interval_count": 1, + "meter": null, + "usage_type": "licensed" + }, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": { + "divide_by": 1592560163, + "round": "down" + }, + "type": "recurring", + "unit_amount": 2000, + "unit_amount_decimal": "2000" + }, + "quantity": 1, + "subscription": "sub_1Pgc6xB7WZ01zgkWJMvZp5ja", + "tax_rates": [] + } + ], + "has_more": false, + "object": "list", + "url": "/v1/subscription_items?subscription=sub_1Pgc6rB7WZ01zgkWNy0Cn5nw" + }, + "latest_invoice": null, + "livemode": false, + "metadata": {}, + "next_pending_invoice_item_invoice": 1234567890, + "object": "subscription", + "on_behalf_of": null, + "pause_collection": { + "behavior": "mark_uncollectible", + "resumes_at": null + }, + "payment_settings": { + "payment_method_options": { + "acss_debit": {}, + "bancontact": { + "preferred_language": "fr" + }, + "card": { + "network": null, + "request_three_d_secure": null + }, + "customer_balance": { + "funding_type": null + }, + "konbini": {}, + "sepa_debit": {}, + "us_bank_account": {} + }, + "payment_method_types": null, + "save_default_payment_method": null + }, + "pending_invoice_item_interval": { + "interval": "month", + "interval_count": 797691627 + }, + "pending_setup_intent": null, + "pending_update": { + "billing_cycle_anchor": null, + "expires_at": 833811170, + "subscription_items": null, + "trial_end": null, + "trial_from_plan": null + }, + "schedule": null, + "start_date": 1234567890, + "status": "active", + "test_clock": null, + "transfer_data": { + "amount_percent": null, + "destination": { + "id": "obj_123", + "object": "account" + } + }, + "trial_end": 1234567890, + "trial_settings": { + "end_behavior": { + "missing_payment_method": "create_invoice" + } + }, + "trial_start": 1234567890 +} diff --git a/src/StripeTests/Resources/api_fixtures/subscription_schedule.json b/src/StripeTests/Resources/api_fixtures/subscription_schedule.json new file mode 100644 index 0000000000..0b3e03455a --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/subscription_schedule.json @@ -0,0 +1,116 @@ +{ + "application": null, + "canceled_at": 1234567890, + "completed_at": 1234567890, + "created": 1234567890, + "current_phase": { + "end_date": 1725067410, + "start_date": 1573629589 + }, + "customer": "cus_QXg1o8vcGmoR32", + "default_settings": { + "application_fee_percent": null, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": { + "type": "account" + } + }, + "billing_cycle_anchor": "automatic", + "collection_method": "charge_automatically", + "default_payment_method": null, + "description": null, + "invoice_settings": { + "account_tax_ids": null, + "days_until_due": null, + "issuer": { + "type": "self" + } + }, + "on_behalf_of": null, + "transfer_data": { + "amount_percent": null, + "destination": { + "id": "obj_123", + "object": "account" + } + } + }, + "end_behavior": "release", + "id": "sub_sched_123", + "livemode": false, + "metadata": {}, + "object": "subscription_schedule", + "phases": [ + { + "add_invoice_items": [], + "application_fee_percent": null, + "billing_cycle_anchor": null, + "collection_method": null, + "currency": "usd", + "default_payment_method": null, + "default_tax_rates": [], + "description": null, + "discounts": [], + "end_date": 1754008472, + "invoice_settings": { + "account_tax_ids": null, + "days_until_due": null, + "issuer": { + "type": "account" + } + }, + "items": [ + { + "discounts": [], + "metadata": {}, + "plan": { + "active": true, + "amount": null, + "amount_decimal": null, + "billing_scheme": "tiered", + "created": 1028554472, + "currency": "currency", + "id": "obj_123", + "interval": "month", + "interval_count": 797691627, + "livemode": true, + "metadata": null, + "meter": null, + "nickname": null, + "object": "plan", + "product": null, + "tiers_mode": null, + "transform_usage": { + "divide_by": 1592560163, + "round": "down" + }, + "trial_period_days": null, + "usage_type": "licensed" + }, + "price": "price_1PgafmB7WZ01zgkW6dKueIc5", + "quantity": 1, + "tax_rates": [] + } + ], + "metadata": {}, + "on_behalf_of": null, + "proration_behavior": "create_prorations", + "start_date": 1722558872, + "transfer_data": { + "amount_percent": null, + "destination": { + "id": "obj_123", + "object": "account" + } + }, + "trial_end": null + } + ], + "released_at": 1234567890, + "released_subscription": null, + "status": "not_started", + "subscription": null, + "test_clock": null +} diff --git a/src/StripeTests/Resources/api_fixtures/subscription_schedule_with_expansions.json b/src/StripeTests/Resources/api_fixtures/subscription_schedule_with_expansions.json new file mode 100644 index 0000000000..00ddfc554b --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/subscription_schedule_with_expansions.json @@ -0,0 +1,399 @@ +{ + "application": null, + "canceled_at": 1234567890, + "completed_at": 1234567890, + "created": 1234567890, + "current_phase": { + "end_date": 1725067410, + "start_date": 1573629589 + }, + "customer": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "balance": 0, + "created": 1234567890, + "currency": "usd", + "default_source": null, + "delinquent": false, + "description": null, + "discount": { + "checkout_session": null, + "coupon": { + "amount_off": null, + "created": 1028554472, + "currency": null, + "duration": "forever", + "duration_in_months": null, + "id": "obj_123", + "livemode": true, + "max_redemptions": null, + "metadata": null, + "name": null, + "object": "coupon", + "percent_off": null, + "redeem_by": null, + "times_redeemed": 990066668, + "valid": true + }, + "customer": null, + "end": null, + "id": "obj_123", + "invoice": null, + "invoice_item": null, + "object": "discount", + "promotion_code": null, + "start": 109757538, + "subscription": null, + "subscription_item": null + }, + "email": null, + "id": "cus_QXg1o8vcGmoR32", + "invoice_prefix": "7FE1103", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "footer": null, + "rendering_options": { + "amount_tax_display": null, + "template": null + } + }, + "livemode": false, + "metadata": {}, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": {}, + "tax_exempt": "none", + "test_clock": null + }, + "default_settings": { + "application_fee_percent": null, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": { + "type": "account" + } + }, + "billing_cycle_anchor": "automatic", + "collection_method": "charge_automatically", + "default_payment_method": { + "allow_redisplay": "unspecified", + "billing_details": { + "address": { + "city": "San Francisco", + "country": "US", + "line1": "1234 Fake Street", + "line2": null, + "postal_code": "94102", + "state": "CA" + }, + "email": "jenny@example.com", + "name": null, + "phone": "+15555555555" + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "display_brand": "visa", + "exp_month": 8, + "exp_year": 2025, + "fingerprint": "AOB934RVNwzk6xtn", + "funding": "credit", + "generated_from": { + "charge": null, + "payment_method_details": { + "type": "type" + }, + "setup_attempt": null + }, + "last4": "4242", + "networks": { + "available": [ + "visa" + ], + "preferred": null + }, + "regulated_status": null, + "three_d_secure_usage": { + "supported": true + }, + "wallet": { + "dynamic_last4": null, + "type": "link" + } + }, + "created": 1234567890, + "customer": null, + "id": "pm_1Pgc75B7WZ01zgkWlHVgdEGJ", + "livemode": false, + "metadata": { + "order_id": "123456789" + }, + "object": "payment_method", + "type": "card" + }, + "description": null, + "invoice_settings": { + "account_tax_ids": null, + "days_until_due": null, + "issuer": { + "type": "self" + } + }, + "on_behalf_of": null, + "transfer_data": { + "amount_percent": null, + "destination": { + "id": "obj_123", + "object": "account" + } + } + }, + "end_behavior": "release", + "id": "sub_sched_123", + "livemode": false, + "metadata": {}, + "object": "subscription_schedule", + "phases": [ + { + "add_invoice_items": [], + "application_fee_percent": null, + "billing_cycle_anchor": null, + "collection_method": null, + "currency": "usd", + "default_payment_method": null, + "default_tax_rates": [], + "description": null, + "discounts": [], + "end_date": 1754008472, + "invoice_settings": { + "account_tax_ids": null, + "days_until_due": null, + "issuer": { + "type": "account" + } + }, + "items": [ + { + "discounts": [], + "metadata": {}, + "plan": { + "active": true, + "amount": null, + "amount_decimal": null, + "billing_scheme": "tiered", + "created": 1028554472, + "currency": "currency", + "id": "obj_123", + "interval": "month", + "interval_count": 797691627, + "livemode": true, + "metadata": null, + "meter": null, + "nickname": null, + "object": "plan", + "product": null, + "tiers_mode": null, + "transform_usage": { + "divide_by": 1592560163, + "round": "down" + }, + "trial_period_days": null, + "usage_type": "licensed" + }, + "price": "price_1PgafmB7WZ01zgkW6dKueIc5", + "quantity": 1, + "tax_rates": [] + } + ], + "metadata": {}, + "on_behalf_of": null, + "proration_behavior": "create_prorations", + "start_date": 1722558872, + "transfer_data": { + "amount_percent": null, + "destination": { + "id": "obj_123", + "object": "account" + } + }, + "trial_end": null + } + ], + "released_at": 1234567890, + "released_subscription": null, + "status": "not_started", + "subscription": { + "application": null, + "application_fee_percent": null, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": { + "type": "account" + } + }, + "billing_cycle_anchor": 1234567890, + "billing_cycle_anchor_config": { + "day_of_month": 1361669285, + "hour": null, + "minute": null, + "month": null, + "second": null + }, + "cancel_at": 1234567890, + "cancel_at_period_end": false, + "canceled_at": 1234567890, + "cancellation_details": { + "comment": null, + "feedback": null, + "reason": null + }, + "collection_method": "charge_automatically", + "created": 1234567890, + "currency": "usd", + "customer": "cus_QXg1o8vcGmoR32", + "days_until_due": null, + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discounts": [], + "ended_at": 1234567890, + "id": "sub_1Pgc6rB7WZ01zgkWNy0Cn5nw", + "invoice_settings": { + "account_tax_ids": null, + "issuer": { + "type": "self" + } + }, + "items": { + "data": [ + { + "created": 1721954060, + "current_period_end": 976287773, + "current_period_start": 1896570518, + "discounts": [], + "id": "si_QXhVBoJ7NQdNXh", + "metadata": {}, + "object": "subscription_item", + "price": { + "active": true, + "billing_scheme": "per_unit", + "created": 1721948530, + "currency": "usd", + "custom_unit_amount": { + "maximum": null, + "minimum": null, + "preset": null + }, + "id": "price_1PgafmB7WZ01zgkW6dKueIc5", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_QXg1hqf4jFNsqG", + "recurring": { + "interval": "month", + "interval_count": 1, + "meter": null, + "usage_type": "licensed" + }, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": { + "divide_by": 1592560163, + "round": "down" + }, + "type": "recurring", + "unit_amount": 2000, + "unit_amount_decimal": "2000" + }, + "quantity": 1, + "subscription": "sub_1Pgc6xB7WZ01zgkWJMvZp5ja", + "tax_rates": [] + } + ], + "has_more": false, + "object": "list", + "url": "/v1/subscription_items?subscription=sub_1Pgc6rB7WZ01zgkWNy0Cn5nw" + }, + "latest_invoice": null, + "livemode": false, + "metadata": {}, + "next_pending_invoice_item_invoice": 1234567890, + "object": "subscription", + "on_behalf_of": null, + "pause_collection": { + "behavior": "mark_uncollectible", + "resumes_at": null + }, + "payment_settings": { + "payment_method_options": { + "acss_debit": {}, + "bancontact": { + "preferred_language": "fr" + }, + "card": { + "network": null, + "request_three_d_secure": null + }, + "customer_balance": { + "funding_type": null + }, + "konbini": {}, + "sepa_debit": {}, + "us_bank_account": {} + }, + "payment_method_types": null, + "save_default_payment_method": null + }, + "pending_invoice_item_interval": { + "interval": "month", + "interval_count": 797691627 + }, + "pending_setup_intent": null, + "pending_update": { + "billing_cycle_anchor": null, + "expires_at": 833811170, + "subscription_items": null, + "trial_end": null, + "trial_from_plan": null + }, + "schedule": null, + "start_date": 1234567890, + "status": "active", + "test_clock": null, + "transfer_data": { + "amount_percent": null, + "destination": { + "id": "obj_123", + "object": "account" + } + }, + "trial_end": 1234567890, + "trial_settings": { + "end_behavior": { + "missing_payment_method": "create_invoice" + } + }, + "trial_start": 1234567890 + }, + "test_clock": null +} diff --git a/src/StripeTests/Resources/api_fixtures/subscription_with_expansions.json b/src/StripeTests/Resources/api_fixtures/subscription_with_expansions.json new file mode 100644 index 0000000000..6f933d5eee --- /dev/null +++ b/src/StripeTests/Resources/api_fixtures/subscription_with_expansions.json @@ -0,0 +1,520 @@ +{ + "application": null, + "application_fee_percent": null, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": { + "type": "account" + } + }, + "billing_cycle_anchor": 1234567890, + "billing_cycle_anchor_config": { + "day_of_month": 1361669285, + "hour": null, + "minute": null, + "month": null, + "second": null + }, + "cancel_at": 1234567890, + "cancel_at_period_end": false, + "canceled_at": 1234567890, + "cancellation_details": { + "comment": null, + "feedback": null, + "reason": null + }, + "collection_method": "charge_automatically", + "created": 1234567890, + "currency": "usd", + "customer": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "balance": 0, + "created": 1234567890, + "currency": "usd", + "default_source": null, + "delinquent": false, + "description": null, + "discount": { + "checkout_session": null, + "coupon": { + "amount_off": null, + "created": 1028554472, + "currency": null, + "duration": "forever", + "duration_in_months": null, + "id": "obj_123", + "livemode": true, + "max_redemptions": null, + "metadata": null, + "name": null, + "object": "coupon", + "percent_off": null, + "redeem_by": null, + "times_redeemed": 990066668, + "valid": true + }, + "customer": null, + "end": null, + "id": "obj_123", + "invoice": null, + "invoice_item": null, + "object": "discount", + "promotion_code": null, + "start": 109757538, + "subscription": null, + "subscription_item": null + }, + "email": null, + "id": "cus_QXg1o8vcGmoR32", + "invoice_prefix": "7FE1103", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "footer": null, + "rendering_options": { + "amount_tax_display": null, + "template": null + } + }, + "livemode": false, + "metadata": {}, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": {}, + "tax_exempt": "none", + "test_clock": null + }, + "days_until_due": null, + "default_payment_method": { + "allow_redisplay": "unspecified", + "billing_details": { + "address": { + "city": "San Francisco", + "country": "US", + "line1": "1234 Fake Street", + "line2": null, + "postal_code": "94102", + "state": "CA" + }, + "email": "jenny@example.com", + "name": null, + "phone": "+15555555555" + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "display_brand": "visa", + "exp_month": 8, + "exp_year": 2025, + "fingerprint": "AOB934RVNwzk6xtn", + "funding": "credit", + "generated_from": { + "charge": null, + "payment_method_details": { + "type": "type" + }, + "setup_attempt": null + }, + "last4": "4242", + "networks": { + "available": [ + "visa" + ], + "preferred": null + }, + "regulated_status": null, + "three_d_secure_usage": { + "supported": true + }, + "wallet": { + "dynamic_last4": null, + "type": "link" + } + }, + "created": 1234567890, + "customer": null, + "id": "pm_1Pgc75B7WZ01zgkWlHVgdEGJ", + "livemode": false, + "metadata": { + "order_id": "123456789" + }, + "object": "payment_method", + "type": "card" + }, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discounts": [], + "ended_at": 1234567890, + "id": "sub_123", + "invoice_settings": { + "account_tax_ids": null, + "issuer": { + "type": "self" + } + }, + "items": { + "data": [ + { + "created": 1721954060, + "current_period_end": 976287773, + "current_period_start": 1896570518, + "discounts": [], + "id": "si_QXhVBoJ7NQdNXh", + "metadata": {}, + "object": "subscription_item", + "price": { + "active": true, + "billing_scheme": "per_unit", + "created": 1721948530, + "currency": "usd", + "custom_unit_amount": { + "maximum": null, + "minimum": null, + "preset": null + }, + "id": "price_1PgafmB7WZ01zgkW6dKueIc5", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_QXg1hqf4jFNsqG", + "recurring": { + "interval": "month", + "interval_count": 1, + "meter": null, + "usage_type": "licensed" + }, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": { + "divide_by": 1592560163, + "round": "down" + }, + "type": "recurring", + "unit_amount": 2000, + "unit_amount_decimal": "2000" + }, + "quantity": 1, + "subscription": "sub_1Pgc6xB7WZ01zgkWJMvZp5ja", + "tax_rates": [] + } + ], + "has_more": false, + "object": "list", + "url": "/v1/subscription_items?subscription=sub_1Pgc6rB7WZ01zgkWNy0Cn5nw" + }, + "latest_invoice": { + "account_country": "US", + "account_name": null, + "account_tax_ids": null, + "amount_due": 1000, + "amount_overpaid": 149300825, + "amount_paid": 0, + "amount_remaining": 1000, + "amount_shipping": 0, + "application": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": false, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": { + "type": "account" + }, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "collection_method": "charge_automatically", + "created": 1234567890, + "currency": "usd", + "custom_fields": null, + "customer": "cus_QXg1o8vcGmoR32", + "customer_address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "customer_email": null, + "customer_name": null, + "customer_phone": null, + "customer_shipping": {}, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discounts": [], + "due_date": 1234567890, + "effective_at": 1234567890, + "ending_balance": null, + "footer": null, + "from_invoice": { + "action": "action", + "invoice": "invoice" + }, + "hosted_invoice_url": null, + "id": "in_1Pgc6tB7WZ01zgkWu9fdqL6I", + "invoice_pdf": null, + "issuer": { + "type": "self" + }, + "last_finalization_error": { + "type": "idempotency_error" + }, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 1000, + "currency": "usd", + "description": "My First Invoice Item (created for API docs)", + "discount_amounts": [], + "discountable": true, + "discounts": [], + "id": "il_tmp_1Pgc6sB7WZ01zgkWrG16hkdl", + "invoice": "in_1Pgc6tB7WZ01zgkWu9fdqL6I", + "livemode": false, + "metadata": {}, + "object": "line_item", + "parent": { + "invoice_item_details": { + "invoice_item": "invoice_item", + "proration": true, + "proration_details": { + "credited_items": { + "invoice": "invoice", + "invoice_line_items": [ + "invoice_line_items" + ] + } + }, + "subscription": null + }, + "subscription_item_details": { + "invoice_item": null, + "proration": true, + "proration_details": { + "credited_items": { + "invoice": "invoice", + "invoice_line_items": [ + "invoice_line_items" + ] + } + }, + "subscription": "subscription", + "subscription_item": "subscription_item" + }, + "type": "invoice_item_details" + }, + "period": { + "end": 1721954054, + "start": 1721954054 + }, + "pretax_credit_amounts": null, + "pricing": { + "type": "price_details", + "unit_amount_decimal": null + }, + "quantity": 1, + "subscription": null, + "taxes": null + } + ], + "has_more": false, + "object": "list", + "url": "/v1/invoices/in_1Pgc6tB7WZ01zgkWu9fdqL6I/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1234567890, + "number": null, + "object": "invoice", + "on_behalf_of": null, + "parent": { + "quote_details": { + "quote": "quote" + }, + "subscription_details": { + "metadata": null, + "subscription": "subscription" + }, + "type": "quote_details" + }, + "payment_settings": { + "default_mandate": null, + "payment_method_options": { + "acss_debit": {}, + "bancontact": { + "preferred_language": "fr" + }, + "card": { + "request_three_d_secure": null + }, + "customer_balance": { + "funding_type": null + }, + "konbini": {}, + "sepa_debit": {}, + "us_bank_account": {} + }, + "payment_method_types": null + }, + "period_end": 1234567890, + "period_start": 1234567890, + "post_payment_credit_notes_amount": 0, + "pre_payment_credit_notes_amount": 0, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": null + }, + "template": null, + "template_version": null + }, + "shipping_cost": { + "amount_subtotal": 1555417355, + "amount_tax": 1424534716, + "amount_total": 1117121693, + "shipping_rate": null + }, + "shipping_details": {}, + "starting_balance": 0, + "statement_descriptor": null, + "status": "draft", + "status_transitions": { + "finalized_at": null, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subtotal": 1000, + "subtotal_excluding_tax": 1000, + "test_clock": null, + "total": 1000, + "total_discount_amounts": [], + "total_excluding_tax": 1000, + "total_pretax_credit_amounts": null, + "total_taxes": null, + "webhooks_delivered_at": 1234567890 + }, + "livemode": false, + "metadata": {}, + "next_pending_invoice_item_invoice": 1234567890, + "object": "subscription", + "on_behalf_of": null, + "pause_collection": { + "behavior": "mark_uncollectible", + "resumes_at": null + }, + "payment_settings": { + "payment_method_options": { + "acss_debit": {}, + "bancontact": { + "preferred_language": "fr" + }, + "card": { + "network": null, + "request_three_d_secure": null + }, + "customer_balance": { + "funding_type": null + }, + "konbini": {}, + "sepa_debit": {}, + "us_bank_account": {} + }, + "payment_method_types": null, + "save_default_payment_method": null + }, + "pending_invoice_item_interval": { + "interval": "month", + "interval_count": 797691627 + }, + "pending_setup_intent": { + "application": null, + "automatic_payment_methods": { + "enabled": null + }, + "cancellation_reason": null, + "client_secret": "seti_1Pgag7B7WZ01zgkWSgwGdb8Z_secret_QXg2AQLdBxJwtY51IkwvUaBVsnCqPSp", + "created": 1234567890, + "customer": null, + "description": null, + "flow_directions": null, + "id": "seti_1Pgag7B7WZ01zgkWSgwGdb8Z", + "last_setup_error": { + "type": "idempotency_error" + }, + "latest_attempt": null, + "livemode": false, + "mandate": null, + "metadata": {}, + "next_action": { + "type": "type" + }, + "object": "setup_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "obj_123", + "parent": null + }, + "payment_method_options": {}, + "payment_method_types": [ + "card" + ], + "single_use_mandate": null, + "status": "requires_payment_method", + "usage": "off_session" + }, + "pending_update": { + "billing_cycle_anchor": null, + "expires_at": 833811170, + "subscription_items": null, + "trial_end": null, + "trial_from_plan": null + }, + "schedule": null, + "start_date": 1234567890, + "status": "active", + "test_clock": null, + "transfer_data": { + "amount_percent": null, + "destination": { + "id": "obj_123", + "object": "account" + } + }, + "trial_end": 1234567890, + "trial_settings": { + "end_behavior": { + "missing_payment_method": "create_invoice" + } + }, + "trial_start": 1234567890 +}