Introduction
In the dynamic realm of online transactions, a smooth and secure payment gateway is indispensable. With .NET Core emerging as a go-to framework for web development, seamlessly integrating payment gateways like PayPhi has become essential. This article offers a concise guide to effortlessly integrating PayPhi with .NET Core. Let’s delve into the process, empowering developers to enhance their online payment systems efficiently.

Creation of a html/cshtml page
First and foremost, let's begin by setting up the groundwork. Create a new HTML page where we'll implement the PayPhi Payment Gateway integration with .NET Core. This HTML page will serve as the foundation for our project, allowing us to seamlessly incorporate PayPhi's functionality into our web application. We'll start by defining the structure of our page and then gradually integrate the necessary elements to facilitate secure and efficient online transactions. So, let's dive in and get started with the initial setup!
Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payment Details</title>
<style>
label {
display: block;
margin-bottom: 5px;
}
input {
width: 100%;
padding: 8px;
margin-bottom: 10px;
border-radius: 5px;
border: 1px solid #ccc;
box-sizing: border-box;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<h2>Enter Payment Details</h2>
<form id="paymentForm">
<label for="customerName">Customer Name:</label>
<input type="text" id="customerName" name="customerName" value="John Doe" required>
<label for="mobile">Mobile Number:</label>
<input type="tel" id="mobile" name="mobile" value="1234567890" pattern="[0-9]{10}" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" value="[email protected]" required>
<label for="paymentAmount">Payment Amount:</label>
<input type="number" id="paymentAmount" name="paymentAmount" value="100.00" min="0" step="0.01" required>
<label for="invoiceNumber">Invoice/Merchant Unique Number:</label>
<input type="text" id="invoiceNumber" name="invoiceNumber" value="INV123456" required>
<button type="submit">Submit Payment</button>
</form>
<script>
document.getElementById('paymentForm').addEventListener('submit', function(event) {
event.preventDefault();
// Here you can handle the form submission, such as sending the data to your server
// You can access form fields using document.getElementById('elementId').value
// Example: var customerName = document.getElementById('customerName').value;
// Perform further processing or send data to the server using AJAX
});
</script>
</body>
</html>
Creation of request from client side to Server side
To initiate the transaction process, the client-side script will craft a request containing essential payment details. These details typically include the customer's name, contact information, payment amount, and any additional metadata such as invoice or merchant unique numbers. Using JavaScript or a similar client-side scripting language, the request is assembled and sent to the server-side endpoint designated to handle payment processing. This communication between the client and server is crucial for securely transmitting sensitive payment data and initiating the subsequent steps in the payment flow. Let's explore how this request is structured and transmitted to ensure a seamless integration of the PayPhi Payment Gateway with our .NET Core application.
Note. You can check my artile How to create a unique number for Paymant Gateway
Code
<script type="text/javascript">
$('.btnUnionBankPayOnline').click(function (e) {
$('.divPaymantGateway').toggleClass('d-none');
});
$('.btnPayPhi').click(function (e) {
function getMonthsInLet(mid) {
if (mid == 0) {
return "A";
} else if (mid == 1) {
return "B";
} else if (mid == 2) {
return "C";
} else if (mid == 3) {
return "D";
} else if (mid == 4) {
return "E";
} else if (mid == 5) {
return "F";
} else if (mid == 6) {
return "G";
} else if (mid == 7) {
return "H";
} else if (mid == 8) {
return "I";
} else if (mid == 9) {
return "J";
} else if (mid == 10) {
return "K";
} else if (mid == 11) {
return "L";
}
}
var Date1 = new Date();
var getMonLet = getMonthsInLet(Date1.getMonth());
var RandNo = 'PP' + Date1.getDate().toString().padStart(2, "0") + getMonLet + Date1.getFullYear().toString().substr(-2) + Date1.getHours() + Date1.getMinutes() + Date1.getSeconds() + Date1.getMilliseconds();
$('.TransNo').text(RandNo);
$('.hdnTransNo').val(RandNo);
var merchantorderno = $('.hdnTransNo').val();
var custphone = $('.hdnCustmob').val();
var custemail = $('.hdnCustEmail').val();
var firstname = $('.hdnCustname').val();
if (fstname == " " || fstname == null) {
$('.chkmessage').text("Please update your name.");
$('#CheckingModel').modal("show");
return false;
}
else if (custemail == " " || custemail == null) {
$('.chkmessage').text("Please update your email.");
$('#CheckingModel').modal("show");
return false;
}
else if (custphone == " " || custphone == null) {
$('.chkmessage').text("Please update your mobile no.");
$('#CheckingModel').modal("show");
return false;
}
else {
$('#CheckingModel').modal("hide");
}
var postdata = {
MerchantOrderNo: merchantorderno,
CustomerPaidAmount: actpaidAmt,
customer_phone: custphone,
customer_email: custemail,
customer_firstname: fstname,
};
swal({
title: "Ready to Pay with PayPhi?",
content: {
element: "div",
attributes: {
innerHTML: "<pre><b>Merchant Order No:</b>" + RandNo + "<br><b>Contract Number:</b>" + contractno + "<br><b>Amount:</b>" + actpaidAmt + "</pre>",
},
},
icon: "warning",
buttons: true,
dangerMode: true,
closeOnClickOutside: false,
closeOnEsc: false,
})
.then((willMakePayment) => {
if (willMakePayment) {
$('#ModalLoader').modal('show');
$.ajax({
type: "POST",
url: appRoot + "/OrderProcessing/MakePaymentPayPhiMoneyOnline",
data: JSON.stringify(postdata),
datatype: "json",
contentType: 'application/json',
traditional: true,
success: function (data) {
//console.log(data);
if (data != null && data.includes("http")) {
window.location.href = data;
}
else {
$('#ModalLoader').modal('hide');
swal({
text: data,
icon: "error",
buttons: true,
closeOnClickOutside: false,
});
$('.divPaymantGateway').addClass('d-none');
return false;
}
}
});
} else {
swal({
text: "Payment cancelled. Please review your details.",
icon: "error",
buttons: true,
closeOnClickOutside: false,
})
}
});
});
</script>
Note. For sweet Alter you need to be use the swal Plugin.
Creation of modal class:
Creating a modal class in .NET Core allows us to organize and manage payment details efficiently. This class serves as a blueprint for storing attributes like customer name, contact information, payment amount, and invoice/merchant unique number. By encapsulating these details, we ensure code clarity and facilitate seamless integration with the PayPhi Payment Gateway. Let's dive into crafting this modal class for streamlined payment data management in our .NET Core application.
using System;
using System.Collections.Generic;
using System.Text;
namespace Domain.Common
{
public class PayPhi
{
}
public class PayPhiPaymentRequest
{
public string addlParam1 { get; set; }
public string addlParam2 { get; set; }
public string chargeAmount { get; set; }
public string chargeHead1 { get; set; }
public string currencyCode { get; set; }
public string desc { get; set; }
public string dueDate { get; set; }
public string emailID { get; set; }
public string expiryPeriod { get; set; }
public string invoiceNo { get; set; }
public string merchantId { get; set; }
public string mobileNo { get; set; }
public string paymentReturnURL { get; set; }
public string udf21 { get; set; }
public string udf22 { get; set; }
public string udf23 { get; set; }
public string userName { get; set; }
public string secureHash { get; set; }
}
public class PayPhiResponse
{
public string responseCode { get; set; }
public string respDescription { get; set; }
public string merchantId { get; set; }
public string invoiceNo { get; set; }
public string txnID { get; set; }
public string redirectionURL { get; set; }
public string secureHash { get; set; }
}
public class PayPhiDvResponse
{
public string responseCode { get; set; }
public string respDescription { get; set; }
public string merchantId { get; set; }
public string invoiceNo { get; set; }
public string mobileNo { get; set; }
public string chargeAmount { get; set; }
public string addlParam1 { get; set; }
public string addlParam2 { get; set; }
public string invoiceStatus { get; set; }
public string paidAmount { get; set; }
public string refundedAmount { get; set; }
public List<PaymentChildDtls> payments { get; set; }
public string secureHash { get; set; }
}
public class PaymentChildDtls
{
public string txnID { get; set; }
public string paymentMode { get; set; }
public string paymentID { get; set; }
public string paymentDateTime { get; set; }
}
public class PayPhiConfiguration
{
public string PaymentReturnURL { get; set; }
public string MerchanKey { get; set; }
public string MerchantId { get; set; }
public string PayPhiRequestURL { get; set; }
public string CurrencyCode { get; set; }
public string ExpiryPeriod { get; set; }
public string StatusCheckURL { get; set; }
}
public class PayPhiBankGatewayResponse
{
public string BankCode { get; set; }
public string SecureHash { get; set; }
public string Amount { get; set; }
public string RespDescription { get; set; }
public string PaymentMode { get; set; }
public string CustomerEmailID { get; set; }
public string AddlParam2 { get; set; }
public string ResponseCode { get; set; }
public string CustomerMobileNo { get; set; }
public string PaymentSubInstType { get; set; }
public string MerchantId { get; set; }
public string PaymentID { get; set; }
public string MerchantTxnNo { get; set; }
public string ChargeAmount { get; set; }
public string AddlParam1 { get; set; }
public string PaymentDateTime { get; set; }
public string InvoiceStatus { get; set; }
public string InvoiceNo { get; set; }
public string TxnID { get; set; }
public string DisplayMessage { get; set; }
}
public class RequestForPayPhiDoulbeVerification
{
public string invoiceNo { get; set; }
public string merchantId { get; set; }
public string reqType { get; set; }
public string secureHash { get; set; }
}
}
Before going to write the controller code create a common class for generating the secureHash as HmacHelper.cs as below:
HmacHelper.cs
using System;
using System.Security.Cryptography;
using System.Text;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Summary description for HmacHelper
/// </summary>
public class HmacHelper
{
public static string GetHashValue(string key, string message, HMACTypes type)
{
string response = "";
UTF8Encoding encoding = new UTF8Encoding();
byte[] keyByte = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(message);
switch (type)
{
case HMACTypes.HMAC_MD5:
using (var hmacmd = new HMACMD5(keyByte))
{
response = ByteToString(hmacmd.ComputeHash(messageBytes));
}
break;
case HMACTypes.HMAC_SHA1:
using (var hmacmd = new HMACSHA1(keyByte))
{
response = ByteToString(hmacmd.ComputeHash(messageBytes));
}
break;
case HMACTypes.HMAC_SHA256:
using (var hmacmd = new HMACSHA256(keyByte))
{
response = ByteToString(hmacmd.ComputeHash(messageBytes)).ToLower();
}
break;
case HMACTypes.HMAC_SHA384:
using (var hmacmd = new HMACSHA384(keyByte))
{
response = ByteToString(hmacmd.ComputeHash(messageBytes));
}
break;
case HMACTypes.HMAC_SHA512:
using (var hmacmd = new HMACSHA512(keyByte))
{
response = ByteToString(hmacmd.ComputeHash(messageBytes));
}
break;
}
return response;
}
private static string ByteToString(byte[] buff)
{
return buff.Aggregate("", (current, t) => current + t.ToString("X2"));
}
}
public enum HMACTypes
{
HMAC_MD5 = 0,
HMAC_SHA1,
HMAC_SHA256,
HMAC_SHA384,
HMAC_SHA512
}
Write the Controller code for Payment Initiation
[HttpPost]
public async Task<IActionResult> MakePaymentPayPhiMoneyOnline([FromBody] Payment payment)
{
try
{
LoggedInUser profile = HttpContext.Session.Get<LoggedInUser>(KeyHelper.UserKey);
if (profile == null)
{
return RedirectToAction("Logout", "Account");
}
else
{
var guidTokenNo = Guid.NewGuid().ToString();
string amount = Convert.ToString(payment.CustomerPaidAmount);
string customerName = payment.customer_firstname;
string email = payment.customer_email;
string phone = payment.customer_phone;
string productinfo = payment.ContractNumber.Trim();
/*Getting the priceperMT and Paid Qty*/
// Split the string by '|' character
string[] parts = payment.ItemsIndPriceDetails?.Split('|');
string pricePerMT = (parts?.Length > 1) ? parts[1].Trim() : "0.00";
string paidQty = (parts?.Length > 2) ? parts[2].Trim() : "0.00";
/*Added by Prakash For Mines Name,MaterialName & Contract Qty*/
PrintOnlineReceipt pt = new PrintOnlineReceipt();
pt.ContractNumber = productinfo;
pt.Action = "D";
var mnres = _orderProcessingRepository.GetMinesByContract(pt).Result.FirstOrDefault();
/*END*/
if (mnres != null)
{
var getPayPhiConfig = _commonRepository.GetPayPhiCongiguration().Result.FirstOrDefault();
if (getPayPhiConfig != null)
{
PayPhiPaymentRequest payPhireq = new PayPhiPaymentRequest();
payPhireq.addlParam1 = productinfo.Trim();
payPhireq.addlParam2 = mnres.MineName.Trim();
payPhireq.chargeAmount = amount.Trim();
payPhireq.chargeHead1 = amount.Trim();
payPhireq.currencyCode = getPayPhiConfig.CurrencyCode.Trim();
payPhireq.desc = "Payment For Contract No : " + productinfo.Trim();
payPhireq.dueDate = DateTime.Now.ToString("dd/MM/yyyy").Trim();
payPhireq.emailID = email.Trim();
payPhireq.expiryPeriod = mnres.DayCountInHours.Trim();
payPhireq.invoiceNo = payment.MerchantOrderNo.Trim();
payPhireq.merchantId = getPayPhiConfig.MerchantId.Trim();
payPhireq.mobileNo = phone.Trim();
payPhireq.paymentReturnURL = getPayPhiConfig.PaymentReturnURL.Trim();
payPhireq.udf21 = mnres.MaterialName.Trim();
payPhireq.udf22 = paidQty.Trim();
payPhireq.udf23 = pricePerMT.Trim();
payPhireq.userName = customerName.Trim();
// Set the property accoing to alphabetical order
string hashSequence = $"{payPhireq.addlParam1}{payPhireq.addlParam2}{payPhireq.chargeAmount}{payPhireq.chargeHead1}{payPhireq.currencyCode}{payPhireq.desc}{payPhireq.dueDate}{payPhireq.emailID}{payPhireq.expiryPeriod}{payPhireq.invoiceNo}{payPhireq.merchantId}{payPhireq.mobileNo}{payPhireq.paymentReturnURL}{payPhireq.udf21}{payPhireq.udf22}{payPhireq.udf23}{payPhireq.userName}";
var SecureHash = HmacHelper.GetHashValue(getPayPhiConfig.MerchanKey, hashSequence, HMACTypes.HMAC_SHA256);
payPhireq.secureHash = SecureHash;
string errorMessage = "";
if (string.IsNullOrEmpty(payPhireq.chargeAmount))
{
errorMessage = "chargeAmount is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.chargeHead1))
{
errorMessage = "chargeHead1 is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.currencyCode))
{
errorMessage = "currencyCode is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.desc))
{
errorMessage = "desc is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.dueDate))
{
errorMessage = "dueDate is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.invoiceNo))
{
errorMessage = "invoiceNo is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.paymentReturnURL))
{
errorMessage = "paymentReturnURL is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.merchantId))
{
errorMessage = "merchantId is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.secureHash))
{
errorMessage = "secureHash is missing or empty.";
}
else if (string.IsNullOrEmpty(payPhireq.emailID))
{
errorMessage = "emailID is missing or empty.";
}
if (!string.IsNullOrEmpty(errorMessage))
{
return Json(errorMessage);
}
var Payment_Request_String = JsonConvert.SerializeObject(payPhireq).ToString();
if (Payment_Request_String != null)
{
// Write the Payment Json Request in API Log Table
await _commonRepository.WriteAPILogDetail(new WriteAPILog
{
TokenNo = guidTokenNo,
API_Name = "MakePaymentPayPhiMoneyOnline",
Error_Message = "",
Request_String = Payment_Request_String,
Response_Message = "",
Response_Statuscode = "",
Response_String = ""
});
using (HttpClient client = new HttpClient())
{
// Post the request to the PayPhi endpoint directly using the full URL
HttpResponseMessage response = await client.PostAsync(
getPayPhiConfig.PayPhiRequestURL,
new StringContent(Payment_Request_String, Encoding.UTF8, "application/json")
);
// Read the response content
string responseContent = await response.Content.ReadAsStringAsync();
// Deserialize the JSON response
var jsonResponse = JObject.Parse(responseContent);
// Extract the response code
string responseCode = jsonResponse["responseCode"].ToString();
// Check the response code
if (responseCode == "0000")
{
// If the response code is "0000", the API was successful
// Write the Payment Json response in API Log Table
await _commonRepository.WriteAPILogDetail(new WriteAPILog
{
TokenNo = guidTokenNo,
API_Name = "",
Error_Message = "",
Request_String = "",
Response_Message = response.ReasonPhrase,
Response_Statuscode = responseCode,
Response_String = responseContent
});
// Check if the response is successful
if (response.IsSuccessStatusCode)
{
//Deserialize the response JSON to a PayPhiResponse object
var payPhiResponse = JsonConvert.DeserializeObject<PayPhiResponse>(responseContent);
if (payPhiResponse.redirectionURL != null)
{
/*Insert to to temp table*/
payment.Action = "I";
payment.CreatedBy = profile.UserId;
payment.MerchantId = getPayPhiConfig.MerchanKey;
payment.PaymentGatewayBankName = "PayPhi";
var res = _orderProcessingRepository.AddPaymentOnline(payment).Result;
/*Insert to to temp table*/
// Redirect the user to the redirectionURL received in the response
return Json(payPhiResponse.redirectionURL);
}
}
else
{
// You can access other fields from the JSON response for error handling
string respDescription = jsonResponse["respDescription"].ToString();
// Handle unsuccessful response
return Json(respDescription);
}
}
else
{
// Handle unsuccessful response
// If the response code is not "0000", handle the error accordingly
// You can access other fields from the JSON response for error handling
string respDescription = jsonResponse["respDescription"].ToString();
//Write the Payment Json response in API Log Table
await _commonRepository.WriteAPILogDetail(new WriteAPILog
{
TokenNo = guidTokenNo,
API_Name = "",
Error_Message = respDescription,
Request_String = "",
Response_Message = "",
Response_Statuscode = responseCode,
Response_String = responseContent
});
return Json(respDescription);
}
}
}
}
}
}
}
catch (Exception ex)
{
await _commonRepository.InsertErrorLog(ex.Message, DateTime.Now, "MakePaymentPayPhiMoneyOnline", ex.Source, " StckTrace = " + ex.StackTrace);
return Json(ex.Message);
}
return View();
}
Join the conversation! Your thoughts help the community grow.