How toGeneral

General

Create a Custom Internal Payment Module

The creation of an internal payment method is very easy. First you will need to create a new class that is the entry-point of the payment method. This class should inherit from the 'IPaymentModule' interface ('Sana.Commerce.Payment' namespace).
 
All you will have to do is override the pay method. That is all that is needed to create a payment method. The pay method will be called whenever the user starts a payment using this payment method. The payment method can be used by configuring it in the 'web.config'. See this chapter for more information. 
 
Adding Pipelines 
While we have created a custom payment module it does not do very much at this point as no code is defined in it. In a real life scenario this will not be very useful. There are a few actions that will be present in (almost) all payment modules. These are:
  • Setting the status of the order;
  • Deleting the current users basket;
  • Sending an order confirmation mail;
  • Deducting stock;
  • Sending the user to the order success page.
We could create custom code to accomplish these steps but since the code for these actions already exists this will be inefficient. These steps already exist as pipeline steps, we just have to add a pipeline to our payment module to easily re-use these steps and even add custom steps at any place in the pipeline.
 
It is easy to extend or add a pipeline. Follow these steps:
 
Create a list of steps to execute as a IPaymentStep[] or collection of steps, for example:
 
var steps = new IPaymentStep[]
{     
  new PayOrderStep(),                          //Set the order to paid
  new DeductStockStep(),                     //Deduct the stock for this order
  new DeleteBasketStep(),                     //Delete the basket 
  new SendOrderMailStep(),                  //Send to order confirmation mail 
  new RedirectToSuccessPageStep()   //Redirect the user
};
  • Create a new pipeline; specify the name of the pipeline, the steps that need to be executed and whenever the order supplied to the pipeline must be saved after the pipeline is finished executing (default 'true'). This can be done in the following way:
PaymentPipeline pipeline = new PaymentPipeline("Pipeline",steps,true);
  • Setup the payment context; we always need to pass this context to the pipeline. (we assume order contains the current order and 'Configuration' - the current configuration). Objects in this context are used by all the steps in the pipeline.
PaymentContext context = new PaymentContext();
context.Order = order;
context.Configuration = Configuration;
 
For an overview of the objects that can/should be set in the context refer to the context help section
  • Finally the pipeline needs to be executed:
pipeline.Execute(context, null);
 
As you could see earlier we needed to supply the context we just created. The second parameter is a list of custom objects that can be passed into the pipeline. This is only needed if custom objects need to be processed by the pipeline, for example we just supply null as we do not have any of these custom objects.
 
Those are all the steps needed to add a pipeline to the payment module. A module is not limited to a single pipeline; multiple pipelines can be added if needed. Below you can find a complete working example of an internal payment method:
 
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Sana.Commerce.Order;
using Sana.Commerce.Payment.Configuration;
using Sana.Commerce.Payment.Pipeline;
 
namespace Sana.Commerce.Payment
{
    /// <summary>
    /// Payment method for placing orders on account. This means no  
    /// verification of is needed and no user action is required,
    /// the order will be set to paid right away.
    /// This payment method is useful in a B2B scenario where an ERP
    /// system is used.
    /// </summary>
    public class OnAccountModule : IPaymentModule
    {
     public virtual bool Pay(IOrder order, NameValueCollection
     externalConfiguration)
     {
       IPaymentPipeline pipeline = CreatePipeline();
       PaymentContext context = new PaymentContext();
       context.Order = order;
           
       //Create configuration
       foreach (string key in externalConfiguration.Keys)
       {
         Configuration.Add(new PaymentConfigurationSetting {
         IsRequestParameter = false, Name = key, Value =           
         externalConfiguration[key] });
       }
       context.Configuration = Configuration;
                      
       //Execute the pipeline
       pipeline.Execute(context, null);
 
       PaymentLog.Current.Add(order, "Order was paid using the
       ZeroOrderPaymentModule."
, false);
 
       return true; //Let the checkout process handle deleting of basket         
     }
       
     /// <summary>
     /// Creates a pipeline instance.
     /// </summary>
     /// <returns>A fully initialized pipeline instance.</returns>
     protected virtual IPaymentPipeline CreatePipeline()
     {
      var okSteps = new IPaymentStep[]
      {     
       new PayOrderStep(),      //Set the order to paid
       new DeductStockStep(),   //Deduct the stock for this order
       new DeleteBasketStep(),  //Delete the basket linked to this order
       new SendOrderMailStep(), //Send to order confirmation mail 
       new RedirectToSuccessPageStep() //Redirect the user
      };
      return new PaymentPipeline("StatusOkPipeline", okSteps, true);
      }
       
      /// <summary>
      /// List of configuration values used by the payment module.
      /// </summary>
      protected List<PaymentConfigurationSetting> configuration = new
      List<PaymentConfigurationSetting>();
       
      /// <summary>
      /// List of configuration values used by the payment module.
      /// </summary>
      public virtual List<PaymentConfigurationSetting> Configuration
      {
        get { return configuration; }
        set { configuration = value; }
      }
    }
}
 
The steps executed by this payment method can easily be changed. Out-of-the box the Sana Commerce framework contains the following steps.
 
How toGeneral