# Creating a Custom Payment Gateway > You must have an ABP Team or a higher license to use this module. This document explains creating custom a payment gateway that's different than the existing ones in the [Payment Module](payment#packages). ## Creating Core Operations - Create **MyPaymentGateway.cs** in the **Domain** layer of your project and implement `IPaymentGateway`. ```csharp public class MyPaymentGateway : IPaymentGateway, ITransientDependency { private readonly IPaymentRequestRepository paymentRequestRepository; public MyPaymentGateway(IPaymentRequestRepository paymentRequestRepository) { this.paymentRequestRepository = paymentRequestRepository; } public async Task StartAsync(PaymentRequest paymentRequest, PaymentRequestStartInput input) { var totalPrice = paymentRequest.Products.Sum(x => x.TotalPrice); var checkoutLink = // Some operations here return new PaymentRequestStartResult { CheckoutLink = checkoutLink + "returnUrl=" + input.ReturnUrl }; } public async Task CompleteAsync(Dictionary parameters) { var token = parameters["token"]; // You can get any parameter from your gateway provides. Example: token, id, hash etc. var result = ;// provider.Validate(token); Validate the payment here var paymentRequest = await paymentRequestRepository.FindAsync(result.Id); paymentRequest.SetState(PaymentRequestState.Completed); // completed or anything else according to your result. return paymentRequest; } public Task HandleWebhookAsync(string payload, Dictionary headers) { // You can leave unimplemented if you not configure webhooks. throw new System.NotImplementedException(); } public bool IsValid(PaymentRequest paymentRequest, Dictionary properties) { // You can check some custom logic here to make this gateway available or not. return true; } } ``` - You should also configure `PaymentOptions` for your gateway in the **Domain** layer of your project as shown below. ```csharp Configure(options => { options.Gateways.Add(new PaymentGatewayConfiguration( "MyGateway", LocalizableString.Create("MyGateway"), isSubscriptionSupported: false, typeof(MyPaymentGateway) )); }); ``` ## Creating the UI There are 2 types of pages that are supported by default. You can define a pre-payment page and post-payment page. - Create **PreCheckout.cshtml** and **PreCheckout.cshtml.cs** ```html @model PreCheckoutModel

Pre Checkout

``` ```csharp public class PreCheckoutModel : AbpPageModel { [BindProperty] public Guid PaymentRequestId { get; set; } public virtual ActionResult OnGet() { // GET operation is not supported here. All the selected gateway requests will be sent as POST. return BadRequest(); } public virtual async Task OnPostAsync() { // You can get the payment request from the database by using `PaymentRequestId` and render something on the UI side. } public virtual async Task OnPostContinueToCheckout() { return Redirect("the-actual-checkout-link-of-gateway"); } } ``` - Create **PostCheckout.cshtml** and **PostCheckout.cshtml.cs** ```html @model PostCheckoutModel

Operation Done

``` - Configure your pages using `PaymentWebOptions` in **Web** layer of your project. ```csharp Configure(options => { options.Gateways.Add(new PaymentGatewayWebConfiguration( name: "MyGateway", prePaymentUrl: "/MyGateway/PreCheckout", // This page will be opened before checkout. isSubscriptionSupported: false, postPaymentUrl: "/MyGateway/PostCheckout" // This page will be opened after checkout. )); }); ``` Your custom gateway will be listed in the public payment gateway selection page. If there is only one payment gateway, this page will be skipped. ![ABP Payment Custom Gateway](../images/payment-custom-gateway-public.png)