diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c57d66e452..519bca2d17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,7 @@ on: branches: - master - beta + - private-preview - sdk-release/** - feature/** diff --git a/CHANGELOG.md b/CHANGELOG.md index 74fbb62411..7c5c41a486 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,22 @@ This release changes the pinned API version to `2025-08-27.preview`. * Add support for `PixDisplayQrCode` on `SetupIntent.NextAction` * Add support for `ReaderSecurity` on `Terminal.ConfigurationCreateOptions`, `Terminal.ConfigurationUpdateOptions`, and `Terminal.Configuration` +## 48.5.0 - 2025-08-27 +* [#3164](https://github.com/stripe/stripe-dotnet/pull/3164) Add section on private preview SDKs in readme +* [#3159](https://github.com/stripe/stripe-dotnet/pull/3159) Update generated code. This release changes the pinned API version to `2025-08-27.basil`. + * Add support for `BalanceReport`, `PayoutDetails`, and `PayoutReconciliationReport` on `AccountSession.Components` and `AccountSessionComponentsOptions` + * Add support for `Name` on `BillingPortal.ConfigurationCreateOptions`, `BillingPortal.ConfigurationUpdateOptions`, and `BillingPortal.Configuration` + * Add support for `Installments` on `Charge.PaymentMethodDetails.Alma` + * Add support for `TransactionId` on `Charge.PaymentMethodDetails.Alma`, `Charge.PaymentMethodDetails.AmazonPay`, `Charge.PaymentMethodDetails.Billie`, `Charge.PaymentMethodDetails.KakaoPay`, `Charge.PaymentMethodDetails.KrCard`, `Charge.PaymentMethodDetails.NaverPay`, `Charge.PaymentMethodDetails.Payco`, `Charge.PaymentMethodDetails.RevolutPay`, `Charge.PaymentMethodDetails.SamsungPay`, and `Charge.PaymentMethodDetails.Satispay` + * Add support for `Location` and `Reader` on `Charge.PaymentMethodDetails.Paynow` + * Add support for `AmountIncludesIof` on `Checkout.Session.PaymentMethodOptions.Pix`, `CheckoutSessionPaymentMethodOptionsPixOptions`, `PaymentIntent.PaymentMethodOptions.Pix`, and `PaymentIntentPaymentMethodOptionsPixOptions` + * Add support for `Metadata` and `Period` on `InvoiceScheduleDetailsPhaseAddInvoiceItemOptions`, `SubscriptionAddInvoiceItemOptions`, `SubscriptionSchedule.Phase.AddInvoiceItem`, and `SubscriptionSchedulePhaseAddInvoiceItemOptions` + * Add support for `ExpMonth` and `ExpYear` on `Issuing.CardCreateOptions` + * Add support for `ExcludedPaymentMethodTypes` on `PaymentIntentCreateOptions` and `PaymentIntent` + * Add support for `PayoutMethod` on `PayoutCreateOptions` and `Payout` + * Add support for `Mxn` on `Terminal.Configuration.Tipping` and `TerminalConfigurationTippingOptions` + * Add support for `Card` on `Terminal.TestHelpersReaderPresentPaymentMethodOptions` + ## 48.5.0-beta.2 - 2025-08-08 * [#3160](https://github.com/stripe/stripe-dotnet/pull/3160) Bring back invoice payments APIs that were missing in the public preview SDKs * Add support for new resource `InvoicePayment` diff --git a/README.md b/README.md index 202c501cfc..ba80daa5cd 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ how to use the library. ### Using StripeClient -In version 46 of the Stripe .NET SDK, we have enhanced the `StripeClient` class to be the entry point to access all services that had to be previously independently instantiated with global configuration. This improves discoverability during IDE auto-completion and creates a more intuitive developer experience for you. +In version 46 of the Stripe .NET SDK, we have enhanced the `StripeClient` class to be the entry point to access all services that had to be previously independently instantiated with global configuration. This improves discoverability during IDE auto-completion and creates a more intuitive developer experience for you. Each client instantiation can have its own configuration so you can access Stripe API with different API keys or different configuration (like number of retries) on a per client basis and without changing a global configuration. @@ -335,7 +335,7 @@ The [RawJObject property](#properties) is ignored on serialization in both Json. Stripe has features in the [public preview phase](https://docs.stripe.com/release-phases) that can be accessed via versions of this package that have the `-beta.X` suffix like `45.1.0-beta.2`. We would love for you to try these as we incrementally release new features and improve them based on your feedback. -To install, choose the version that includes support for the preview feature you are interested in by reviewing the [releases page](https://github.com/stripe/stripe-dotnet/releases/) and then use it in the version parameter with `dotnet add package` command: +To install, pick the latest version with the `beta` suffix by reviewing the [releases page](https://github.com/stripe/stripe-dotnet/releases/) and then use it in the version parameter with `dotnet add package` command: ``` dotnet add package Stripe.net --version @@ -349,6 +349,9 @@ Some preview features require a name and version to be set in the `Stripe-Versio ```csharp StripeConfiguration.AddBetaVersion("feature_beta", "v3"); ``` +### Private Preview SDKs + +Stripe has features in the [private preview phase](https://docs.stripe.com/release-phases) that can be accessed via versions of this package that have the `-alpha.X` suffix like `45.2.0-alpha.2`. These are invite-only features. Once invited, you can install the private preview SDKs by following the same instructions as for the [public preview SDKs](https://github.com/stripe/stripe-dotnet?tab=readme-ov-file#public-preview-sdks) above and replacing the term `beta` with `alpha`. ### Custom requests diff --git a/justfile b/justfile index 871aa51e5a..b891bed6de 100644 --- a/justfile +++ b/justfile @@ -20,7 +20,7 @@ ci-test: (_test "--no-build" "" "Release") # ⭐ format all files format *args: # This sets TargetFramework because of a race condition in dotnet format when it tries to format to multiple targets at a time, which could lead to code with compiler errors after it completes - TargetFramework=net5.0 dotnet format src/Stripe.net/Stripe.net.csproj --severity warn {{args}} + TargetFramework=net5.0 dotnet format src/Stripe.net.sln --severity warn {{args}} # verify, but don't modify, the project's formatting format-check: (format "--verify-no-changes") diff --git a/src/Examples/Program.cs b/src/Examples/Program.cs index 4d0ac5f52d..74514af254 100644 --- a/src/Examples/Program.cs +++ b/src/Examples/Program.cs @@ -27,7 +27,7 @@ public Program() /// are set before running the example. /// /// - /// command line args + /// command line args. /// public static async Task Main(string[] args) { diff --git a/src/Examples/V2/ThinEventWebhookHandler.cs b/src/Examples/V2/ThinEventWebhookHandler.cs index dd4e53f889..dbec0d14dc 100644 --- a/src/Examples/V2/ThinEventWebhookHandler.cs +++ b/src/Examples/V2/ThinEventWebhookHandler.cs @@ -22,15 +22,15 @@ namespace Examples.V2 [ApiController] public class ThinEventWebhookHandler : ControllerBase { - private readonly StripeClient _client; - private readonly string _webhookSecret; + private readonly StripeClient client; + private readonly string webhookSecret; public ThinEventWebhookHandler() { var apiKey = Environment.GetEnvironmentVariable("STRIPE_API_KEY"); - _client = new StripeClient(apiKey); + client = new StripeClient(apiKey); - _webhookSecret = Environment.GetEnvironmentVariable("WEBHOOK_SECRET"); + webhookSecret = Environment.GetEnvironmentVariable("WEBHOOK_SECRET"); } [HttpPost] @@ -39,10 +39,10 @@ public async Task Index() var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); try { - var thinEvent = _client.ParseThinEvent(json, Request.Headers["Stripe-Signature"], _webhookSecret); + var thinEvent = client.ParseThinEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); // Fetch the event data to understand the failure - var baseEvent = await _client.V2.Core.Events.GetAsync(thinEvent.Id); + var baseEvent = await client.V2.Core.Events.GetAsync(thinEvent.Id); if (baseEvent is V1BillingMeterErrorReportTriggeredEvent fullEvent) { var meter = await fullEvent.FetchRelatedObjectAsync(); diff --git a/src/Stripe.net/Entities/PaymentIntents/PaymentIntentNextAction.cs b/src/Stripe.net/Entities/PaymentIntents/PaymentIntentNextAction.cs index a645089ed7..5478c4dd6c 100644 --- a/src/Stripe.net/Entities/PaymentIntents/PaymentIntentNextAction.cs +++ b/src/Stripe.net/Entities/PaymentIntents/PaymentIntentNextAction.cs @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec namespace Stripe { + using System.Collections.Generic; using Newtonsoft.Json; #if NET6_0_OR_GREATER using STJS = System.Text.Json.Serialization; @@ -107,7 +108,7 @@ public class PaymentIntentNextAction : StripeEntity #if NET6_0_OR_GREATER [STJS.JsonPropertyName("use_stripe_sdk")] #endif - public PaymentIntentNextActionUseStripeSdk UseStripeSdk { get; set; } + public Dictionary UseStripeSdk { get; set; } [JsonProperty("verify_with_microdeposits")] #if NET6_0_OR_GREATER diff --git a/src/Stripe.net/Entities/PaymentIntents/PaymentIntentNextActionUseStripeSdk.cs b/src/Stripe.net/Entities/PaymentIntents/PaymentIntentNextActionUseStripeSdk.cs deleted file mode 100644 index cdf002d2ad..0000000000 --- a/src/Stripe.net/Entities/PaymentIntents/PaymentIntentNextActionUseStripeSdk.cs +++ /dev/null @@ -1,7 +0,0 @@ -// File generated from our OpenAPI spec -namespace Stripe -{ - public class PaymentIntentNextActionUseStripeSdk : StripeEntity - { - } -} diff --git a/src/Stripe.net/Entities/SetupIntents/SetupIntentNextAction.cs b/src/Stripe.net/Entities/SetupIntents/SetupIntentNextAction.cs index dc6e4b5bfa..1ce3c34c16 100644 --- a/src/Stripe.net/Entities/SetupIntents/SetupIntentNextAction.cs +++ b/src/Stripe.net/Entities/SetupIntents/SetupIntentNextAction.cs @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec namespace Stripe { + using System.Collections.Generic; using Newtonsoft.Json; #if NET6_0_OR_GREATER using STJS = System.Text.Json.Serialization; @@ -47,7 +48,7 @@ public class SetupIntentNextAction : StripeEntity #if NET6_0_OR_GREATER [STJS.JsonPropertyName("use_stripe_sdk")] #endif - public SetupIntentNextActionUseStripeSdk UseStripeSdk { get; set; } + public Dictionary UseStripeSdk { get; set; } [JsonProperty("verify_with_microdeposits")] #if NET6_0_OR_GREATER diff --git a/src/Stripe.net/Entities/SetupIntents/SetupIntentNextActionUseStripeSdk.cs b/src/Stripe.net/Entities/SetupIntents/SetupIntentNextActionUseStripeSdk.cs deleted file mode 100644 index 71794eb783..0000000000 --- a/src/Stripe.net/Entities/SetupIntents/SetupIntentNextActionUseStripeSdk.cs +++ /dev/null @@ -1,7 +0,0 @@ -// File generated from our OpenAPI spec -namespace Stripe -{ - public class SetupIntentNextActionUseStripeSdk : StripeEntity - { - } -} diff --git a/src/Stripe.net/Entities/V2/DeletedObject/DeletedObject.cs b/src/Stripe.net/Entities/V2/DeletedObject/DeletedObject.cs new file mode 100644 index 0000000000..3fca381bbc --- /dev/null +++ b/src/Stripe.net/Entities/V2/DeletedObject/DeletedObject.cs @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec +namespace Stripe.V2 +{ + using Newtonsoft.Json; +#if NET6_0_OR_GREATER + using STJS = System.Text.Json.Serialization; +#endif + + public class DeletedObject : StripeEntity, IHasId, IHasObject + { + /// + /// The ID of the object that's being deleted. + /// + [JsonProperty("id")] +#if NET6_0_OR_GREATER + [STJS.JsonPropertyName("id")] +#endif + public string Id { get; set; } + + /// + /// String representing the type of the object that has been deleted. Objects of the same + /// type share the same value of the object field. + /// + [JsonProperty("object")] +#if NET6_0_OR_GREATER + [STJS.JsonPropertyName("object")] +#endif + public string Object { get; set; } + } +} diff --git a/src/Stripe.net/Infrastructure/FormEncoding/ContentEncoder.cs b/src/Stripe.net/Infrastructure/FormEncoding/ContentEncoder.cs index aeb2453cc8..32733e638c 100644 --- a/src/Stripe.net/Infrastructure/FormEncoding/ContentEncoder.cs +++ b/src/Stripe.net/Infrastructure/FormEncoding/ContentEncoder.cs @@ -145,6 +145,10 @@ private static List> FlattenParamsValue(object valu flatParams = SingleParam(keyPrefix, s); break; + case MultipartFileContent f: + flatParams = SingleParam(keyPrefix, f); + break; + case Stream s: flatParams = SingleParam(keyPrefix, s); break; diff --git a/src/Stripe.net/Infrastructure/FormEncoding/FormEncoder.cs b/src/Stripe.net/Infrastructure/FormEncoding/FormEncoder.cs index 53b2441bae..2c9bca954d 100644 --- a/src/Stripe.net/Infrastructure/FormEncoding/FormEncoder.cs +++ b/src/Stripe.net/Infrastructure/FormEncoding/FormEncoder.cs @@ -116,6 +116,10 @@ private static List> FlattenParamsValue(object valu flatParams = SingleParam(keyPrefix, s); break; + case MultipartFileContent f: + flatParams = SingleParam(keyPrefix, f); + break; + case Stream s: flatParams = SingleParam(keyPrefix, s); break; diff --git a/src/Stripe.net/Infrastructure/FormEncoding/MultipartFormDataContent.cs b/src/Stripe.net/Infrastructure/FormEncoding/MultipartFormDataContent.cs index d7ff9b3427..4c2c46d290 100644 --- a/src/Stripe.net/Infrastructure/FormEncoding/MultipartFormDataContent.cs +++ b/src/Stripe.net/Infrastructure/FormEncoding/MultipartFormDataContent.cs @@ -41,26 +41,29 @@ public MultipartFormDataContent( private static StringContent CreateStringContent(string value) => new StringContent(value, System.Text.Encoding.UTF8); - private static StreamContent CreateStreamContent(Stream value, string name) + private static StreamContent CreateStreamContent(MultipartFileContent value, string name) { - var fileName = "blob"; - var extension = string.Empty; + var fileName = value.Name ?? "blob"; + var extension = Path.GetExtension(fileName); + var stream = value.Data; - FileStream fileStream = value as FileStream; + FileStream fileStream = stream as FileStream; if ((fileStream != null) && (!string.IsNullOrEmpty(fileStream.Name))) { fileName = fileStream.Name; extension = Path.GetExtension(fileName); } - var content = new StreamContent(value); + var type = value.Type ?? MimeTypes.GetMimeType(extension); + + var content = new StreamContent(stream); content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = name, FileName = fileName, FileNameStar = fileName, }; - content.Headers.ContentType = new MediaTypeHeaderValue(MimeTypes.GetMimeType(extension)); + content.Headers.ContentType = new MediaTypeHeaderValue(type); return content; } @@ -79,8 +82,16 @@ private void ProcessParameters(IEnumerable> nameVal this.Add(CreateStringContent(s), QuoteString(kvp.Key)); break; + case MultipartFileContent f: + this.Add(CreateStreamContent(f, QuoteString(kvp.Key))); + break; + case Stream s: - this.Add(CreateStreamContent(s, QuoteString(kvp.Key))); + var fileData = new MultipartFileContent + { + Data = s, + }; + this.Add(CreateStreamContent(fileData, QuoteString(kvp.Key))); break; default: diff --git a/src/Stripe.net/Infrastructure/Public/ApiRequestorAdapter.cs b/src/Stripe.net/Infrastructure/Public/ApiRequestorAdapter.cs index c2a366da5d..95751ea666 100644 --- a/src/Stripe.net/Infrastructure/Public/ApiRequestorAdapter.cs +++ b/src/Stripe.net/Infrastructure/Public/ApiRequestorAdapter.cs @@ -54,7 +54,7 @@ public override Task RequestAsync( if (baseAddress != BaseAddress.Api) { requestOptions ??= new RequestOptions(); - requestOptions.BaseUrl = this.GetBaseUrl(baseAddress); + requestOptions.InternalBaseUrl = this.GetBaseUrl(baseAddress); } return this.client.RequestAsync(method, path, options, requestOptions, cancellationToken); diff --git a/src/Stripe.net/Infrastructure/Public/LiveApiRequestor.cs b/src/Stripe.net/Infrastructure/Public/LiveApiRequestor.cs index 652b563171..e478935b8b 100644 --- a/src/Stripe.net/Infrastructure/Public/LiveApiRequestor.cs +++ b/src/Stripe.net/Infrastructure/Public/LiveApiRequestor.cs @@ -231,7 +231,7 @@ private StripeRequest MakeStripeRequest( } var uri = StripeRequest.BuildUri( - requestOptions?.BaseUrl ?? this.GetBaseUrl(baseAddress), + requestOptions?.InternalBaseUrl ?? this.GetBaseUrl(baseAddress), method, path, options, diff --git a/src/Stripe.net/Services/Files/FileCreateOptions.cs b/src/Stripe.net/Services/Files/FileCreateOptions.cs index a252e950b2..093dcefc53 100644 --- a/src/Stripe.net/Services/Files/FileCreateOptions.cs +++ b/src/Stripe.net/Services/Files/FileCreateOptions.cs @@ -1,7 +1,6 @@ // File generated from our OpenAPI spec namespace Stripe { - using System.IO; using Newtonsoft.Json; #if NET6_0_OR_GREATER using STJS = System.Text.Json.Serialization; @@ -17,7 +16,7 @@ public class FileCreateOptions : BaseOptions #if NET6_0_OR_GREATER [STJS.JsonPropertyName("file")] #endif - public Stream File { get; set; } + public MultipartFileContent File { get; set; } /// /// Optional parameters that automatically create a /// Delete an event destination. /// - public virtual V2.EventDestination Delete(string id, EventDestinationDeleteOptions options = null, RequestOptions requestOptions = null) + public virtual V2.DeletedObject Delete(string id, EventDestinationDeleteOptions options = null, RequestOptions requestOptions = null) { - return this.Request(BaseAddress.Api, HttpMethod.Delete, $"/v2/core/event_destinations/{WebUtility.UrlEncode(id)}", options, requestOptions); + return this.Request(BaseAddress.Api, HttpMethod.Delete, $"/v2/core/event_destinations/{WebUtility.UrlEncode(id)}", options, requestOptions); } /// /// Delete an event destination. /// - public virtual Task DeleteAsync(string id, EventDestinationDeleteOptions options = null, RequestOptions requestOptions = null, CancellationToken cancellationToken = default) + public virtual Task DeleteAsync(string id, EventDestinationDeleteOptions options = null, RequestOptions requestOptions = null, CancellationToken cancellationToken = default) { - return this.RequestAsync(BaseAddress.Api, HttpMethod.Delete, $"/v2/core/event_destinations/{WebUtility.UrlEncode(id)}", options, requestOptions, cancellationToken); + return this.RequestAsync(BaseAddress.Api, HttpMethod.Delete, $"/v2/core/event_destinations/{WebUtility.UrlEncode(id)}", options, requestOptions, cancellationToken); } /// diff --git a/src/Stripe.net/Services/V2/CoreService.cs b/src/Stripe.net/Services/V2/CoreService.cs index 0cc48a622c..0cc4c756e1 100644 --- a/src/Stripe.net/Services/V2/CoreService.cs +++ b/src/Stripe.net/Services/V2/CoreService.cs @@ -9,7 +9,6 @@ public class CoreService : Service { private V2.Core.AccountService accounts; private V2.Core.AccountLinkService accountLinks; - private V2.Core.EventService events; private V2.Core.EventDestinationService eventDestinations; private V2.Core.VaultService vault; @@ -29,9 +28,6 @@ internal CoreService(IStripeClient client) public virtual V2.Core.AccountLinkService AccountLinks => this.accountLinks ??= new V2.Core.AccountLinkService( this.Requestor); - public virtual V2.Core.EventService Events => this.events ??= new V2.Core.EventService( - this.Requestor); - public virtual V2.Core.EventDestinationService EventDestinations => this.eventDestinations ??= new V2.Core.EventDestinationService( this.Requestor); diff --git a/src/Stripe.net/Services/_common/MultipartFileContent.cs b/src/Stripe.net/Services/_common/MultipartFileContent.cs new file mode 100644 index 0000000000..17f46b4180 --- /dev/null +++ b/src/Stripe.net/Services/_common/MultipartFileContent.cs @@ -0,0 +1,31 @@ +namespace Stripe +{ + using System.IO; + + /// + /// Represents Data and optional Name and Type that will be encoded as multipart form + /// data. Used in e.g. FileService.Create. + /// + /// + public class MultipartFileContent + { + /// + /// The file data to send. If this is a FileStream, the SDK will infer + /// the name and type from the file name and extension. If this is not + /// a FileStream set Name and Type to configure the file upload. + /// + public Stream Data { get; set; } + + /// + /// The optional name to send with this file data. Uses the file name if omitted + /// and Data is a FileStream. + /// + public string Name { get; set; } + + /// + /// The optional mime type to use when sending file data. Uses the type that + /// matches the file extension from Name (or the file name from Data) if omitted. + /// + public string Type { get; set; } + } +} diff --git a/src/Stripe.net/Services/_common/RawRequestOptions.cs b/src/Stripe.net/Services/_common/RawRequestOptions.cs index 56d62af257..e10e88377b 100644 --- a/src/Stripe.net/Services/_common/RawRequestOptions.cs +++ b/src/Stripe.net/Services/_common/RawRequestOptions.cs @@ -4,6 +4,13 @@ namespace Stripe public class RawRequestOptions : RequestOptions { + /// Gets or sets the base URL for the raw request. + /// + /// Use this to send API calls to e.g. files.stripe.com or + /// a proxy address. + /// + public string BaseUrl { get => this.InternalBaseUrl; set => this.InternalBaseUrl = value; } + /// Gets or sets additional headers for the request. public Dictionary AdditionalHeaders { get; set; } = new Dictionary(); diff --git a/src/Stripe.net/Services/_common/RequestOptions.cs b/src/Stripe.net/Services/_common/RequestOptions.cs index dd8409cf54..6dbeb3f34e 100644 --- a/src/Stripe.net/Services/_common/RequestOptions.cs +++ b/src/Stripe.net/Services/_common/RequestOptions.cs @@ -27,13 +27,13 @@ public class RequestOptions /// Gets or sets the value or Stripe-Context request header. public string StripeContext { get; set; } - /// Gets or sets the base URL for the request. + /// Gets the base URL for the request. /// /// This is an internal property. It is set by services or individual request methods when /// they need to send a request to a non-standard destination, e.g. files.stripe.com /// for file creation requests or connect.stripe.com for OAuth requests. /// - internal string BaseUrl { get; set; } + internal string InternalBaseUrl { get; set; } /// Gets or sets the API version for the request. /// diff --git a/src/StripeTests/Entities/DeserializationTest.cs b/src/StripeTests/Entities/DeserializationTest.cs index 5a6f715a47..62d4dc381b 100644 --- a/src/StripeTests/Entities/DeserializationTest.cs +++ b/src/StripeTests/Entities/DeserializationTest.cs @@ -1,211 +1,211 @@ namespace StripeTests { - using System; - using System.Collections.Generic; - using System.Linq; - using Newtonsoft.Json; - using Stripe; - using Stripe.Infrastructure; - using Xunit; - - public class DeserializationTest : BaseStripeTest - { - [Fact] - public void TestStubWithIdDirect() + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + using Stripe; + using Stripe.Infrastructure; + using Xunit; + + public class DeserializationTest : BaseStripeTest { - string json = "{\"some_ref\":{\"id\":\"xyz\"}}"; - var entity = StripeEntity.FromJson(json); - Assert.NotNull(entity); - Assert.IsType(entity); - var id = entity.SomeRef.Id; - Assert.Equal("xyz", id); - } - - [Fact] - public void TestStubWithIdExpanded() - { - string json = "{\"some_expandable\":{\"id\":\"xyz\"}}"; - var entity = StripeEntity.FromJson(json); - Assert.NotNull(entity); - Assert.IsType(entity); - var id = entity.SomeExpandable.Id; - Assert.Equal("xyz", id); - } - - [Fact] - public void TestStubWithIdArrayExpanded() - { - string json = "{\"some_expanded_array\":[{\"id\":\"xyz\"}]}"; - var entity = StripeEntity.FromJson(json); - Assert.NotNull(entity); - Assert.IsType(entity); - var id = entity.SomeExpandedArray[0].Id; - Assert.Equal("xyz", id); - } - - [Fact] - public void TestStubWithIdInArray() - { - string json = "{\"some_ref_array\":[{\"id\":\"xyz\"}]}"; - var entity = StripeEntity.FromJson(json); - Assert.NotNull(entity); - Assert.IsType(entity); - var id = entity.SomeRefArray[0].Id; - Assert.Equal("xyz", id); - } - - [Fact] - public void TestStubWithIdInListObject() - { - string json = "{\"some_list_object\":{\"data\":[{\"id\":\"xyz\"}]}}"; - var entity = StripeEntity.FromJson(json); - Assert.NotNull(entity); - Assert.IsType(entity); - var enumerator = entity.SomeListObject.GetEnumerator(); - enumerator.MoveNext(); - var id = enumerator.Current.Id; - Assert.Equal("xyz", id); - } - - [Fact] - public void TestEmptyObjectDirect() - { - string json = "{\"some_ref\":{}}"; - var entity = JsonConvert.DeserializeObject(json); - var id = entity.SomeRef.Id; - Assert.Null(id); - } - - [Fact] - public void TestEmptyObjectArray() - { - string json = "{\"some_ref_array\":[{}]}"; - var entity = JsonConvert.DeserializeObject(json); - var id = entity.SomeRefArray[0].Id; - Assert.Null(id); - } - - [Fact] - public void TestEmptyObjectExpanded() - { - string json = "{\"some_expandable\":{}}"; - var entity = JsonConvert.DeserializeObject(json); - var id = entity.SomeExpandable.Id; - Assert.Null(id); - } - - [Fact] - public void TestEmptyObjectArrayExpanded() - { - string json = "{\"some_expanded_array\":[{}]}"; - var entity = JsonConvert.DeserializeObject(json); - var id = entity.SomeExpandedArray[0].Id; - Assert.Null(id); - } - - public class MyEntity : StripeEntity, IHasId - { - [JsonProperty("id")] - public string Id { get; set; } - - [JsonProperty("some_integer")] - public long SomeInteger { get; set; } - - [JsonProperty("some_longinteger")] - public long SomeLonginteger { get; set; } - - [JsonProperty("some_boolean")] - public bool SomeBoolean { get; set; } - - [JsonProperty("some_number")] - public decimal SomeNumber { get; set; } - - [JsonProperty("some_decimal_string")] - public decimal SomeDecimalString { get; set; } - - [JsonProperty("some_string")] - public string SomeString { get; set; } - - [JsonProperty("some_datetime")] - [JsonConverter(typeof(UnixDateTimeConverter))] - public DateTime SomeDatetime { get; set; } = Stripe.Infrastructure.DateTimeUtils.UnixEpoch; - - [JsonProperty("some_ref")] - public MyEntity SomeRef { get; set; } - - [JsonProperty("some_literal")] - public string SomeLiteral { get; set; } - - [JsonProperty("some_nullable")] - public string SomeNullable { get; set; } - - [JsonProperty("some_string_array")] - public List SomeStringArray { get; set; } - - [JsonProperty("some_ref_array")] - public List SomeRefArray { get; set; } + [Fact] + public void TestStubWithIdDirect() + { + string json = "{\"some_ref\":{\"id\":\"xyz\"}}"; + var entity = StripeEntity.FromJson(json); + Assert.NotNull(entity); + Assert.IsType(entity); + var id = entity.SomeRef.Id; + Assert.Equal("xyz", id); + } + + [Fact] + public void TestStubWithIdExpanded() + { + string json = "{\"some_expandable\":{\"id\":\"xyz\"}}"; + var entity = StripeEntity.FromJson(json); + Assert.NotNull(entity); + Assert.IsType(entity); + var id = entity.SomeExpandable.Id; + Assert.Equal("xyz", id); + } + + [Fact] + public void TestStubWithIdArrayExpanded() + { + string json = "{\"some_expanded_array\":[{\"id\":\"xyz\"}]}"; + var entity = StripeEntity.FromJson(json); + Assert.NotNull(entity); + Assert.IsType(entity); + var id = entity.SomeExpandedArray[0].Id; + Assert.Equal("xyz", id); + } + + [Fact] + public void TestStubWithIdInArray() + { + string json = "{\"some_ref_array\":[{\"id\":\"xyz\"}]}"; + var entity = StripeEntity.FromJson(json); + Assert.NotNull(entity); + Assert.IsType(entity); + var id = entity.SomeRefArray[0].Id; + Assert.Equal("xyz", id); + } + + [Fact] + public void TestStubWithIdInListObject() + { + string json = "{\"some_list_object\":{\"data\":[{\"id\":\"xyz\"}]}}"; + var entity = StripeEntity.FromJson(json); + Assert.NotNull(entity); + Assert.IsType(entity); + var enumerator = entity.SomeListObject.GetEnumerator(); + enumerator.MoveNext(); + var id = enumerator.Current.Id; + Assert.Equal("xyz", id); + } + + [Fact] + public void TestEmptyObjectDirect() + { + string json = "{\"some_ref\":{}}"; + var entity = JsonConvert.DeserializeObject(json); + var id = entity.SomeRef.Id; + Assert.Null(id); + } + + [Fact] + public void TestEmptyObjectArray() + { + string json = "{\"some_ref_array\":[{}]}"; + var entity = JsonConvert.DeserializeObject(json); + var id = entity.SomeRefArray[0].Id; + Assert.Null(id); + } + + [Fact] + public void TestEmptyObjectExpanded() + { + string json = "{\"some_expandable\":{}}"; + var entity = JsonConvert.DeserializeObject(json); + var id = entity.SomeExpandable.Id; + Assert.Null(id); + } + + [Fact] + public void TestEmptyObjectArrayExpanded() + { + string json = "{\"some_expanded_array\":[{}]}"; + var entity = JsonConvert.DeserializeObject(json); + var id = entity.SomeExpandedArray[0].Id; + Assert.Null(id); + } + + public class MyEntity : StripeEntity, IHasId + { + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("some_integer")] + public long SomeInteger { get; set; } + + [JsonProperty("some_longinteger")] + public long SomeLonginteger { get; set; } + + [JsonProperty("some_boolean")] + public bool SomeBoolean { get; set; } + + [JsonProperty("some_number")] + public decimal SomeNumber { get; set; } + + [JsonProperty("some_decimal_string")] + public decimal SomeDecimalString { get; set; } + + [JsonProperty("some_string")] + public string SomeString { get; set; } + + [JsonProperty("some_datetime")] + [JsonConverter(typeof(UnixDateTimeConverter))] + public DateTime SomeDatetime { get; set; } = Stripe.Infrastructure.DateTimeUtils.UnixEpoch; + + [JsonProperty("some_ref")] + public MyEntity SomeRef { get; set; } + + [JsonProperty("some_literal")] + public string SomeLiteral { get; set; } + + [JsonProperty("some_nullable")] + public string SomeNullable { get; set; } + + [JsonProperty("some_string_array")] + public List SomeStringArray { get; set; } + + [JsonProperty("some_ref_array")] + public List SomeRefArray { get; set; } + + #region Expandable SomeExpandedArray + + [JsonIgnore] + public List SomeExpandedArrayIds + { + get => this.InternalSomeExpandedArray?.Select((x) => x.Id).ToList(); + set => this.InternalSomeExpandedArray = SetExpandableArrayIds(value); + } + + [JsonIgnore] + public List SomeExpandedArray + { + get => this.InternalSomeExpandedArray?.Select((x) => x.ExpandedObject).ToList(); + set => this.InternalSomeExpandedArray = SetExpandableArrayObjects(value); + } + + [JsonProperty("some_expanded_array", ItemConverterType = typeof(ExpandableFieldConverter))] + internal List> InternalSomeExpandedArray { get; set; } + #endregion + + [JsonProperty("some_enum")] + public string SomeEnum { get; set; } + + [JsonProperty("some_map")] + public Dictionary SomeMap { get; set; } + + [JsonProperty("some_object")] + public MyEntitySomeObject SomeObject { get; set; } + + [JsonProperty("some_list_object")] + public StripeList SomeListObject { get; set; } + + #region Expandable SomeExpandable + + [JsonIgnore] + public string SomeExpandableId + { + get => this.InternalSomeExpandable?.Id; + set => this.InternalSomeExpandable = SetExpandableFieldId(value, this.InternalSomeExpandable); + } + + [JsonIgnore] + public MyEntity SomeExpandable + { + get => this.InternalSomeExpandable?.ExpandedObject; + set => this.InternalSomeExpandable = SetExpandableFieldObject(value, this.InternalSomeExpandable); + } - #region Expandable SomeExpandedArray + [JsonProperty("some_expandable")] + [JsonConverter(typeof(ExpandableFieldConverter))] + internal ExpandableField InternalSomeExpandable { get; set; } + #endregion - [JsonIgnore] - public List SomeExpandedArrayIds - { - get => this.InternalSomeExpandedArray?.Select((x) => x.Id).ToList(); - set => this.InternalSomeExpandedArray = SetExpandableArrayIds(value); - } + [JsonProperty("some_polymorphic_group")] + public MyEntity SomePolymorphicGroup { get; set; } + } - [JsonIgnore] - public List SomeExpandedArray - { - get => this.InternalSomeExpandedArray?.Select((x) => x.ExpandedObject).ToList(); - set => this.InternalSomeExpandedArray = SetExpandableArrayObjects(value); - } - - [JsonProperty("some_expanded_array", ItemConverterType = typeof(ExpandableFieldConverter))] - internal List> InternalSomeExpandedArray { get; set; } - #endregion - - [JsonProperty("some_enum")] - public string SomeEnum { get; set; } - - [JsonProperty("some_map")] - public Dictionary SomeMap { get; set; } - - [JsonProperty("some_object")] - public MyEntitySomeObject SomeObject { get; set; } - - [JsonProperty("some_list_object")] - public StripeList SomeListObject { get; set; } - - #region Expandable SomeExpandable - - [JsonIgnore] - public string SomeExpandableId - { - get => this.InternalSomeExpandable?.Id; - set => this.InternalSomeExpandable = SetExpandableFieldId(value, this.InternalSomeExpandable); - } - - [JsonIgnore] - public MyEntity SomeExpandable - { - get => this.InternalSomeExpandable?.ExpandedObject; - set => this.InternalSomeExpandable = SetExpandableFieldObject(value, this.InternalSomeExpandable); - } - - [JsonProperty("some_expandable")] - [JsonConverter(typeof(ExpandableFieldConverter))] - internal ExpandableField InternalSomeExpandable { get; set; } - #endregion - - [JsonProperty("some_polymorphic_group")] - public MyEntity SomePolymorphicGroup { get; set; } - } - - public class MyEntitySomeObject : StripeEntity - { - [JsonProperty("some_string")] - public string SomeString { get; set; } + public class MyEntitySomeObject : StripeEntity + { + [JsonProperty("some_string")] + public string SomeString { get; set; } + } } - } } diff --git a/src/StripeTests/Infrastructure/FormEncoding/MultipartFormDataContentTest.cs b/src/StripeTests/Infrastructure/FormEncoding/MultipartFormDataContentTest.cs index 30f2bf6c40..fcaa77faad 100644 --- a/src/StripeTests/Infrastructure/FormEncoding/MultipartFormDataContentTest.cs +++ b/src/StripeTests/Infrastructure/FormEncoding/MultipartFormDataContentTest.cs @@ -5,6 +5,7 @@ namespace StripeTests using System.IO; using System.Text; using System.Threading.Tasks; + using Stripe; using Stripe.Infrastructure.FormEncoding; using Xunit; @@ -71,6 +72,132 @@ public async Task Ctor_OneStreamEntry_Success() result); } + [Fact] + public async Task Ctor_OneMultipartFileContentEntry_Success() + { + var source = new Dictionary + { + { "key", new MultipartFileContent { Data = new MemoryStream(Encoding.UTF8.GetBytes("Hello World!")) } }, + }; + var content = new MultipartFormDataContent(source, "test-boundary"); + + var stream = await content.ReadAsStreamAsync(); + Assert.Equal(174, stream.Length); + var result = new StreamReader(stream).ReadToEnd(); + Assert.Equal( + "--test-boundary\r\n" + + "Content-Disposition: form-data; name=\"key\"; filename=blob; filename*=utf-8''blob\r\n" + + "Content-Type: application/octet-stream\r\n\r\nHello World!\r\n" + + "--test-boundary--\r\n", + result); + } + + [Fact] + public async Task Ctor_OneMultipartFileContentWithNameEntry_Success() + { + var source = new Dictionary + { + { + "key", new MultipartFileContent + { + Data = new MemoryStream(Encoding.UTF8.GetBytes("Hello World!")), + Name = "file", + } + }, + }; + var content = new MultipartFormDataContent(source, "test-boundary"); + + var stream = await content.ReadAsStreamAsync(); + Assert.Equal(174, stream.Length); + var result = new StreamReader(stream).ReadToEnd(); + Assert.Equal( + "--test-boundary\r\n" + + "Content-Disposition: form-data; name=\"key\"; filename=file; filename*=utf-8''file\r\n" + + "Content-Type: application/octet-stream\r\n\r\nHello World!\r\n" + + "--test-boundary--\r\n", + result); + } + + [Fact] + public async Task Ctor_OneMultipartFileContentWithNameAndExtEntry_Success() + { + var source = new Dictionary + { + { + "key", new MultipartFileContent + { + Data = new MemoryStream(Encoding.UTF8.GetBytes("Hello World!")), + Name = "file.csv", + } + }, + }; + var content = new MultipartFormDataContent(source, "test-boundary"); + + var stream = await content.ReadAsStreamAsync(); + Assert.Equal(166, stream.Length); + var result = new StreamReader(stream).ReadToEnd(); + Assert.Equal( + "--test-boundary\r\n" + + "Content-Disposition: form-data; name=\"key\"; filename=file.csv; filename*=utf-8''file.csv\r\n" + + "Content-Type: text/csv\r\n\r\nHello World!\r\n" + + "--test-boundary--\r\n", + result); + } + + [Fact] + public async Task Ctor_OneMultipartFileContentWithNameAndTypeEntry_Success() + { + var source = new Dictionary + { + { + "key", new MultipartFileContent + { + Data = new MemoryStream(Encoding.UTF8.GetBytes("Hello World!")), + Name = "file", + Type = "application/json", + } + }, + }; + var content = new MultipartFormDataContent(source, "test-boundary"); + + var stream = await content.ReadAsStreamAsync(); + Assert.Equal(166, stream.Length); + var result = new StreamReader(stream).ReadToEnd(); + Assert.Equal( + "--test-boundary\r\n" + + "Content-Disposition: form-data; name=\"key\"; filename=file; filename*=utf-8''file\r\n" + + "Content-Type: application/json\r\n\r\nHello World!\r\n" + + "--test-boundary--\r\n", + result); + } + + [Fact] + public async Task Ctor_OneMultipartFileContentWithNameAndExtAndTypeEntry_Success() + { + var source = new Dictionary + { + { + "key", new MultipartFileContent + { + Data = new MemoryStream(Encoding.UTF8.GetBytes("Hello World!")), + Name = "file.json", + Type = "application/octet-stream", + } + }, + }; + var content = new MultipartFormDataContent(source, "test-boundary"); + + var stream = await content.ReadAsStreamAsync(); + Assert.Equal(184, stream.Length); + var result = new StreamReader(stream).ReadToEnd(); + Assert.Equal( + "--test-boundary\r\n" + + "Content-Disposition: form-data; name=\"key\"; filename=file.json; filename*=utf-8''file.json\r\n" + + "Content-Type: application/octet-stream\r\n\r\nHello World!\r\n" + + "--test-boundary--\r\n", + result); + } + [Fact] public async Task Ctor_TwoEntries_Success() { diff --git a/src/StripeTests/Infrastructure/Public/StripeClientTest.cs b/src/StripeTests/Infrastructure/Public/StripeClientTest.cs index 78df76c9ca..91a4d5e55d 100644 --- a/src/StripeTests/Infrastructure/Public/StripeClientTest.cs +++ b/src/StripeTests/Infrastructure/Public/StripeClientTest.cs @@ -164,6 +164,42 @@ public async Task RawRequestAsync_Json() Assert.Equal("mes_123", obj.Id); } + [Fact] + public async Task RawRequest_BaseUrl() + { + // Stub a request as stripe-mock does not support v2 + this.MockHttpClientFixture.StubRequest( + HttpMethod.Post, + "/v2/billing/meter_event_session", + System.Net.HttpStatusCode.OK, + "{\"id\": \"mes_123\",\"object\":\"v2.billing.meter_event_session\"}"); + + var expectedBaseUrl = "https://test.stripetest.com"; + var rawResponse = await this.stripeClient.RawRequestAsync( + HttpMethod.Post, + "/v2/billing/meter_event_session", + "{}", + new RawRequestOptions + { + BaseUrl = expectedBaseUrl, + AdditionalHeaders = + { + { "foo", "bar" }, + }, + }); + + this.MockHttpClientFixture.MockHandler.Protected() + .Verify( + "SendAsync", + Times.Once(), + ItExpr.Is(m => + new Uri(expectedBaseUrl).Host == (string)m.Properties["OriginalHost"]), + ItExpr.IsAny()); + + var obj = this.stripeClient.Deserialize(rawResponse.Content); + Assert.Equal("mes_123", obj.Id); + } + [Fact] public async Task RawRequestAsyncIncludesCorrectUsage() { diff --git a/src/StripeTests/Services/Files/FileServiceTest.cs b/src/StripeTests/Services/Files/FileServiceTest.cs index 9a0bd84032..bdf88084cd 100644 --- a/src/StripeTests/Services/Files/FileServiceTest.cs +++ b/src/StripeTests/Services/Files/FileServiceTest.cs @@ -28,9 +28,13 @@ public FileServiceTest( { this.service = new FileService(this.StripeClient); + var resourceStream = typeof(FileServiceTest).GetTypeInfo().Assembly.GetManifestResourceStream(FileName); this.createOptions = new FileCreateOptions { - File = typeof(FileServiceTest).GetTypeInfo().Assembly.GetManifestResourceStream(FileName), + File = new MultipartFileContent + { + Data = resourceStream, + }, FileLinkData = new FileFileLinkDataOptions { Create = true, @@ -44,7 +48,10 @@ public FileServiceTest( this.base64Options = new FileCreateOptions { - File = new MemoryStream(Convert.FromBase64String("c3RyaXBlLWRvdG5ldA==")), + File = new MultipartFileContent + { + Data = new MemoryStream(Convert.FromBase64String("c3RyaXBlLWRvdG5ldA==")), + }, Purpose = FilePurpose.BusinessLogo, }; diff --git a/src/StripeTests/Services/GeneratedExamplesTest.cs b/src/StripeTests/Services/GeneratedExamplesTest.cs index 25757387ce..5ed89c34e1 100644 --- a/src/StripeTests/Services/GeneratedExamplesTest.cs +++ b/src/StripeTests/Services/GeneratedExamplesTest.cs @@ -1330,8 +1330,11 @@ public void TestFilesPost() var options = new FileCreateOptions { Purpose = "account_requirement", - File = new System.IO.MemoryStream( - System.Text.Encoding.UTF8.GetBytes("File contents")), + File = new Stripe.MultipartFileContent + { + Data = new System.IO.MemoryStream( + System.Text.Encoding.UTF8.GetBytes("File contents")), + }, }; var service = new FileService(this.StripeClient); File file = service.Create(options); @@ -3922,7 +3925,6 @@ public void TestSubscriptionSchedulesPost() Quantity = 1, }, }, - Iterations = 12, }, }, }; @@ -8015,6 +8017,144 @@ public void TestRecipientNotNotifiableError() "/v2/money_management/outbound_payments"); } + [Fact] + public void TestV2CoreEventDestinationGet() + { + this.StubRequest( + HttpMethod.Get, + "/v2/core/event_destinations", + (HttpStatusCode)200, + "{\"data\":[{\"id\":\"obj_123\",\"object\":\"v2.core.event_destination\",\"created\":\"1970-01-12T21:42:34.472Z\",\"description\":\"description\",\"enabled_events\":[\"enabled_events\"],\"event_payload\":\"thin\",\"livemode\":true,\"name\":\"name\",\"status\":\"disabled\",\"type\":\"amazon_eventbridge\",\"updated\":\"1970-01-03T17:07:10.277Z\"}],\"next_page_url\":null,\"previous_page_url\":null}"); + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.StripeList eventDestinations = service + .List(); + this.AssertRequest(HttpMethod.Get, "/v2/core/event_destinations"); + } + + [Fact] + public void TestV2CoreEventDestinationPost() + { + this.StubRequest( + HttpMethod.Post, + "/v2/core/event_destinations", + (HttpStatusCode)200, + "{\"id\":\"obj_123\",\"object\":\"v2.core.event_destination\",\"created\":\"1970-01-12T21:42:34.472Z\",\"description\":\"description\",\"enabled_events\":[\"enabled_events\"],\"event_payload\":\"thin\",\"livemode\":true,\"name\":\"name\",\"status\":\"disabled\",\"type\":\"amazon_eventbridge\",\"updated\":\"1970-01-03T17:07:10.277Z\"}"); + var options = new Stripe.V2.Core.EventDestinationCreateOptions + { + EnabledEvents = new List { "enabled_events" }, + EventPayload = "thin", + Name = "name", + Type = "amazon_eventbridge", + }; + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.EventDestination eventDestination = service.Create( + options); + this.AssertRequest(HttpMethod.Post, "/v2/core/event_destinations"); + } + + [Fact] + public void TestV2CoreEventDestinationDelete() + { + this.StubRequest( + HttpMethod.Delete, + "/v2/core/event_destinations/id_123", + (HttpStatusCode)200, + "{\"id\":\"abc_123\",\"object\":\"some.object.tag\"}"); + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.DeletedObject deleted = service.Delete("id_123"); + this.AssertRequest( + HttpMethod.Delete, + "/v2/core/event_destinations/id_123"); + } + + [Fact] + public void TestV2CoreEventDestinationGet2() + { + this.StubRequest( + HttpMethod.Get, + "/v2/core/event_destinations/id_123", + (HttpStatusCode)200, + "{\"id\":\"obj_123\",\"object\":\"v2.core.event_destination\",\"created\":\"1970-01-12T21:42:34.472Z\",\"description\":\"description\",\"enabled_events\":[\"enabled_events\"],\"event_payload\":\"thin\",\"livemode\":true,\"name\":\"name\",\"status\":\"disabled\",\"type\":\"amazon_eventbridge\",\"updated\":\"1970-01-03T17:07:10.277Z\"}"); + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.EventDestination eventDestination = service.Get("id_123"); + this.AssertRequest( + HttpMethod.Get, + "/v2/core/event_destinations/id_123"); + } + + [Fact] + public void TestV2CoreEventDestinationPost2() + { + this.StubRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123", + (HttpStatusCode)200, + "{\"id\":\"obj_123\",\"object\":\"v2.core.event_destination\",\"created\":\"1970-01-12T21:42:34.472Z\",\"description\":\"description\",\"enabled_events\":[\"enabled_events\"],\"event_payload\":\"thin\",\"livemode\":true,\"name\":\"name\",\"status\":\"disabled\",\"type\":\"amazon_eventbridge\",\"updated\":\"1970-01-03T17:07:10.277Z\"}"); + var options = new Stripe.V2.Core.EventDestinationUpdateOptions(); + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.EventDestination eventDestination = service.Update( + "id_123", + options); + this.AssertRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123"); + } + + [Fact] + public void TestV2CoreEventDestinationPost3() + { + this.StubRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123/disable", + (HttpStatusCode)200, + "{\"id\":\"obj_123\",\"object\":\"v2.core.event_destination\",\"created\":\"1970-01-12T21:42:34.472Z\",\"description\":\"description\",\"enabled_events\":[\"enabled_events\"],\"event_payload\":\"thin\",\"livemode\":true,\"name\":\"name\",\"status\":\"disabled\",\"type\":\"amazon_eventbridge\",\"updated\":\"1970-01-03T17:07:10.277Z\"}"); + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.EventDestination eventDestination = service.Disable( + "id_123"); + this.AssertRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123/disable"); + } + + [Fact] + public void TestV2CoreEventDestinationPost4() + { + this.StubRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123/enable", + (HttpStatusCode)200, + "{\"id\":\"obj_123\",\"object\":\"v2.core.event_destination\",\"created\":\"1970-01-12T21:42:34.472Z\",\"description\":\"description\",\"enabled_events\":[\"enabled_events\"],\"event_payload\":\"thin\",\"livemode\":true,\"name\":\"name\",\"status\":\"disabled\",\"type\":\"amazon_eventbridge\",\"updated\":\"1970-01-03T17:07:10.277Z\"}"); + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.EventDestination eventDestination = service.Enable( + "id_123"); + this.AssertRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123/enable"); + } + + [Fact] + public void TestV2CoreEventDestinationPost5() + { + this.StubRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123/ping", + (HttpStatusCode)200, + "{\"id\":\"obj_123\",\"object\":\"v2.core.event\",\"created\":\"1970-01-12T21:42:34.472Z\",\"livemode\":true,\"type\":\"type\"}"); + var client = new StripeClient(this.Requestor); + var service = client.V2.Core.EventDestinations; + Stripe.V2.Event result = service.Ping("id_123"); + this.AssertRequest( + HttpMethod.Post, + "/v2/core/event_destinations/id_123/ping"); + } + [Fact] public void TestTemporarySessionExpiredError() { @@ -8026,9 +8166,9 @@ public void TestTemporarySessionExpiredError() var exception = Assert.Throws( () => { - var options = new Stripe.V2.Billing.MeterEventStreamCreateOptions - { - Events = new List + var options = new Stripe.V2.Billing.MeterEventStreamCreateOptions + { + Events = new List { new Stripe.V2.Billing.MeterEventStreamCreateEventOptions { @@ -8039,10 +8179,10 @@ public void TestTemporarySessionExpiredError() }, }, }, - }; - var client = new StripeClient(this.Requestor); - var service = client.V2.Billing.MeterEventStream; - service.Create(options); + }; + var client = new StripeClient(this.Requestor); + var service = client.V2.Billing.MeterEventStream; + service.Create(options); }); this.AssertRequest( HttpMethod.Post,