This article explains the functions of the IPaymentProvider.ExecutePayment method and contains advice on how to implement it.
The ExecutePayment method is responsible for initializing the payment provider and registering the transaction with it. Then it should either call the necessary method in the payment provider or direct Litium to post information to the payment provider's website.
The first step is to extend the ExecutePaymentResult class to include information that will be returned from this method. We create a new class TestPaymentsExecutePaymentResult for that.
using Litium.Foundation.Modules.ECommerce.Plugins.Payments;
namespace Litium.Studio.AddOns.Samples.TestPaymentsProvider
{
/// <summary>
/// Extends abstract class <see cref="ExecutePaymentResult"/> to provide information returned from
/// <see cref="IPaymentProvider.ExecutePayment method."/>
/// </summary>
public class TestPaymentsExecutePaymentResult : ExecutePaymentResult
{
}
}
Then, in the TestPaymentsProvider class, the IPaymentProvider.ExecutePayment method is implemented to return an instance of the above class.
/// <summary>
/// Executes the payment.
/// </summary>
/// <param name="args">The arguments.</param>
/// <param name="token">The token.</param>
/// <returns>
/// Result of executing this command in a payment provider.
/// </returns>
public ExecutePaymentResult ExecutePayment(ExecutePaymentArgs args, SecurityToken token)
{
TestPaymentsExecutePaymentResult result = new TestPaymentsExecutePaymentResult(){Success = false};
var paymentArgs = args as PaymentArgs;
if (paymentArgs.PaymentMode == ExecutePaymentMode.Reserve && CanReserveMoneyFromCustomerAccount)
{
//reserve the money from the customers account.
//before calling Reserve, we should set correct payment status.
PaymentInfo.SetPaymentStatus((short)PaymentStatus.ExecuteReserve, token);
Reserve(paymentArgs, result, token);
}
else if (paymentArgs.PaymentMode == ExecutePaymentMode.Charge && CanChargeCustomerAccountDirectly)
{
//charge the money from the customers account.
//before calling Charge, we should set correct payment status.
PaymentInfo.SetPaymentStatus((short)PaymentStatus.ExecuteCharge, token);
Charge(paymentArgs, result, token);
}
return result;
}
The Charge and Reserve methods would look as follows. Pay particular attention to how the PaymentStatus is changed. Before the payment provider is called, the payment status is changed to keep a note of that we are about to call the payment provider. For example, before calling the payment provider if the payment mode is Reserve, the payment status is set to ExecuteReserve. The status is changed to Reserved after we have received a successful reply from the payment provider.
Then, after receiving a result from the payment provider, the payment status is set to reflect the result. In our example,we just simulate results based on the payment method name.
/// <summary>
/// Charge money from customers account.
/// </summary>
/// <param name="paymentArgs">The payment args.</param>
/// <param name="result">The result.</param>
/// <param name="token">The token.</param>
/// <exception cref="Litium.Foundation.Modules.ECommerce.Plugins.Payments.PaymentProviderException">Charge failed</exception>
/// <exception cref="System.NotImplementedException"></exception>
private void Charge(PaymentArgs paymentArgs, TestPaymentsExecutePaymentResult result, SecurityToken token)
{
//Todo: Call the payment provider web-service or any other implementation to charge money.
//var resultFromProvider = ChargeMethodAtPaymentProvider();
PaymentInfo.SetTransactionReference(PaymentInfo.ReferenceID, token);
var paymentMethod = (PaymentMethod)Enum.Parse(typeof(PaymentMethod), PaymentInfo.PaymentMethod);
switch (paymentMethod)
{
case PaymentMethod.SimulateSuccess:
PaymentInfo.SetPaymentStatus((short)PaymentStatus.Paid, token);
PaymentInfo.SetPaymentDate(DateTime.Now, token);
PaymentInfo.AppendExternalMessage(DateTime.Now.ToString() + " " + ProviderName + CHARGE_ACCOUNT_SUCCEEDED, token);
result.Success = true;
break;
case PaymentMethod.SimulateFailureWithException:
PaymentInfo.SetPaymentStatus((short)PaymentStatus.ChargeFailed, token);
PaymentInfo.SetPaymentDate(DateTime.Now, token);
PaymentInfo.AppendExternalMessage(DateTime.Now.ToString() + " " + ProviderName + CHARGE_ACCOUNT_FAILED, token);
throw new PaymentProviderException(ProviderName + CHARGE_ACCOUNT_FAILED, ProviderName);
case PaymentMethod.SimulateUserCancelled:
PaymentInfo.SetPaymentStatus((short)PaymentStatus.Cancelled, token);
PaymentInfo.SetPaymentDate(DateTime.Now, token);
PaymentInfo.AppendExternalMessage(DateTime.Now.ToString() + " " + ProviderName + CANCELED_BY_THE_USER, token);
result.Success = false;
result.ErrorMessage = CANCELED_BY_THE_USER;
break;
}
}
/// <summary>
/// Reserves the money from customers account.
/// </summary>
/// <param name="paymentArgs">The payment args.</param>
/// <param name="result">The result.</param>
/// <param name="token">The token.</param>
/// <returns></returns>
/// <exception cref="System.NotImplementedException"></exception>
private void Reserve(PaymentArgs paymentArgs, TestPaymentsExecutePaymentResult result, SecurityToken token)
{
//Todo: Call the payment provider web-service or any other implementation to charge money.
//var resultFromProvider = ChargeMethodAtPaymentProvider();
PaymentInfo.SetTransactionReference(PaymentInfo.ReferenceID, token);
var paymentMethod = (PaymentMethod)Enum.Parse(typeof(PaymentMethod), PaymentInfo.PaymentMethod);
switch (paymentMethod)
{
case PaymentMethod.SimulateSuccess:
PaymentInfo.SetPaymentStatus((short)PaymentStatus.Reserved, token);
PaymentInfo.SetPaymentDate(DateTime.Now, token);
PaymentInfo.AppendExternalMessage(DateTime.Now.ToString() + " " + ProviderName + RESERVE_SUCCEEDED, token);
result.Success = true;
break;
case PaymentMethod.SimulateFailureWithException:
PaymentInfo.SetPaymentStatus((short)PaymentStatus.ReserveFailed, token);
PaymentInfo.SetPaymentDate(DateTime.Now, token);
PaymentInfo.AppendExternalMessage(DateTime.Now.ToString() + " " + ProviderName +RESERVE_FAILED, token);
throw new PaymentProviderException(ProviderName + RESERVE_FAILED, ProviderName);
case PaymentMethod.SimulateUserCancelled:
PaymentInfo.SetPaymentStatus((short)PaymentStatus.Cancelled, token);
PaymentInfo.SetPaymentDate(DateTime.Now, token);
PaymentInfo.AppendExternalMessage(DateTime.Now.ToString() + " " + ProviderName + CANCELED_BY_THE_USER, token);
result.Success = false;
result.ErrorMessage = CANCELED_BY_THE_USER;
break;
}
}