public class PaymentCallbackController : Controller
{
// The user is redirected to paymentcallback/user/orderRef={guid}&orderNumber={string}&confirmationUrl={url} after having successfully supplied their payment information in PayEx
public RedirectResult User(string orderRef, string orderNumber, string confirmationUrl)
{
UrlBuilder confirmationUrlBuilder = new UrlBuilder(confirmationUrl);
// Get the cart for the current user
Cart cart = new CartHelper(Cart.DefaultName).Cart;
PayExPayment payExPayment = GetPayExPayment(cart);
// If the cart doesn't contain a PayExPayment, something has gone wrong
if (payExPayment == null)
return ErrorResult(confirmationUrlBuilder, null);
// If the PayExPayment doesn't contain an OrderNumber, something has gone wrong
if (string.IsNullOrWhiteSpace(payExPayment.OrderNumber))
return ErrorResult(confirmationUrlBuilder, null);
// If the PayExPayment OrderNumber doesn't equal the orderNumber from the queryString, something has gone wrong
if (!payExPayment.OrderNumber.Equals(orderNumber))
return ErrorResult(confirmationUrlBuilder, null);
PayExPaymentGateway gateway = new PayExPaymentGateway();
string transactionErrorCode;
// Complete the PayEx payment
bool processed = gateway.ProcessSuccessfulTransaction(payExPayment, orderNumber, orderRef, cart, out transactionErrorCode);
bool created = false;
if (processed) // If the payment was successfully completed, you can create a Purchase Order
created = CreatePurchaseOrder(cart, payExPayment, orderNumber);
if (!created)
return ErrorResult(confirmationUrlBuilder, transactionErrorCode);
// Redirect the user to an order confirmation page
confirmationUrlBuilder.QueryCollection.Add(ParameterName.OrderNumber, orderNumber);
return new RedirectResult(confirmationUrlBuilder.ToString());
}
// This action is used for transactional callbacks: http://www.payexpim.com/quick-guide/9-transaction-callback/
public HttpStatusCodeResult Index(string orderRef, [Bind(Prefix = ParameterName.PayExTransactionNumber)] string transactionNumber, [Bind(Prefix = ParameterName.PayExTransactionRef)] string transactionRef)
{
// Check that the request comes from a valid PayEx IP: http://www.payexpim.com/quick-guide/9-transaction-callback/
// The IP should not be hardcoded, this is only an example!
if (Request.ServerVariables["REMOTE_ADDR"] != "82.115.146.170")
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
if (string.IsNullOrEmpty(orderRef))
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
string orderNumber;
Cart cart = GetCartByOrderRef(orderRef, out orderNumber);
if (cart == null || string.IsNullOrEmpty(orderNumber))
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
PayExPayment payExPayment = GetPayExPayment(cart);
PayExPaymentGateway gateway = new PayExPaymentGateway();
string transactionErrorCode;
// Complete the PayEx payment
bool success = gateway.ProcessSuccessfulTransaction(payExPayment, orderNumber, orderRef, cart, out transactionErrorCode);
if (success)
return new HttpStatusCodeResult(HttpStatusCode.OK);
else
{
// If an order has already been created, maybe you'd want to cancel it if the callback wasn't successful?
}
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
///
/// Returns a Cart based on the PayEx orderReference
///
/// PayEx orderReference
/// Order number
/// Cart
private Cart GetCartByOrderRef(string orderRef, out string orderNumber)
{
var parameters = new OrderSearchParameters
{
SqlMetaWhereClause = "",
SqlWhereClause = "OrderGroupId IN (SELECT OrderGroupId FROM OrderFormPayment WHERE TransactionType LIKE 'Authorization' AND Status LIKE 'Pending')"
};
var options = new OrderSearchOptions
{
Classes = new StringCollection { "ShoppingCart" },
CacheResults = false,
RecordsToRetrieve = 10000,
Namespace = "Mediachase.Commerce.Orders"
};
var carts = OrderContext.Current.FindCarts(parameters, options);
foreach (var cart in carts)
{
var payment = GetPayExPayment(cart);
if (payment == null || string.IsNullOrWhiteSpace(payment.PayExOrderRef))
continue;
if (payment.PayExOrderRef.Equals(orderRef))
{
orderNumber = payment.OrderNumber;
return cart;
}
}
orderNumber = string.Empty;
return null;
}
///
/// Creates an error URL containing detailed information about the error that occured
///
/// UrlBuilder containing the confirmation URL
/// Error code returned from PayEx
/// A RedirectResult containing the error URL
private RedirectResult ErrorResult(UrlBuilder confirmationUrlBuilder, string transactionErrorCode)
{
confirmationUrlBuilder.QueryCollection.Add("error", "true");
if (!string.IsNullOrWhiteSpace(transactionErrorCode))
{
if (transactionErrorCode.Equals("CardNotAcceptedForThisPurchase"))
confirmationUrlBuilder.QueryCollection.Add("declined", "true");
}
return new RedirectResult(confirmationUrlBuilder.ToString());
}
///
/// Returns a PayExPayment for the given cart, if one exists
///
/// Cart
/// The PayExPayment gor the given cart
private PayExPayment GetPayExPayment(Cart cart)
{
if (cart.OrderForms == null || cart.OrderForms.Count == 0 || cart.OrderForms[0].Payments == null || cart.OrderForms[0].Payments.Count == 0)
return null;
List payments = cart.OrderForms[0].Payments.Where(p => p is PayExPayment).ToList();
payments = PaymentTransactionTypeManager.GetResultingPaymentsByTransactionType(payments,
TransactionType.Authorization).ToList();
if (payments.Any())
return payments.First() as PayExPayment;
return null;
}
///
/// Creates a purchase order with the given order number and deletes the cart
///
/// Cart
/// Payment
/// orderNumber
/// Boolean indicating success or failure
private bool CreatePurchaseOrder(Cart cart, Payment payment, string orderNumber)
{
try
{
using (TransactionScope scope = new TransactionScope())
{
PaymentStatusManager.ProcessPayment(payment);
cart.OrderNumberMethod = c => orderNumber;
PurchaseOrder purchaseOrder = cart.SaveAsPurchaseOrder();
cart.Delete();
cart.AcceptChanges();
purchaseOrder.AcceptChanges();
scope.Complete();
}
return true;
}
catch (Exception e)
{
// Add your own logging
return false;
}
}
}