You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

534 lines
23 KiB

using Common.Models.Bank_Account;
using Common.Models.Donga;
using Common.Models.RequestResponse;
using Common.Models.Status;
using Common.Models.TxnModel;
using Common.TPService;
using Common.Utility;
using log4net;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using RestSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web.Hosting;
namespace Donga.DongaAPIService
{
public class DongApiV2 : ITPApiServices
{
private readonly ILog _log = LogManager.GetLogger(typeof(DongApiV2));
protected string baseUrl { get; set; }
protected string partnerId { get; set; }
protected string secretKey { get; set; }
protected string privatekey { get; set; }
private const string ACCOUNT_VERIFY = "/restapi/account/verify";
private const string TRANSFER_SENDMASTER = "/restapi/transfer/sendmaster";
private const string TRANSFER_SENDDETAIL = "/restapi/transfer/senddetail";
private const string TRANSFER_ONLINE = "/restapi/transfer/online";
private const string TRANSFER_STATUS = "/restapi/transfer/tracking";
public DongApiV2()
{
baseUrl = GetStatic.ReadWebConfig("dongav2_base_url", "");
partnerId = GetStatic.ReadWebConfig("dongav2_partnerId", "");
secretKey = GetStatic.ReadWebConfig("dongav2_secretKey", "");
privatekey = GetStatic.ReadWebConfig("dongav2_privateKey", "");
}
public TPResponse GetTPResponse<T>(T model, string MethodName) where T : class
{
switch (MethodName)
{
case "send":
return SendTransaction(model as SendTransaction);
case "verify":
return AccountVerifyDongav2(model as AccountValidate);
case "status":
return GetStatusDongaV2(model as GetStatus);
default:
throw new NotImplementedException();
}
}
private TPResponse SendTransaction(SendTransaction model)
{
TPResponse _response = new TPResponse();
string sendTxnURL = "";
if (model.IsAccValSupported && model.Transaction.PaymentType.ToLower() == "bank deposit")
{
sendTxnURL = TRANSFER_ONLINE;
AccountValidate _validateRequest = new AccountValidate
{
AccountNumber = model.Receiver.RAccountNo,
BankCode = model.Agent.PBankId,
ReceiverName = model.Receiver.RFullName,
ControlNo = model.Transaction.JMEControlNo
};
_response = AccountVerifyDongav2(_validateRequest);
if (_response.ResponseCode == "0")
{
var _request = MapDongaRequestData(model, _response.Extra, "online");
_response = SendTransactionDonga(_request, "online", sendTxnURL);
}
}
else
{
sendTxnURL = TRANSFER_SENDDETAIL;
_response = SendMasterData(model);
if (_response.ResponseCode == "0")
{
var _request = MapDongaRequestData(model, _response.Extra, "other");
_response = SendTransactionDonga(_request, "other", sendTxnURL);
}
}
return _response;
}
private TPResponse SendTransactionDonga<T>(T model, string sendType, string url)
{
TPResponse _response = new TPResponse();
try
{
var client = new RestClient(baseUrl);
string request = "";
if (sendType == "online")
request = SimpleJson.SerializeObject(model as OnlineTransferRequest);
else
request = SimpleJson.SerializeObject(model as List<DetailDataRequest>);
string signature = SignData(request);
_log.Info($"{url}|REQUEST : {request}");
var result = client.Execute<MasterDataResponse>(BuildRequest<string>(url, request, signature));
_log.Info($"{url}|RESPONSE : {result.Content}");
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
var res = result.Data;
_response.Data = result.Data;
if (!string.IsNullOrEmpty(res.ResponseCode) && res.ResponseCode.Equals("0000"))
{
_response.ResponseCode = "0";
_response.Msg = "Success";
}
else
{
_response.ResponseCode = "1";
_response.Extra = res.ResponseCode;
_response.Msg = $"ErrorCode: {res.ResponseCode }. { (ResponseCodes.ContainsKey(res.ResponseCode) ? ResponseCodes[res.ResponseCode] : "")}";
}
}
else
{
_response.ResponseCode = "1";
_response.Msg = string.IsNullOrEmpty(result.Content) ? result.ErrorMessage : string.Join(",", SimpleJson.DeserializeObject<DongaV2Error>(result.Content).Errors);
}
}
catch (Exception ex)
{
_response.ResponseCode = "999";
_response.Msg = ex.Message;
}
return _response;
}
private TPResponse SendMasterData(SendTransaction model)
{
TPResponse _response = new TPResponse();
try
{
var client = new RestClient(baseUrl);
MasterDataRequest masterDataRequest = new MasterDataRequest()
{
SumTransaction = 1,
PartnerId = partnerId,
SumAUD = (model.Transaction.PCurr.ToLower().Equals("aud")) ? Convert.ToDecimal(model.Transaction.PAmt) : 0,
SumCAD = (model.Transaction.PCurr.ToLower().Equals("cad")) ? Convert.ToDecimal(model.Transaction.PAmt) : 0,
SumEUR = (model.Transaction.PCurr.ToLower().Equals("eur")) ? Convert.ToDecimal(model.Transaction.PAmt) : 0,
SumGBP = (model.Transaction.PCurr.ToLower().Equals("gbp")) ? Convert.ToDecimal(model.Transaction.PAmt) : 0,
SumJPY = (model.Transaction.PCurr.ToLower().Equals("jpy")) ? Convert.ToDecimal(model.Transaction.PAmt) : 0,
SumUSD = (model.Transaction.PCurr.ToLower().Equals("usd")) ? Convert.ToDecimal(model.Transaction.PAmt) : 0,
SumVND = (model.Transaction.PCurr.ToLower().Equals("vnd")) ? Convert.ToDecimal(model.Transaction.PAmt) : 0
};
string requestString = SimpleJson.SerializeObject(masterDataRequest);
string signature = SignData(requestString);
_log.Info($"{TRANSFER_SENDMASTER}|REQUEST : {requestString}");
var result = client.Execute<MasterDataResponse>(BuildRequest<MasterDataRequest>(TRANSFER_SENDMASTER, masterDataRequest, signature));
_log.Info($"{TRANSFER_SENDMASTER}|RESPONSE : {result.Content}");
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
var res = result.Data;
_response.Data = result.Data;
if (!string.IsNullOrEmpty(res.ResponseCode) && res.ResponseCode.Equals("0000"))
{
_response.ResponseCode = "0";
_response.Msg = "Success";
_response.Extra = result.Data.ApiKey;
}
else
{
_response.ResponseCode = "1";
_response.Msg = $"ErrorCode: {res.ResponseCode }. { (ResponseCodes.ContainsKey(res.ResponseCode) ? ResponseCodes[res.ResponseCode] : "")}";
}
}
else
{
_response.ResponseCode = "1";
_response.Msg = string.IsNullOrEmpty(result.Content) ? result.ErrorMessage : string.Join(",", SimpleJson.DeserializeObject<DongaV2Error>(result.Content).Errors);
}
}
catch (Exception ex)
{
_response.ResponseCode = "999";
_response.Msg = ex.Message;
}
return _response;
}
private object MapDongaRequestData(SendTransaction model, string apiKey, string type)
{
if (type == "online")
{
return new OnlineTransferRequest
{
PartnerID = partnerId,
ApiKey = apiKey,
TransactionId = model.Transaction.JMEControlNo,
SenderName = model.Sender.SFullName,
BenName = model.Receiver.RFullName,
BenAddress = model.Receiver.RAdd1.Trim(),
CityCode = "002", //Default
DistrictCode = model.Receiver.RCityCode,
Amount = model.Transaction.PAmt,
SCurrency = model.Transaction.PCurr,
PCurrency = model.Transaction.PCurr,
PaymentMode = GetPayoutMode(model.Transaction.PaymentType),
TransferType = "OT",
BenPhone = model.Receiver.RMobile,
BenAccount = model.Receiver.RAccountNo,
AccountType = "ACC",
BankCode = model.Agent.PBankId,
BenRelationship = model.Receiver.RelWithSenderName,
MoneyPurpose = model.Transaction.PurposeOfRemittanceName
};
}
else
{
List<DetailDataRequest> _dongaSendTxnRequestData = new List<DetailDataRequest>();
var pm = GetPayoutMode(model.Transaction.PaymentType);
_dongaSendTxnRequestData.Add(new DetailDataRequest
{
ApiKey = apiKey,
TransactionId = model.Transaction.JMEControlNo,
SenderName = model.Sender.SFullName,
BenName = model.Receiver.RFullName,
BenAddress = model.Receiver.RAdd1.Trim(),
CityCode = pm.Equals("TA") ? "002" : model.Receiver.RStateId,
DistrictCode = model.Receiver.RCityCode,
Amount = model.Transaction.PAmt,
SCurrency = model.Transaction.PCurr,
PCurrency = model.Transaction.PCurr,
PaymentMode = pm,
BenPhone = model.Receiver.RMobile,
BenAccount = pm.Equals("TA") ? model.Receiver.RAccountNo : null,
BankCode = pm.Equals("TA") ? model.Agent.PBankId : null,
Message = model.Transaction.PayoutMsg,
BenRelationship = model.Receiver.RelWithSenderName,
MoneyPurpose = model.Transaction.PurposeOfRemittanceName,
// IsBankTransfer = pm.Equals("TA") ? true : false
});
return _dongaSendTxnRequestData;
}
}
private string GetPayoutMode(string paymentType)
{
if (paymentType.ToLower().Equals("cash payment"))
return "CP";
else if (paymentType.ToLower().Equals("home delivery"))
return "HD";
else if (paymentType.ToLower().Equals("bank deposit"))
return "TA";
return "";
}
private TPResponse AccountVerifyDongav2(AccountValidate model)
{
TPResponse _response = new TPResponse();
try
{
var client = new RestClient(baseUrl);
AccountVerifyRequest accountVerifyRequest = new AccountVerifyRequest()
{
AccountType = "ACC",
BankCode = model.BankCode,
BenAccount = model.AccountNumber,
PartnerId = partnerId
};
var requestJson = JsonConvert.SerializeObject(accountVerifyRequest, Formatting.None);
_log.Info($"{ACCOUNT_VERIFY}|REQUEST : {requestJson}");
var result = client.Execute<AccountVerifyResponse>(BuildRequest<AccountVerifyRequest>(ACCOUNT_VERIFY, accountVerifyRequest, SignData(requestJson)));
_log.Info($"{ACCOUNT_VERIFY}|RESPONSE : {result.Content}");
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
var res = result.Data;
_response.Data = result.Data;
if (!string.IsNullOrEmpty(res.ResponseCode) && res.ResponseCode.Equals("0000"))
{
_response.ResponseCode = "0";
_response.Msg = "Success";
_response.Extra = res.ApiKey;
_response.Extra2 = res.BenName;
}
else
{
_response.ResponseCode = "1";
if (res.ResponseCode.Equals("0001"))
{
_response.Msg = $"ErrorCode: {res.ResponseCode }. Account validation failed!. Please check Bank/Account number";
}
else
_response.Msg = $"ErrorCode: {res.ResponseCode }. { (ResponseCodes.ContainsKey(res.ResponseCode) ? ResponseCodes[res.ResponseCode] : "")}";
}
}
else
{
_response.ResponseCode = "1";
_response.Msg = string.IsNullOrEmpty(result.Content) ? result.ErrorMessage : string.Join(",", SimpleJson.DeserializeObject<DongaV2Error>(result.Content).Errors);
}
}
catch (Exception ex)
{
_response.ResponseCode = "999";
_response.Msg = ex.Message;
}
return _response;
}
private TPResponse GetStatusDongaV2(GetStatus model)
{
TPResponse _response = new TPResponse();
try
{
var client = new RestClient(baseUrl);
TrackingStatusRequest statusRequest = new TrackingStatusRequest()
{
TransactionID = model.ControlNo,
PartnerID = partnerId
};
var requestJson = JsonConvert.SerializeObject(statusRequest, Formatting.None);
_log.Info($"{TRANSFER_STATUS}|REQUEST : {requestJson}");
var result = client.Execute<TrackingStatusResponse>(BuildRequest<TrackingStatusRequest>(TRANSFER_STATUS, statusRequest, SignData(requestJson)));
_log.Info($"{TRANSFER_STATUS}|RESPONSE : {result.Content}");
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
var res = result.Data;
_response.Data = result.Data;
if (!string.IsNullOrEmpty(res.ResponseCode) && res.ResponseCode.Equals("0000"))
{
_response.ResponseCode = "0";
_response.Extra2 = StatusCodes.ContainsKey(res.Status) ? StatusCodes[res.Status] : "Unpaid";
_response.Msg = $"{res.Status }: { (StatusCodes.ContainsKey(res.Status) ? StatusCodes[res.Status] : "")}";
if (!string.IsNullOrEmpty(res.PaidDate))
_response.Msg += $"Paid Date : {res.PaidDate} | ";
if (!string.IsNullOrEmpty(res.UnpaidReason))
_response.Msg += $"Unpaid Reason: { res.UnpaidReason}";
}
else
{
_response.ResponseCode = "1";
_response.Msg = !string.IsNullOrEmpty(res.Status) ? $"Code: {res.Status}| Reason: {(StatusCodes.ContainsKey(res.Status) ? StatusCodes[res.Status] : result.Content)}" : result.Content;
}
}
else
{
_response.ResponseCode = "1";
_response.Msg = string.IsNullOrEmpty(result.Content) ? result.ErrorMessage : string.Join(",", SimpleJson.DeserializeObject<DongaV2Error>(result.Content).Errors);
}
}
catch (Exception ex)
{
_response.ResponseCode = "999";
_response.Msg = ex.Message;
}
return _response;
}
private RestRequest BuildRequest<T>(string action, T o, string signature = "", Method method = Method.POST) where T : class
{
var authorizeHeader = "Basic " + Base64Encode($"{ partnerId}:{secretKey}");
var request = new RestRequest(action, method);
request.AddHeader("Content-Type", "application/json");
if (!string.IsNullOrEmpty(authorizeHeader))
request.AddHeader("Authorization", authorizeHeader);
if (!string.IsNullOrEmpty(signature))
request.AddHeader("Signature", signature);
request.RequestFormat = DataFormat.Json;
if (o != null)
request.AddJsonBody(o);
return request;
}
#region Helpers
private static string Base64Encode(string plainText)
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
public string SignData(string plainText)
{
var privateKey = File.ReadAllText(HostingEnvironment.MapPath($"~/{privatekey}"));
var ms = new MemoryStream(Encoding.Default.GetBytes(privateKey));
var sr = new StreamReader(ms);
var pemReader = new PemReader(sr);
var key = (RsaPrivateCrtKeyParameters)pemReader.ReadObject();
var signer = SignerUtilities.GetSigner("SHA256withRSA");
signer.Init(true, key);
var bytes = Encoding.UTF8.GetBytes(plainText);
signer.BlockUpdate(bytes, 0, bytes.Length);
byte[] signature = signer.GenerateSignature();
return Convert.ToBase64String(signature);
}
#endregion
public static Dictionary<string, string> ResponseCodes = new Dictionary<string, string>()
{
{ "0000", "SUCCESS"},
{ "0001", "Unexpected error."},
{ "0002", "Records missedmatch"},
{ "0003", "Account is incorrect"},
{ "0004", "Invalid data."},
{ "0005", "Invalid API KEY"},
{ "0006", "Duplicate records."},
{ "0007", "Total of amount missed match"},
{ "0008", "TIME OUT"},
{ "0009", "NO DATA FOUND"},
{ "0010", "Invalid Data"},
{ "0012", "Invalid transaction."},
{ "0013", "Invalid amount."},
{ "0014", "Invalid card or Account number (no such number)"},
{ "0015", "Not sufficient funds"},
{ "0016", "Http method is not Allow"},
{ "0017", "Invalid capture date"},
{ "0019", "Please check with issuing bank."},
{ "0021", "Card not initialized"},
{ "0030", "Message Format Error"},
{ "0034", "Suspected Fraud"},
{ "0039", "No Credit account"},
{ "0041", "Pick up card (Lost card)"},
{ "0042", "No universal account"},
{ "0043", "Stolen card, pick-up"},
{ "0051", "System is busy. Try again later"},
{ "0054", "Expire Card"},
{ "0057", "Transaction not permitted to cardholder"},
{ "0059", "Suspected Fraud"},
{ "0062", "Restricted Card"},
{ "0064", "Original Amount Incorrect"},
{ "0066", "Exceeds Acquirer Limit"},
{ "0068", "Response received too late (time-out)"},
{ "0075", "Allowable number of PIN tries exceeded"},
{ "0076", "Invalid Account."},
{ "0090", "Cut-off is in progress"},
{ "0091", "Issuer or switch is in operation"},
{ "0092", "Financial institution or intermediate network facility cannot be found for routing"},
{ "0093", "Invalid Acquirer"},
{ "0094", "Duplicate Transaction"},
{ "0096", "System denied transaction, please try again later."},
//{ "0099", "Please check with issuing bank."},
{ "0103", "Transaction does not exist"},
{ "0105", "Invalid Transfer Account Type"},
{ "0106", "CITAD only support working time & business date"},
{ "1111", "Internal Error"},
{ "1002", "IBT Transfer to Our bank card"},
{ "1003", "There are no app payments information registered"},
{ "1004", "The transaction has been canceled due to an error of authentication number three time or more"},
{ "1005", "Transaction error, please make transaction again."},
{ "1006", "Please check with issuing bank."},
{ "1007", "This request is not able to process Please apply for a new one"},
{ "1010", "Currency not allowed"},
{ "1011", "Operation account number is mandatory."},
{ "1021", "In-Active Card"},
{ "0025", "Unable to locate record on file"},
{ "1030", "Transaction information is invalid."},
{ "1040", "Requested function not supported"},
{ "1053", "Deposit limit account"},
{ "0061", "The transfer amount is over allowed limit."},
{ "0065", "Allowable number of Transactions Count exceeded"},
//{ "1075", "Please check with issuing bank."},
{ "3001", "Communication"},
{ "3002", "Identify"},
{ "3003", "Message parsing"},
{ "3004", "Connect Error"},
{ "3005", "No Channel"},
{ "3006", "Time over"},
{ "3007", "Closed"},
{ "3008", "No Adapter"},
{ "9997", "Create signature error"},
{ "9998", "Validation signature error"},
{ "9999", "Authorization error"}
};
public static Dictionary<string, string> StatusCodes = new Dictionary<string, string>()
{
{ "001", "WAITING"},
{ "002", "IN PROCESS "},
{ "003", "PAID"},
{ "004", "CANCELLED"},
{ "005", "NO DATA FOUND"}
};
}
}