Extension configuration page
This documentation describes the main points of extension configuration and shows how to add configuration page for your extension in Sana Admin.
How to add configuration to extension
1. Create class that will describe configuration
Note
More details of configuration declaration you can find in 'Configuration class' chapter.
Important
Configuration class must be inherited from ExtensionConfiguration
class.
[ConfigurationKey("Dibs")]
public class DibsConfiguration : ExtensionConfiguration
{
[Display(Name = "Integration mode")]
public PaymentIntegrationMode IntegrationMode { get; set; }
[Required]
[Display(Name = "Merchant ID", Description = "This ID can be found in the DIBS admin panel.")]
[SecureString]
public string Merchant { get; set; }
[Required]
[Display(Name = "MD5 key 1")]
[SecureString]
public string Md5Key1 { get; set; }
[Required]
[Display(Name = "MD5 key 2", Description = "The values for these keys can be generated in the DIBS admin panel.")]
[SecureString]
public string Md5Key2 { get; set; }
[Required]
[Display(Name = "Enabled payment types", Description = "Use the ',' character to separate several payment types.")]
[AdditionalInfoUrl("http://tech.dibspayment.com/D2/Toolbox/Paytypes")]
public string EnabledPayTypes { get; set; }
[Display(Name = "Capture immediately", Description = "If checked, then the funds will be transferred from the customer's account immediately; otherwise all payments have to be captured manually from the DIBS administration.")]
public bool CaptureImmediately { get; set; } = true;
}
2. Attach configuration class to your extension
To attach configuration to your extension you should implement the IConfigurable<TConfiguration>
interface in your extension.
public class DibsPaymentExtension : PaymentExtension, IConfigurable<DibsConfiguration>
{
public DibsConfiguration Configuration { get; set; }
// Other code
}
3. Check new configuration in Sana Admin
When you rebuild your extension new configuration should be available in Sana Admin.
Note
You can find page with extensions by next path: Tools => Extension packages
4. Use configuration parameter(s)
Properties of the configuration class will be automatically filled in with values that were set in the Sana Admin so you can use it directly in extension.
protected virtual IDictionary<string, string> GetFormPostParameters(PaymentStartContext context)
{
var merchant = Configuration.Merchant;
// Other code
}
Same configuration for different extension
You can use single configuration for many extensions. You can do it by following the next steps:
1. Implement IConfigurable<TConfiguration>
in your shared context
Note
More details about shared context you can find in other documents.
public class AuthorizeNetContext : SharedContext, IConfigurable<AuthorizeNetConfiguration>
{
public AuthorizeNetConfiguration Configuration { get; set; }
}
2. Use configuration in extension
You can have access to configuration via Configuration
property of Context
.
public class AuthorizeNetPaymentExtension : PaymentExtension, IShareContext<AuthorizeNetContext>
{
public AuthorizeNetContext Context { get; set; }
protected virtual IDictionary<string, string> GetFormPostParameters(PaymentStartContext context)
{
var transactionKey = Context.Configuration.TransactionKey;
// Other code
}
}
Configuration class
Configuration key attribute
This attribute was added in Extension API version 1.1.0 with implementing upgrade extension data feature and allows developers to set custom configuration key.
Note
The value of this attribute needs to be unique in scope of extension package.
In previous version Sana used class name as unique key for an extension configuration. After implementation of this attribute you will be able to write upgrades for extension configuration without user data loss even when extension configuration class name has been changed.
Important
The ConfigurationKey
attribute is required for the newly developed add-ons but Sana still supports
configuration without this attribute as a backward compatibility for the already existing extension add-ons.
[ConfigurationKey("Dibs")]
public class DibsConfiguration : ExtensionConfiguration
{
// Code omitted for simplicity
}
Data annotation attributes
You can use attributes from System.ComponentModel.DataAnnotations
namespace for adding
validation or adding descriptions for configuration.
[ConfigurationKey("Dibs")]
public class DibsConfiguration : ExtensionConfiguration
{
[Required]
[Display(Name = "Merchant ID", Description = "This ID can be found in the DIBS admin panel.")]
public string Merchant { get; set; }
}
Sana attributes
Sana has own attributes that allow to describe or add additional behavior to properties in
configuration class. (For example: SecureStringAttribute
, AdditionalInfoUrlAttribute
)
Note
You can find all Sana attributes in next namespace:
Sana.ComponentModel
[ConfigurationKey("Dibs")]
public class DibsConfiguration : ExtensionConfiguration
{
[SecureString]
public string Md5Key2 { get; set; }
[AdditionalInfoUrl("http://tech.dibspayment.com/D2/Toolbox/Paytypes")]
public string EnabledPayTypes { get; set; }
}
Additional validation
You can override public virtual bool Test(out string message)
method for adding additional
validation.
[ConfigurationKey("Dibs")]
public class DibsConfiguration : ExtensionConfiguration
{
public override bool Test(out string message)
{
if (!Merchant.StartsWith("En"))
{
message = "Merchant must be started with 'En'.";
return false;
}
return base.Test(out message);
}
}
Configuration must be flat
You should use only standard types for properties in configuration. The properties with custom type are not supported.
Next configuration will not work correctly:
public class GeneralConfig
{
public string Merchant { get; set; }
}
[ConfigurationKey("Dibs")]
public class DibsConfiguration : ExtensionConfiguration
{
/// You cannot use own types for configuration properties.
public GeneralConfig Config { get; set; }
}
SecureStringAttribute
Indicates that the property contains sensitive data and the stored value should be encrypted.
Important
All properties with sensitive data must have this attribute.
Integration mode
Most of the payment service providers allow developers to test their applications before using it in production.
Sana Extensions framework provides extension developers with PaymentIntegrationMode
enum
which defines integration modes that extension developer can use in payment extension.
It is highly recommended to add property of PaymentIntegrationMode
type to configuration model
of your payment extension to have possibility to test payment extension before switching to
"Live" mode.
Let's imagine that our payment service provider has two payment pages:
- Test payment page - "https://test.payment.net/gateway/transact.dll"
- Live payment page - "https://live.payment.net/gateway/transact.dll"
Therefore, we can use following code to use integration modes:
string GetPaymentPageUrl(PaymentStartContext context)
{
if (Configuration.IntegrationMode == PaymentIntegrationMode.Test)
return "https://test.payment.net/gateway/transact.dll";
else
return "https://live.payment.net/gateway/transact.dll";
}
In such case, if you need to test payment extension you can select "Test" option of "Integration mode" setting in Sana Admin. All payments performed in this mode will be redirected to the test payment page of payment service provider.
When testing is completed you can simply switch "Integration mode" setting to "Live" and since that time all payments will be redirected to the real payment page of our payment service provider.
Upload files for extension configuration
If you want to add ability to upload file on configuration page you should create property with
string
type and [DataType(DataType.Upload)]
attribute.
[ConfigurationKey("Dibs")]
public class DibsConfiguration : ExtensionConfiguration
{
[Required]
[DataType(DataType.Upload)]
public string XmlFile { get; set; }
}
After that you can get access to this file via Api.DataFiles
API:
public class DibsPaymentExtension : PaymentExtension, IConfigurable<DibsConfiguration>
{
public DibsConfiguration Configuration { get; set; }
protected virtual IDictionary<string, string> GetFormPostParameters(PaymentStartContext context)
{
using (var stream = Api.DataFiles.OpenRead(Configuration.XmlFile))
{
if (stream == null || stream.Length <= 0)
throw new Exception("File not found.");
var doc = XDocument.Load(stream);
// Other code
}
}
}