Configuring Settings Per Payment Method
Payment service providers (PSPs) often support multiple payment methods, each requiring specific configuration parameters to function correctly. Sana provides extension developers with a robust framework to implement payment method-specific settings through the PaymentMethodSettings class. This guide demonstrates how to implement and manage payment method settings for your payment extensions.
This guide builds upon the Stripe payment extension created in the Implementing New Payment Service Provider tutorial. We'll extend it to support configurable payment methods.
Prerequisites
Before implementing payment method settings, ensure you have:
- A working payment extension (see Implementing New Payment Service Provider)
Required References
- PaymentExtension reference
- PaymentContext reference
- PaymentStartContext reference
- Extension Configuration
Create Payment Method Settings Class
Create a new class that inherits from PaymentMethodSettings. This class defines the configuration properties that administrators can set for each payment method instance.
using System.ComponentModel.DataAnnotations;
using Sana.Extensions.Payment;
namespace Sana.Extensions.CustomStripe
{
/// <summary>
/// Defines configurable settings for Stripe payment methods.
/// These settings appear in the Sana Admin payment method configuration page.
/// </summary>
public class CustomStripePaymentMethodSettings : PaymentMethodSettings
{
/// <summary>
/// Gets or sets the enabled payment methods for this configuration.
/// </summary>
[Display(Name = "Payment Methods",
Description = "Select the payment method type to enable for this configuration")]
[Required(ErrorMessage = "Please select a payment method")]
public PaymentMethods paymentMethods { get; set; }
/// <summary>
/// Enumeration of supported Stripe payment methods.
/// </summary>
public enum PaymentMethods
{
Card,
BanContact,
EPS,
P24,
other
}
}
}
Note
A class that inherits from PaymentMethodSettings acts as the view-model Sana renders on the payment-method configuration page in Sana Admin, so you can decorate its properties with DataAnnotations attributes and even supply custom editor templates.
Update Payment Extension Class
Modify your payment extension to use the generic type parameter with your settings class:
using Sana.Extensions.Cache;
using Sana.Extensions.Models.Orders;
using Sana.Extensions.Payment;
using Sana.Extensions.Payment.Contexts;
using System;
using System.Collections.Generic;
using System.Linq;
using Stripe;
using Stripe.Checkout;
namespace Sana.Extensions.CustomStripe
{
/// <summary>
/// Custom Stripe Payment Extension with configurable payment method settings.
/// </summary>
[PaymentModuleId("CustomStripePayment")]
public class CustomStripePaymentExtension: PaymentExtension<CustomStripePaymentMethodSettings>, IConfigurable<CustomStripeConfiguration>
{
public CustomStripeConfiguration Configuration { get; set; }
// Extension implementation continues...
}
}
After these steps we can see the following block with the "PaymentMethods" input on the payment method configuration page.
Note the generic type parameter <CustomStripePaymentMethodSettings> added to PaymentExtension.
Access Payment Method Settings
Within your payment extension methods, access the configured settings through the context parameter:
public override NextAction StartPayment(PaymentStartContext context)
{
try
{
// Validate the input context
if (context == null)
{
throw new ArgumentNullException(nameof(context), "Payment context cannot be null");
}
// Access payment method settings with type safety
var paymentMethodSettings = (CustomStripePaymentMethodSettings)context.MethodSettings;
// Retrieve the configured payment method
var selectedPaymentMethod = paymentMethodSettings.paymentMethods;
// Convert enum to Stripe-compatible string format
var stripePaymentMethod = ConvertToStripePaymentMethod(selectedPaymentMethod);
// Configure Stripe API
StripeConfiguration.ApiKey = Configuration.ApiKey;
// Create Stripe checkout session with the selected payment method
var options = new SessionCreateOptions
{
PaymentMethodTypes = new List<string> { stripePaymentMethod },
Mode = StripeConstants.CHECKOUT_MODE_PAYMENT,
SuccessUrl = context.SuccessUrl,
CancelUrl = context.CancelUrl,
LineItems = CreateLineItemsFromOrderLines(context)
};
var sessionService = new SessionService();
Session session = sessionService.Create(options);
// Continue with payment flow...
return NextAction.Redirect(session.Url);
}
catch (Exception ex)
{
// Log exception details for debugging
Api.LogError(ex, "Failed to start Stripe payment");
throw;
}
}
Implement Helper Method (ConvertToStripePaymentMethod)
Add helper methods to handle payment method conversions and validations:
/// <summary>
/// Converts the payment method enum to Stripe's expected format.
/// </summary>
/// <param name="paymentMethod">The configured payment method</param>
/// <returns>Stripe-compatible payment method string</returns>
private string ConvertToStripePaymentMethod(CustomStripePaymentMethodSettings.PaymentMethods paymentMethod)
{
switch (paymentMethod)
{
case CustomStripePaymentMethodSettings.PaymentMethods.Card:
return "card";
case CustomStripePaymentMethodSettings.PaymentMethods.BanContact:
return "bancontact";
case CustomStripePaymentMethodSettings.PaymentMethods.EPS:
return "eps";
case CustomStripePaymentMethodSettings.PaymentMethods.P24:
return "p24";
case CustomStripePaymentMethodSettings.PaymentMethods.other:
// For 'other', you might want to implement additional logic
// or configuration to specify the exact payment method
return "card"; // Default fallback
default:
throw new NotSupportedException($"Payment method {paymentMethod} is not supported");
}
}