Sana Assistant (online)
Table of Contents

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

Extensions page Dibs Configuration page

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
        }
    }
}