Developing Custom Payment Gateway 4/19/2012 Miro Remias, Solution Architect Built-in Payment Gateways PayPal, Authorize.NET, Customer Credit, ? Custom Payment Gateway, Market Place: E-way, PayPal Payflow Pro, Agenda SQL Database Save order Update result 2 A) Checkout steps B) Kentico Buyer(s) Authorize.NET HTTP(S) POST Redirect PayPal 1 Redirect (optional) Thank you page Payment Notification Update result 2 3 Confirmation (optional) PN page • • • • • Payment gateway class, payment gateway form (1) Payment result (2) Payment Notification (3) Security (4) Real world example - DEMO Payment provider (1) Payment Gateway Class API CMS.EcommerceProvider.CMSPaymentGatewayProvider ShoppingCartControl (ShoppingCart) ShoppingCartInfoObj (ShoppingCartInfo) OrderId (int) PaymentResult (PaymentResultInfo) IsPaymentCompleted (bool) PaymentResult.PaymentIsCompleted AddCustomData() - CMSPaymentGatewayForm control is added to the payment data container and its data are loaded. RemoveCustomData() - All controls from payment data container are removed. ValidateCustomData() - CMSPaymentGatewayForm control data are validated. ProcessCustomData() - CMSPaymentGatewayForm data are processed. ShoppingCartInfoObj.PaymentGatewayCustomData (Hashtable) ProcessPayment() - Override this method to process payment by your payment processor. GetPaymentDataForm() - Override this method to get your own payment gateway form. (static)GetPaymentGatewayProvider(int paymentOptionId) – Loads payment gateway. UpdateOrderPaymentResult() - Updates order payment result in database. OrderId PaymentResult (1) Payment Gateway Form API CMS.EcommerceProvider.CMSPaymentGatewayForm ShoppingCartControl (ShoppingCart) ShoppingCartInfoObj (ShoppingCartInfo) PaymentGatewayCustomData (Hashtable) LoadData() - Initializes form controls with customer payment data CMSPaymentGatewayProvider.AddCustomData() - ShoppingCartPaymentGateway ValidateData() - Validates form data and returns error message if some error occurs CMSPaymentGatewayProvider.ValidateCustomData() - ShoppingCartPaymentGateway ProcessData() - Process form data and returns error message if some error occurs CMSPaymentGatewayProvider.ProcessCustomData() - ShoppingCartPaymentGateway UI (1) I Don’t Need Payment Gateway Form ShoppingCartPaymentGateway API PaymentOptionInfo poi = PaymentOptionInfoProvider.GetPaymentOptionInfo(this.ShoppingCartInfoObj.ShoppingCartPaymentOptionID); if (poi != null && poi.PaymentOptionClassName.ToLower().Equals("worldpayprovider")) { this.ButtonNextClickAction(); } else { LoadData(); } (2) Working With Payment Result Database API COM_Order [Table] OrderPaymentResult [Column] CMS.Ecommerce.OrderInfo OrderPaymentResult CMS.Ecommerce.PaymentResultInfo PaymentDate PaymentMethodID PaymentMethodName PaymentIsCompleted PaymentStatusName PaymentStatusCode PaymentTransactionID LoadPaymentResultXml(string xml) <result> <item name="date" header="{$PaymentGateway.Result.Date$}" value="4/12/2012 8:30:19 PM" /> <item name="method" header="{$PaymentGateway.Result.PaymentMethod$}" text="Word Pay" value="5" /> <item name="completed" header="{$PaymentGateway.Result.IsCompleted$}" value="1" text="{$PaymentGateway.Result.PaymentCompleted$}" /> <item name="transactionid" header="{$PaymentGateway.Result.TransactionID$}" value="6dc9af1c.." /> <item name="description" header="{$PaymentGateway.Result.Description$}" /> <item name="verified" header="{$PaymentGateway.WorldPayResult.Verification$}" value="1" text="{$PaymentGateway.WorldPayResult.Verification.Verified$}" /> </result> COM_Order [Table] OrderIsPaid [Column](new from version 6.0) // Create/address new/existing PaymentResultItemInfo PaymentResultItemInfo itemObj = EnsurePaymentResultItemInfo("verified", HEADER_VERIFIED); // PaymentResultItemInfo itemObj = GetPaymentResultItemInfo("verified"); if(itemObj != null) { // item.Name // item.Header item.Value = ""; item.Text = ""; } // Save new item SetPaymentResultItemInfo(item); CMS.Ecommerce.OrderInfo OrderIsPaid Note: You don’t need to specify both value and item text if they are identical ((1) item text, (2) item value) (3) Payment Notification • Physical page (.aspx) vs. virtual page (served by Kentico), • PN page is not displaying anything - it should only process the received data, • • • Common location: ~\CMSModules\Ecommerce\CMSPages\ PN page needs to be accessible by public user, Compare order data (COM_Order) and secret (e.g. from settings) with payment gateway response/result data, Confirm payment with payment gateway (optional), Log any exceptions, error or suspicious behavior into Event log, Update order payment result, • • • • Confirmation e-mails are automatically sent, API CMS.EcommerceProvider.CMSPaymentGatewayProvider OrderId PaymentResult UpdateOrderPaymentResult() int orderID = 5; // from response int paymentOptionID = 6; // from order (based on orderID) // Load payment provider CMSPaymentGatewayProvider provider = (WorldPayProvider)CMSPaymentGatewayProvider.GetPaymentGatewayProvider(paymentOptionID); provider.OrderId = orderId; // Compare data … // provider.PaymentResult = provider.UpdateOrderPaymentResult(); (4) Security • Consider using SSL (HTTPS) on shopping cart page when collecting sensitive information, • Use POST instead of GET (redirect) if possible, • Redirect/post with SSL (HTTPS), • Do not send sensitive information as part of the URL (querystring), • Verify data/integrity/result/etc. against some secret information, • Don’t save sensitive information in Kentico, • Customer credit card etc., • Use payment gateway security features, • Be paranoid!, Real World Example • Understand how payment gateway works, o Documentation, • Develop payment gateway class, form, PN page etc. o Take advantage of documentation examples, o Provide your code from App_Code folder, No need to rebuild your DLL file when upgrading or applying hotfix, • Use custom setting keys, o CMS Site Manager -> Development -> Custom Settings (new from version 6.0), • Register payment option (gateway) in Kentico, o Assign it to some shipping option, • Test and review the security, [DEMO] Questions ? Sources E-commerce Guide • http://devnet.kentico.com/docs/ecommerceguide/index.html Contact Miro Remias • e-mail: miro@kentico.com • consulting: http://www.kentico.com/Support/Consulting/Overview