Sv vào trang https://sandbox.vnpayment.vn/devreg/ để đăng ký tài khoản Sandbox.
Bạn điền đầy đủ thông tin cần thiết vào mẫu đăng ký và nhấn “Đăng ký”. Sau khi hoàn tất, hãy kiểm tra email để kích hoạt tài khoản. Sau khi kích hoạt, bạn sẽ nhận được các thông tin cần thiết để tiếp tục cài đặt. Các thông tin cấn thiết/bắt buộc là: vnp_TmnCode, vnp_HashSecret, vnp_Url, vnp_ReturnUrl.
Download mã nguồn tích hợp cho các ngôn ngữ ở đây: https://sandbox.vnpayment.vn/apis/downloads/
public class VnPaymentResponseModel
{
public bool Success { get; set; }
public string PaymentMethod { get; set; }
public string OrderDescription { get; set; }
public string OrderId { get; set; }
public string PaymentId { get; set; }
public string TransactionId { get; set; }
public string Token { get; set; }
public string VnPayResponseCode { get; set; }
}
public class VnPaymentRequestModel
{
public int OrderId { get; set; }
public string FullName { get; set; }
public string Description { get; set; }
public double Amount { get; set; }
public DateTime CreatedDate { get; set; }
}
public class VnPayLibrary
{
private readonly SortedList<string, string> _requestData = new SortedList<string, string>(new VnPayCompare());
private readonly SortedList<string, string> _responseData = new SortedList<string, string>(new VnPayCompare());
public void AddRequestData(string key, string value)
{
if (!string.IsNullOrEmpty(value))
{
_requestData.Add(key, value);
}
}
public void AddResponseData(string key, string value)
{
if (!string.IsNullOrEmpty(value))
{
_responseData.Add(key, value);
}
}
public string GetResponseData(string key)
{
return _responseData.TryGetValue(key, out var retValue) ? retValue : string.Empty;
}
#region Request
public string CreateRequestUrl(string baseUrl, string vnpHashSecret)
{
var data = new StringBuilder();
foreach (var (key, value) in _requestData.Where(kv => !string.IsNullOrEmpty(kv.Value)))
{
data.Append(WebUtility.UrlEncode(key) + "=" + WebUtility.UrlEncode(value) + "&");
}
var querystring = data.ToString();
baseUrl += "?" + querystring;
var signData = querystring;
if (signData.Length > 0)
{
signData = signData.Remove(data.Length - 1, 1);
}
var vnpSecureHash = Utils.HmacSHA512(vnpHashSecret, signData);
baseUrl += "vnp_SecureHash=" + vnpSecureHash;
return baseUrl;
}
#endregion
#region Response process
public bool ValidateSignature(string inputHash, string secretKey)
{
var rspRaw = GetResponseData();
var myChecksum = Utils.HmacSHA512(secretKey, rspRaw);
return myChecksum.Equals(inputHash, StringComparison.InvariantCultureIgnoreCase);
}
private string GetResponseData()
{
var data = new StringBuilder();
if (_responseData.ContainsKey("vnp_SecureHashType"))
{
_responseData.Remove("vnp_SecureHashType");
}
if (_responseData.ContainsKey("vnp_SecureHash"))
{
_responseData.Remove("vnp_SecureHash");
}
foreach (var (key, value) in _responseData.Where(kv => !string.IsNullOrEmpty(kv.Value)))
{
data.Append(WebUtility.UrlEncode(key) + "=" + WebUtility.UrlEncode(value) + "&");
}
//remove last '&'
if (data.Length > 0)
{
data.Remove(data.Length - 1, 1);
}
return data.ToString();
}
#endregion
}
public class Utils
{
public static string HmacSHA512(string key, string inputData)
{
var hash = new StringBuilder();
var keyBytes = Encoding.UTF8.GetBytes(key);
var inputBytes = Encoding.UTF8.GetBytes(inputData);
using (var hmac = new HMACSHA512(keyBytes))
{
var hashValue = hmac.ComputeHash(inputBytes);
foreach (var theByte in hashValue)
{
hash.Append(theByte.ToString("x2"));
}
}
return hash.ToString();
}
// có chế biến cho .NET Core MVC
public static string GetIpAddress(HttpContext context)
{
var ipAddress = string.Empty;
try
{
var remoteIpAddress = context.Connection.RemoteIpAddress;
if (remoteIpAddress != null)
{
if (remoteIpAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
remoteIpAddress = Dns.GetHostEntry(remoteIpAddress).AddressList
.FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork);
}
if (remoteIpAddress != null) ipAddress = remoteIpAddress.ToString();
return ipAddress;
}
}
catch (Exception ex)
{
return "Invalid IP:" + ex.Message;
}
return "127.0.0.1";
}
}
public class VnPayCompare : IComparer<string>
{
public int Compare(string x, string y)
{
if (x == y) return 0;
if (x == null) return -1;
if (y == null) return 1;
var vnpCompare = CompareInfo.GetCompareInfo("en-US");
return vnpCompare.Compare(x, y, CompareOptions.Ordinal);
}
}
public interface IVnPayService
{
string CreatePaymentUrl(HttpContext context, VnPaymentRequestModel model);
VnPaymentResponseModel PaymentExecute(IQueryCollection collections);
}
public class VnPayService : IVnPayService
{
private readonly IConfiguration _config;
public VnPayService(IConfiguration config)
{
_config = config;
}
public string CreatePaymentUrl(HttpContext context, VnPaymentRequestModel model)
{
var tick = DateTime.Now.Ticks.ToString();
var vnpay = new VnPayLibrary();
vnpay.AddRequestData("vnp_Version", _config["VnPay:Version"]);
vnpay.AddRequestData("vnp_Command", _config["VnPay:Command"]);
vnpay.AddRequestData("vnp_TmnCode", _config["VnPay:TmnCode"]);
vnpay.AddRequestData("vnp_Amount", (model.Amount * 100).ToString()); //Số tiền thanh toán. Số tiền không mang các ký tự phân tách thập phân, phần nghìn, ký tự tiền tệ. Để gửi số tiền thanh toán là 100,000 VND (một trăm nghìn VNĐ) thì merchant cần nhân thêm 100 lần (khử phần thập phân), sau đó gửi sang VNPAY là: 10000000
vnpay.AddRequestData("vnp_CreateDate", model.CreatedDate.ToString("yyyyMMddHHmmss"));
vnpay.AddRequestData("vnp_CurrCode", _config["VnPay:CurrCode"]);
vnpay.AddRequestData("vnp_IpAddr", Utils.GetIpAddress(context));
vnpay.AddRequestData("vnp_Locale", _config["VnPay:Locale"]);
vnpay.AddRequestData("vnp_OrderInfo", "Thanh toán cho đơn hàng:" + model.OrderId);
vnpay.AddRequestData("vnp_OrderType", "other"); //default value: other
vnpay.AddRequestData("vnp_ReturnUrl", _config["VnPay:PaymentBackReturnUrl"]);
vnpay.AddRequestData("vnp_TxnRef", tick); // Mã tham chiếu của giao dịch tại hệ thống của merchant. Mã này là duy nhất dùng để phân biệt các đơn hàng gửi sang VNPAY. Không được trùng lặp trong ngày
var paymentUrl = vnpay.CreateRequestUrl(_config["VnPay:BaseUrl"], _config["VnPay:HashSecret"]);
return paymentUrl;
}
public VnPaymentResponseModel PaymentExecute(IQueryCollection collections)
{
var vnpay = new VnPayLibrary();
foreach (var (key, value) in collections)
{
if (!string.IsNullOrEmpty(key) && key.StartsWith("vnp_"))
{
vnpay.AddResponseData(key, value.ToString());
}
}
var vnp_orderId = Convert.ToInt64(vnpay.GetResponseData("vnp_TxnRef"));
var vnp_TransactionId = Convert.ToInt64(vnpay.GetResponseData("vnp_TransactionNo"));
var vnp_SecureHash = collections.FirstOrDefault(p => p.Key == "vnp_SecureHash").Value;
var vnp_ResponseCode = vnpay.GetResponseData("vnp_ResponseCode");
var vnp_OrderInfo = vnpay.GetResponseData("vnp_OrderInfo");
bool checkSignature = vnpay.ValidateSignature(vnp_SecureHash, _config["VnPay:HashSecret"]);
if (!checkSignature)
{
return new VnPaymentResponseModel
{
Success = false
};
}
return new VnPaymentResponseModel {
Success = true,
PaymentMethod = "VnPay",
OrderDescription = vnp_OrderInfo,
OrderId = vnp_orderId.ToString(),
TransactionId = vnp_TransactionId.ToString(),
Token = vnp_SecureHash,
VnPayResponseCode = vnp_ResponseCode
};
}
}
builder.Services.AddSingleton<IVnPayService, VnPayService>();
"VnPay": {
"TmnCode": "your_Tmn_Code",
"HashSecret": "your_hash_secret",
"BaseUrl": "https://sandbox.vnpayment.vn/paymentv2/vpcpay.html",
"Version": "2.1.0",
"Command": "pay",
"CurrCode": "VND",
"Locale": "vn",
"PaymentBackReturnUrl": "https://localhost:port/payment/PaymentCallBack"
},
var vnPayModel = new VnPaymentRequestModel
{
Amount = Cart.Sum(p => p.ThanhTien),
CreatedDate = DateTime.Now,
Description = $"{model.HoTen} {model.DienThoai}",
FullName = model.HoTen,
OrderId = new Random().Next(1000, 100000)
};
return Redirect(_vnPayservice.CreatePaymentUrl(HttpContext, vnPayModel));
public IActionResult PaymentCallBack()
{
var response = _vnPayservice.PaymentExecute(Request.Query);
if (response == null || response.VnPayResponseCode != "00")
{
TempData["Message"] = $"Lỗi thanh toán VN Pay: {response.VnPayResponseCode}";
return RedirectToAction("PaymentFail");
}
// Lưu đơn hàng vô database
TempData["Message"] = $"Thanh toán VNPay thành công";
return RedirectToAction("PaymentSuccess");
}
Thông tài tài khoản test: https://sandbox.vnpayment.vn/apis/vnpay-demo/