diff --git a/justfile b/justfile
index 50a0dcbfe5..871aa51e5a 100644
--- a/justfile
+++ b/justfile
@@ -31,3 +31,7 @@ update-version version:
echo "{{ version }}" > VERSION
perl -pi -e 's|[.\-\d\w]+|{{ version }}|' src/Stripe.net/Stripe.net.csproj
perl -pi -e 's|Current = "[.\-\d\w]+";|Current = "{{ version }}";|' src/Stripe.net/Constants/Version.cs
+
+[working-directory("src/Examples/")]
+run-example example:
+ dotnet run --project Examples.csproj {{ example }}
diff --git a/src/Examples/ExampleTemplate.cs b/src/Examples/ExampleTemplate.cs
index aa38a0e08e..dd03bde9c1 100644
--- a/src/Examples/ExampleTemplate.cs
+++ b/src/Examples/ExampleTemplate.cs
@@ -2,6 +2,7 @@ namespace Examples
{
using System;
using System.Threading.Tasks;
+ using Stripe;
///
///
@@ -21,14 +22,12 @@ public class ExampleTemplate
{
public static async Task Run()
{
- var apiKey = "{{API_KEY}}";
+ var apiKey = Environment.GetEnvironmentVariable("STRIPE_API_KEY");
try
{
- Console.WriteLine("Hello World");
-
- // var client = new StripeClient(apiKey);
- // client.V1...
+ var client = new StripeClient(apiKey);
+ Console.WriteLine(await client.V1.Customers.ListAsync());
}
catch (Exception ex)
{
diff --git a/src/Examples/Program.cs b/src/Examples/Program.cs
index 31579e23ce..4d0ac5f52d 100644
--- a/src/Examples/Program.cs
+++ b/src/Examples/Program.cs
@@ -1,6 +1,7 @@
namespace Examples
{
using System;
+ using System.Reflection;
using System.Threading.Tasks;
public class Program
@@ -9,14 +10,62 @@ public Program()
{
}
+ ///
+ /// To create an example, clone ExampleTemplate.cs, implement the example
+ /// copy this line and replace the class name with your new class.
+ ///
+ /// To run an example from this folder, execute:
+ /// dotnet run --project Examples.csproj NameOfExample
+ ///
+ /// The name of the example should include any namespace parts other than "Examples"
+ /// which is prepended when looking up the type, for example"
+ /// dotnet run --project Examples.csproj
+ /// or
+ /// dotnet run --project Examples.csproj .
+ ///
+ /// Examples accept configuration via environment variables, so ensure all environment vars
+ /// are set before running the example.
+ ///
+ ///
+ /// command line args
+ ///
public static async Task Main(string[] args)
{
- // To create an example, clone NewExample.cs, implement the example
- // copy this line and replace the class name with your new class.
- // await NewExample.Run();
- // e.g.
- // await MeterEventExample.Run();
- // then build the project and run bin/Debug/net8.0/Examples
+ if (args.Length != 1)
+ {
+ Console.WriteLine("Usage: dotnet run --project Examples ");
+ Environment.Exit(1);
+ return;
+ }
+
+ var type = Assembly.GetExecutingAssembly().GetType($"Examples.{args[0]}");
+
+ if (type == null)
+ {
+ Console.WriteLine($"Unable to find example class {args[0]}");
+ Environment.Exit(1);
+ return;
+ }
+
+ var runMethod = type.GetMethod(
+ "Run",
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
+ if (runMethod == null)
+ {
+ Console.WriteLine($"Example class {args[0]} is missing Run method");
+ Environment.Exit(1);
+ return;
+ }
+
+ Task? result = (Task?)runMethod.Invoke(null, null);
+ if (result == null)
+ {
+ Console.WriteLine($"Unable to invoke Run method on {args[0]}");
+ Environment.Exit(1);
+ return;
+ }
+
+ await result;
}
}
}
diff --git a/src/Examples/V2/MeterEventStream.cs b/src/Examples/V2/MeterEventStream.cs
index 4949e92671..85154b8ed8 100644
--- a/src/Examples/V2/MeterEventStream.cs
+++ b/src/Examples/V2/MeterEventStream.cs
@@ -1,68 +1,70 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Stripe;
-using Stripe.V2.Billing;
-
-///
-/// Use the high-throughput MeterEventStream to report create billing meter events.
-///
-/// In this example, we:
-/// - create a meter event session and store the session's authentication token
-/// - define an event with a payload
-/// - use the meterEventStream service to create an event stream that reports this event
-///
-/// This example expects a billing meter with an event_name of 'alpaca_ai_tokens'. If you have
-/// a different meter event name, you can change it before running this example.
-///
-public class MeterEventStream
+namespace Examples.V2
{
- private static MeterEventSession? meterEventSession;
+ using System;
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using Stripe;
+ using Stripe.V2.Billing;
- public static async Task Run()
+ ///
+ /// Use the high-throughput MeterEventStream to report create billing meter events.
+ ///
+ /// In this example, we:
+ /// - create a meter event session and store the session's authentication token
+ /// - define an event with a payload
+ /// - use the meterEventStream service to create an event stream that reports this event
+ ///
+ /// This example expects a billing meter with an event_name of 'alpaca_ai_tokens'. If you have
+ /// a different meter event name, you can change it before running this example.
+ ///
+ public class MeterEventStream
{
- var apiKey = "{{API_KEY}}";
- var customerId = "{{CUSTOMER_ID}}"; // Replace with actual customer ID
+ private static MeterEventSession? meterEventSession;
- try
- {
- await SendMeterEvent(apiKey, "alpaca_ai_tokens", customerId, "25");
- Console.WriteLine("Meter event sent successfully!");
- }
- catch (Exception ex)
+ public static async Task Run()
{
- Console.WriteLine($"Error sending meter event: {ex.Message}");
- }
- }
+ var apiKey = Environment.GetEnvironmentVariable("STRIPE_API_KEY");
+ var customerId = Environment.GetEnvironmentVariable("CUSTOMER_ID");
- private static async Task RefreshMeterEventSession(string apiKey)
- {
- // Check if session is null or expired
- if (meterEventSession == null || meterEventSession.ExpiresAt <= DateTime.UtcNow)
- {
- // Create a new meter event session in case the existing session expired
- var client = new StripeClient(apiKey);
- meterEventSession = await client.V2.Billing.MeterEventSession.CreateAsync(new MeterEventSessionCreateOptions());
+ try
+ {
+ await SendMeterEvent(apiKey, "alpaca_ai_tokens", customerId, "25");
+ Console.WriteLine("Meter event sent successfully!");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error sending meter event: {ex.Message}");
+ }
}
- }
-
- private static async Task SendMeterEvent(string apiKey, string eventName, string stripeCustomerId, string value)
- {
- // Refresh the meter event session if necessary
- await RefreshMeterEventSession(apiKey);
- if (meterEventSession == null)
+ private static async Task RefreshMeterEventSession(string apiKey)
{
- throw new Exception("Unable to refresh meter event session");
+ // Check if session is null or expired
+ if (meterEventSession == null || meterEventSession.ExpiresAt <= DateTime.UtcNow)
+ {
+ // Create a new meter event session in case the existing session expired
+ var client = new StripeClient(apiKey);
+ meterEventSession = await client.V2.Billing.MeterEventSession.CreateAsync(new MeterEventSessionCreateOptions());
+ }
}
- // Create a meter event
- var client = new StripeClient(meterEventSession.AuthenticationToken);
- var options = new MeterEventStreamCreateOptions
+ private static async Task SendMeterEvent(string apiKey, string eventName, string stripeCustomerId, string value)
{
- Events =
- [
- new MeterEventStreamCreateEventOptions
+ // Refresh the meter event session if necessary
+ await RefreshMeterEventSession(apiKey);
+
+ if (meterEventSession == null)
+ {
+ throw new Exception("Unable to refresh meter event session");
+ }
+
+ // Create a meter event
+ var client = new StripeClient(meterEventSession.AuthenticationToken);
+ var options = new MeterEventStreamCreateOptions
+ {
+ Events =
+ [
+ new MeterEventStreamCreateEventOptions
{
EventName = eventName,
Payload = new Dictionary
@@ -72,7 +74,8 @@ private static async Task SendMeterEvent(string apiKey, string eventName, string
},
},
],
- };
- client.V2.Billing.MeterEventStream.Create(options);
+ };
+ client.V2.Billing.MeterEventStream.Create(options);
+ }
}
}
diff --git a/src/Examples/V2/ThinEventWebhookHandler.cs b/src/Examples/V2/ThinEventWebhookHandler.cs
index bf717d287a..dd4e53f889 100644
--- a/src/Examples/V2/ThinEventWebhookHandler.cs
+++ b/src/Examples/V2/ThinEventWebhookHandler.cs
@@ -1,60 +1,63 @@
-#pragma warning disable SA1101 // Prefix local calls with this
-
-using System;
-using System.IO;
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Stripe;
-using Stripe.Events;
-
-///
-/// Receive and process thin events like the v1.billing.meter.error_report_triggered event.
-///
-/// In this example, we:
-/// - use parseThinEvent to parse the received thin event webhook body
-/// - call StripeClient.v2.core.events.retrieve to retrieve the full event object
-/// - if it is a V1BillingMeterErrorReportTriggeredEvent event type, call fetchRelatedObject
-/// to retrieve the Billing Meter object associated with the event.
-///
-[Route("api/[controller]")]
-[ApiController]
-public class ThinEventWebhookHandler : ControllerBase
+namespace Examples.V2
{
- private readonly StripeClient _client;
- private readonly string _webhookSecret;
+#pragma warning disable SA1101 // Prefix local calls with this
- public ThinEventWebhookHandler()
+ using System;
+ using System.IO;
+ using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Mvc;
+ using Stripe;
+ using Stripe.Events;
+
+ ///
+ /// Receive and process thin events like the v1.billing.meter.error_report_triggered event.
+ ///
+ /// In this example, we:
+ /// - use parseThinEvent to parse the received thin event webhook body
+ /// - call StripeClient.v2.core.events.retrieve to retrieve the full event object
+ /// - if it is a V1BillingMeterErrorReportTriggeredEvent event type, call fetchRelatedObject
+ /// to retrieve the Billing Meter object associated with the event.
+ ///
+ [Route("api/[controller]")]
+ [ApiController]
+ public class ThinEventWebhookHandler : ControllerBase
{
- var apiKey = Environment.GetEnvironmentVariable("STRIPE_API_KEY");
- _client = new StripeClient(apiKey);
-
- _webhookSecret = Environment.GetEnvironmentVariable("WEBHOOK_SECRET");
- }
+ private readonly StripeClient _client;
+ private readonly string _webhookSecret;
- [HttpPost]
- public async Task Index()
- {
- var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
- try
+ public ThinEventWebhookHandler()
{
- var thinEvent = _client.ParseThinEvent(json, Request.Headers["Stripe-Signature"], _webhookSecret);
+ var apiKey = Environment.GetEnvironmentVariable("STRIPE_API_KEY");
+ _client = new StripeClient(apiKey);
+
+ _webhookSecret = Environment.GetEnvironmentVariable("WEBHOOK_SECRET");
+ }
- // Fetch the event data to understand the failure
- var baseEvent = await _client.V2.Core.Events.GetAsync(thinEvent.Id);
- if (baseEvent is V1BillingMeterErrorReportTriggeredEvent fullEvent)
+ [HttpPost]
+ public async Task Index()
+ {
+ var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
+ try
{
- var meter = await fullEvent.FetchRelatedObjectAsync();
- var meterId = meter.Id;
+ var thinEvent = _client.ParseThinEvent(json, Request.Headers["Stripe-Signature"], _webhookSecret);
- // Record the failures and alert your team
- // Add your logic here
- }
+ // Fetch the event data to understand the failure
+ var baseEvent = await _client.V2.Core.Events.GetAsync(thinEvent.Id);
+ if (baseEvent is V1BillingMeterErrorReportTriggeredEvent fullEvent)
+ {
+ var meter = await fullEvent.FetchRelatedObjectAsync();
+ var meterId = meter.Id;
- return Ok();
- }
- catch (StripeException e)
- {
- return BadRequest(e.Message);
+ // Record the failures and alert your team
+ // Add your logic here
+ }
+
+ return Ok();
+ }
+ catch (StripeException e)
+ {
+ return BadRequest(e.Message);
+ }
}
}
}