Compare commits
5 Commits
b4dcc35a8b
...
35a2870179
| Author | SHA1 | Date | |
|---|---|---|---|
| 35a2870179 | |||
| c053868dd3 | |||
| 1c420dd01e | |||
| df9d822465 | |||
| 3f559dfd45 |
@ -218,6 +218,7 @@
|
|||||||
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>packages\System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll</HintPath>
|
<HintPath>packages\System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Numerics" />
|
<Reference Include="System.Numerics" />
|
||||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||||
@ -247,6 +248,7 @@
|
|||||||
<Compile Include="Client.cs" />
|
<Compile Include="Client.cs" />
|
||||||
<Compile Include="ClientApp.cs" />
|
<Compile Include="ClientApp.cs" />
|
||||||
<Compile Include="ConfigFileParser.cs" />
|
<Compile Include="ConfigFileParser.cs" />
|
||||||
|
<Compile Include="ErrorLogger.cs" />
|
||||||
<Compile Include="ExtraParameter.cs" />
|
<Compile Include="ExtraParameter.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
83
Client.cs
83
Client.cs
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Reflection.Metadata;
|
using System.Reflection.Metadata;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
namespace Creditcall.ChipDna.Client
|
namespace Creditcall.ChipDna.Client
|
||||||
{
|
{
|
||||||
@ -249,7 +250,6 @@ namespace Creditcall.ChipDna.Client
|
|||||||
{
|
{
|
||||||
{ ParameterKeys.Errors, errors },
|
{ ParameterKeys.Errors, errors },
|
||||||
{ ParameterKeys.Reference, reference },
|
{ ParameterKeys.Reference, reference },
|
||||||
{ ParameterKeys.TransactionResult, "ERROR" }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (TransactionCompletionSource != null && !TransactionCompletionSource.Task.IsCompleted)
|
if (TransactionCompletionSource != null && !TransactionCompletionSource.Task.IsCompleted)
|
||||||
@ -318,13 +318,13 @@ namespace Creditcall.ChipDna.Client
|
|||||||
PerformStartTransaction("250", "");
|
PerformStartTransaction("250", "");
|
||||||
break;
|
break;
|
||||||
case "C":
|
case "C":
|
||||||
PerformConfirmTransaction("", out TransactionConfirmation confirmation);
|
PerformConfirmTransaction("", "");
|
||||||
break;
|
break;
|
||||||
case "V":
|
case "V":
|
||||||
PerformVoidTransaction();
|
PerformVoidTransaction("");
|
||||||
break;
|
break;
|
||||||
case "I":
|
case "I":
|
||||||
PerformGetTransactionInformation();
|
PerformGetTransactionInformation("");
|
||||||
break;
|
break;
|
||||||
case "K":
|
case "K":
|
||||||
PerformReleaseCard();
|
PerformReleaseCard();
|
||||||
@ -471,14 +471,14 @@ namespace Creditcall.ChipDna.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetStatus()
|
public Dictionary<string, string> GetStatus()
|
||||||
{
|
{
|
||||||
Console.WriteLine(ParameterKeys.VersionInformation + "\n" + ParameterKeys.ChipDnaStatus + "\n" + ParameterKeys.PaymentDeviceStatus + "\n" + ParameterKeys.RequestQueueStatus + "\n" + ParameterKeys.TmsStatus + "\n" + ParameterKeys.PaymentPlatformStatus);
|
var transactionResult = new Dictionary<string, string>();
|
||||||
|
|
||||||
var parameterSet = new ParameterSet();
|
var parameterSet = new ParameterSet();
|
||||||
|
var responseParameter = new List<Parameter>();
|
||||||
|
|
||||||
parameterSet.Add(GetExtraParams("GetStatus"));
|
parameterSet.Add(GetExtraParams("GetStatus"));
|
||||||
Response response = chipDnaClientLib.GetStatus(GetRequestedParameterSet(parameterSet));
|
Response response = chipDnaClientLib.GetStatus(parameterSet);
|
||||||
|
|
||||||
string errors;
|
string errors;
|
||||||
var serverStatus = (ChipDnaStatus) null;
|
var serverStatus = (ChipDnaStatus) null;
|
||||||
@ -495,6 +495,13 @@ namespace Creditcall.ChipDna.Client
|
|||||||
{
|
{
|
||||||
Console.WriteLine(serverStatus);
|
Console.WriteLine(serverStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
responseParameter = response.ToList();
|
||||||
|
responseParameter.ForEach(parameter =>
|
||||||
|
{
|
||||||
|
transactionResult.Add(parameter.Key, parameter.Value);
|
||||||
|
});
|
||||||
|
return transactionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetMerchantData()
|
private void GetMerchantData()
|
||||||
@ -635,19 +642,23 @@ namespace Creditcall.ChipDna.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PerformConfirmTransaction(string reference, out TransactionConfirmation confirmation)
|
public Dictionary<string, string> PerformConfirmTransaction(string reference, string amount)
|
||||||
{
|
{
|
||||||
confirmation = new TransactionConfirmation();
|
var confirmationResult = new Dictionary<string, string>();
|
||||||
|
|
||||||
var parameters = new ParameterSet();
|
var parameters = new ParameterSet();
|
||||||
parameters.Add(ParameterKeys.Reference, reference);
|
parameters.Add(ParameterKeys.Reference, reference);
|
||||||
|
parameters.Add(ParameterKeys.Amount, amount);
|
||||||
parameters.Add(GetExtraParams("ConfirmTransaction"));
|
parameters.Add(GetExtraParams("ConfirmTransaction"));
|
||||||
var response = chipDnaClientLib.ConfirmTransaction(parameters);
|
var response = chipDnaClientLib.ConfirmTransaction(parameters);
|
||||||
|
var responseParameter = response.ToList();
|
||||||
|
responseParameter.ForEach(parameter =>
|
||||||
|
{
|
||||||
|
confirmationResult.Add(parameter.Key, parameter.Value);
|
||||||
|
});
|
||||||
string receipt, result;
|
string receipt, result;
|
||||||
if (response.GetValue(ParameterKeys.TransactionResult, out result))
|
if (response.GetValue(ParameterKeys.TransactionResult, out result))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Confirmed Transaction Result: {0}", result);
|
Console.WriteLine("Confirmed Transaction Result: {0}", result);
|
||||||
confirmation.Result = result;
|
|
||||||
}
|
}
|
||||||
if (response.GetValue(ParameterKeys.ReceiptDataMerchant, out receipt))
|
if (response.GetValue(ParameterKeys.ReceiptDataMerchant, out receipt))
|
||||||
{
|
{
|
||||||
@ -656,21 +667,19 @@ namespace Creditcall.ChipDna.Client
|
|||||||
if (response.GetValue(ParameterKeys.ReceiptDataCardholder, out receipt))
|
if (response.GetValue(ParameterKeys.ReceiptDataCardholder, out receipt))
|
||||||
{
|
{
|
||||||
PrintReceiptData(ReceiptData.GetReceiptDataFromXml(receipt));
|
PrintReceiptData(ReceiptData.GetReceiptDataFromXml(receipt));
|
||||||
confirmation.ReceiptDataCardholder = receipt;
|
|
||||||
}
|
}
|
||||||
string errors;
|
string errors;
|
||||||
if (response.GetValue(ParameterKeys.Errors, out errors))
|
if (response.GetValue(ParameterKeys.Errors, out errors))
|
||||||
{
|
{
|
||||||
Console.WriteLine(ErrorsString("ConfirmTransaction Errors", errors));
|
Console.WriteLine(ErrorsString("ConfirmTransaction Errors", errors));
|
||||||
confirmation.Errors = errors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string errorDescription;
|
string errorDescription;
|
||||||
if (response.GetValue(ParameterKeys.ErrorDescription, out errorDescription))
|
if (response.GetValue(ParameterKeys.ErrorDescription, out errorDescription))
|
||||||
{
|
{
|
||||||
Console.WriteLine("ErrorDescription: {0}", errorDescription);
|
Console.WriteLine("ErrorDescription: {0}", errorDescription);
|
||||||
confirmation.ErrorDescription = errorDescription;
|
|
||||||
}
|
}
|
||||||
|
return confirmationResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DoUpdateTransaction()
|
private void DoUpdateTransaction()
|
||||||
@ -739,18 +748,13 @@ namespace Creditcall.ChipDna.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PerformVoidTransaction()
|
public Dictionary<string, string> PerformVoidTransaction(string referenceValue)
|
||||||
{
|
{
|
||||||
var reference = GetReference(true, "");
|
var transactionResult = new Dictionary<string, string>();
|
||||||
var voidReason = GetUserInput("\r\nPlease Enter Void Reason (Optional)");
|
|
||||||
var parameters = new ParameterSet();
|
var parameters = new ParameterSet();
|
||||||
if (!string.IsNullOrEmpty(reference))
|
if (!string.IsNullOrEmpty(referenceValue))
|
||||||
{
|
{
|
||||||
parameters.Add(ParameterKeys.Reference, reference);
|
parameters.Add(ParameterKeys.Reference, referenceValue);
|
||||||
}
|
|
||||||
if (!String.IsNullOrEmpty(voidReason))
|
|
||||||
{
|
|
||||||
parameters.Add(ParameterKeys.VoidReason, voidReason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters.Add(GetExtraParams("VoidTransaction"));
|
parameters.Add(GetExtraParams("VoidTransaction"));
|
||||||
@ -778,12 +782,18 @@ namespace Creditcall.ChipDna.Client
|
|||||||
{
|
{
|
||||||
Console.WriteLine("ErrorDescription: {0}", errorDescription);
|
Console.WriteLine("ErrorDescription: {0}", errorDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var responseParameter = response.ToList();
|
||||||
|
responseParameter.ForEach(parameter =>
|
||||||
|
{
|
||||||
|
transactionResult.Add(parameter.Key, parameter.Value);
|
||||||
|
});
|
||||||
|
return transactionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PerformGetTransactionInformation()
|
public Dictionary<string, string> PerformGetTransactionInformation(string referenceValue)
|
||||||
{
|
{
|
||||||
var referenceValue = GetReference(true, "");
|
var result = new Dictionary<string, string>();
|
||||||
|
|
||||||
var parameters = new ParameterSet();
|
var parameters = new ParameterSet();
|
||||||
if (!string.IsNullOrEmpty(referenceValue))
|
if (!string.IsNullOrEmpty(referenceValue))
|
||||||
{
|
{
|
||||||
@ -794,18 +804,11 @@ namespace Creditcall.ChipDna.Client
|
|||||||
var response = chipDnaClientLib.GetTransactionInformation(parameters);
|
var response = chipDnaClientLib.GetTransactionInformation(parameters);
|
||||||
|
|
||||||
var responseParameter = response.ToList();
|
var responseParameter = response.ToList();
|
||||||
|
|
||||||
responseParameter.ForEach(parameter =>
|
responseParameter.ForEach(parameter =>
|
||||||
{
|
{
|
||||||
if (parameter.Key == ParameterKeys.Errors)
|
result.Add(parameter.Key, parameter.Value);
|
||||||
{
|
|
||||||
Console.WriteLine(ErrorsString("GetTransactionInformation Errors", parameter.Value));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine("{0} {1}", parameter.Key, parameter.Value);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetUserInput(string prompt)
|
private static string GetUserInput(string prompt)
|
||||||
@ -1458,6 +1461,7 @@ namespace Creditcall.ChipDna.Client
|
|||||||
|
|
||||||
private void ChipDnaClientLibOnPaymentDeviceAvailabilityChangeEvent(object sender, EventParameters connectionEventArgs)
|
private void ChipDnaClientLibOnPaymentDeviceAvailabilityChangeEvent(object sender, EventParameters connectionEventArgs)
|
||||||
{
|
{
|
||||||
|
var transactionResult = new Dictionary<string, string>();
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
connectionEventArgs.ToList().ForEach(param =>
|
connectionEventArgs.ToList().ForEach(param =>
|
||||||
{
|
{
|
||||||
@ -1475,7 +1479,9 @@ namespace Creditcall.ChipDna.Client
|
|||||||
{
|
{
|
||||||
stringBuilder.Append(string.Format("[{0}]", param.ToString()));
|
stringBuilder.Append(string.Format("[{0}]", param.ToString()));
|
||||||
}
|
}
|
||||||
|
transactionResult.Add(param.Key, param.Value);
|
||||||
});
|
});
|
||||||
|
_ = ErrorLogger.SendLogErrorAsync(transactionResult);
|
||||||
Console.WriteLine("{0}: {1}", "Payment Device Availability Change Event", stringBuilder);
|
Console.WriteLine("{0}: {1}", "Payment Device Availability Change Event", stringBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1501,6 +1507,11 @@ namespace Creditcall.ChipDna.Client
|
|||||||
|
|
||||||
private void ChipDnaClientLibOnErrorEvent(object sender, ClientHelperErrorEventArgs errorEventArgs)
|
private void ChipDnaClientLibOnErrorEvent(object sender, ClientHelperErrorEventArgs errorEventArgs)
|
||||||
{
|
{
|
||||||
|
var result = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ ParameterKeys.Errors, errorEventArgs.RaisedException.Message}
|
||||||
|
};
|
||||||
|
_ = ErrorLogger.SendLogErrorAsync(result);
|
||||||
PrintErrorEvent(errorEventArgs.RaisedException);
|
PrintErrorEvent(errorEventArgs.RaisedException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
202
ClientApp.cs
202
ClientApp.cs
@ -19,6 +19,7 @@ namespace Creditcall.ChipDna.Client
|
|||||||
private const int DefaultPort = 1869;
|
private const int DefaultPort = 1869;
|
||||||
private const string DefaultIpAddress = "127.0.0.1";
|
private const string DefaultIpAddress = "127.0.0.1";
|
||||||
private const bool DefaultSaveReceipt = false;
|
private const bool DefaultSaveReceipt = false;
|
||||||
|
private const int transactionTimeoutSeconds = 300;
|
||||||
|
|
||||||
private static Client client;
|
private static Client client;
|
||||||
|
|
||||||
@ -72,10 +73,18 @@ namespace Creditcall.ChipDna.Client
|
|||||||
{
|
{
|
||||||
HttpListener listener = new HttpListener();
|
HttpListener listener = new HttpListener();
|
||||||
listener.Prefixes.Add("http://127.0.0.1:18181/start-transaction/");
|
listener.Prefixes.Add("http://127.0.0.1:18181/start-transaction/");
|
||||||
|
listener.Prefixes.Add("http://127.0.0.1:18181/confirm-transaction/");
|
||||||
|
listener.Prefixes.Add("http://127.0.0.1:18181/transaction-information/");
|
||||||
|
listener.Prefixes.Add("http://127.0.0.1:18181/void-transaction/");
|
||||||
|
listener.Prefixes.Add("http://127.0.0.1:18181/chipdna-status/");
|
||||||
listener.Start();
|
listener.Start();
|
||||||
|
|
||||||
Console.WriteLine("Listening on:");
|
Console.WriteLine("Listening on:");
|
||||||
Console.WriteLine(" http://127.0.0.1:18181/start-transaction/");
|
Console.WriteLine(" http://127.0.0.1:18181/start-transaction/");
|
||||||
|
Console.WriteLine(" http://127.0.0.1:18181/confirm-transaction/");
|
||||||
|
Console.WriteLine(" http://127.0.0.1:18181/transaction-information/");
|
||||||
|
Console.WriteLine(" http://127.0.0.1:18181/void-transaction/");
|
||||||
|
Console.WriteLine(" http://127.0.0.1:18181/chipdna-status/");
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@ -95,6 +104,22 @@ namespace Creditcall.ChipDna.Client
|
|||||||
if (rawUrl.StartsWith("/start-transaction", StringComparison.OrdinalIgnoreCase))
|
if (rawUrl.StartsWith("/start-transaction", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
HandleStartTransaction(context);
|
HandleStartTransaction(context);
|
||||||
|
|
||||||
|
} else if (rawUrl.StartsWith("/confirm-transaction", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
HandleConfirmTransaction(context);
|
||||||
|
}
|
||||||
|
else if (rawUrl.StartsWith("/transaction-information", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
HandleTransactionInformation(context);
|
||||||
|
}
|
||||||
|
else if (rawUrl.StartsWith("/void-transaction", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
HandleVoidTransaction(context);
|
||||||
|
}
|
||||||
|
else if (rawUrl.StartsWith("/chipdna-status", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
HandleGetStatus(context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -115,21 +140,127 @@ namespace Creditcall.ChipDna.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void HandleGetStatus(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var statusResult = client.GetStatus();
|
||||||
|
var responseSerializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
||||||
|
context.Response.ContentType = "application/xml";
|
||||||
|
var wrappedResult = new SerializableKeyValueList(statusResult);
|
||||||
|
responseSerializer.Serialize(context.Response.OutputStream, wrappedResult);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error in -status: " + ex.Message);
|
||||||
|
context.Response.StatusCode = 500;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
context.Response.OutputStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleTransactionInformation(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serializer = new XmlSerializer(typeof(TransactionReferenceRequest));
|
||||||
|
TransactionReferenceRequest req = (TransactionReferenceRequest)serializer.Deserialize(context.Request.InputStream);
|
||||||
|
|
||||||
|
var transactionResult = client.PerformGetTransactionInformation(req.TransactionReference);
|
||||||
|
|
||||||
|
// Return the final key/value list
|
||||||
|
var responseSerializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
||||||
|
context.Response.ContentType = "application/xml";
|
||||||
|
var wrappedResult = new SerializableKeyValueList(transactionResult);
|
||||||
|
responseSerializer.Serialize(context.Response.OutputStream, wrappedResult);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error in transaction-information: " + ex.Message);
|
||||||
|
context.Response.StatusCode = 500;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
context.Response.OutputStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleVoidTransaction(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serializer = new XmlSerializer(typeof(TransactionReferenceRequest));
|
||||||
|
TransactionReferenceRequest req = (TransactionReferenceRequest)serializer.Deserialize(context.Request.InputStream);
|
||||||
|
|
||||||
|
var transactionResult = client.PerformVoidTransaction(req.TransactionReference);
|
||||||
|
|
||||||
|
// Return the final key/value list
|
||||||
|
var responseSerializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
||||||
|
context.Response.ContentType = "application/xml";
|
||||||
|
var wrappedResult = new SerializableKeyValueList(transactionResult);
|
||||||
|
responseSerializer.Serialize(context.Response.OutputStream, wrappedResult);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error in transaction-information: " + ex.Message);
|
||||||
|
context.Response.StatusCode = 500;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
context.Response.OutputStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleConfirmTransaction(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var serializer = new XmlSerializer(typeof(ConfirmTransactionRequest));
|
||||||
|
ConfirmTransactionRequest payload = (ConfirmTransactionRequest)serializer.Deserialize(context.Request.InputStream);
|
||||||
|
|
||||||
|
Console.WriteLine($"Received confirm transaction: Amount={payload.Amount}, TransactionReference={payload.TransactionReference}");
|
||||||
|
|
||||||
|
var confirmationResult = client.PerformConfirmTransaction(payload.TransactionReference, payload.Amount);
|
||||||
|
|
||||||
|
var responseSerializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
||||||
|
context.Response.ContentType = "application/xml";
|
||||||
|
var wrappedResult = new SerializableKeyValueList(confirmationResult);
|
||||||
|
responseSerializer.Serialize(context.Response.OutputStream, wrappedResult);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var errorMap = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ ParameterKeys.TransactionResult, "ERROR" },
|
||||||
|
{ ParameterKeys.Errors, $"ConfirmTransaction failed: {ex.Message}" }
|
||||||
|
};
|
||||||
|
|
||||||
|
var responseSerializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
||||||
|
context.Response.ContentType = "application/xml";
|
||||||
|
var wrappedResult = new SerializableKeyValueList(errorMap);
|
||||||
|
responseSerializer.Serialize(context.Response.OutputStream, wrappedResult);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
context.Response.OutputStream.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void HandleStartTransaction(HttpListenerContext context)
|
private static void HandleStartTransaction(HttpListenerContext context)
|
||||||
{
|
{
|
||||||
const int transactionTimeoutSeconds = 300;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var serializer = new XmlSerializer(typeof(TransactionPayload));
|
var serializer = new XmlSerializer(typeof(TransactionPayload));
|
||||||
TransactionPayload payload = (TransactionPayload)serializer.Deserialize(context.Request.InputStream);
|
TransactionPayload payload = (TransactionPayload)serializer.Deserialize(context.Request.InputStream);
|
||||||
|
|
||||||
Console.WriteLine($"Received start transaction: Amount={payload.amount}, Type={payload.transactionType}");
|
Console.WriteLine($"Received transaction request: Amount={payload.Amount}, Type={payload.TransactionType}");
|
||||||
|
|
||||||
client.TransactionCompletionSource = new TaskCompletionSource<Dictionary<string, string>>();
|
client.TransactionCompletionSource = new TaskCompletionSource<Dictionary<string, string>>();
|
||||||
|
|
||||||
// start transaction (non-blocking)
|
// start transaction (non-blocking)
|
||||||
client.PerformStartTransaction(payload.amount, payload.transactionType);
|
client.PerformStartTransaction(payload.Amount, payload.TransactionType);
|
||||||
|
|
||||||
// Wait for completion with timeout
|
// Wait for completion with timeout
|
||||||
var task = client.TransactionCompletionSource.Task;
|
var task = client.TransactionCompletionSource.Task;
|
||||||
@ -168,45 +299,6 @@ namespace Creditcall.ChipDna.Client
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it's a SALE and approved, call ConfirmTransaction and attach its XML
|
|
||||||
transactionResult.TryGetValue(ParameterKeys.TransactionType, out string txType);
|
|
||||||
transactionResult.TryGetValue(ParameterKeys.TransactionResult, out string txResult);
|
|
||||||
transactionResult.TryGetValue(ParameterKeys.Reference, out string txReference);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(txType) && txType.Equals("SALE", StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!string.IsNullOrEmpty(txResult) && txResult.Equals("APPROVED", StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!string.IsNullOrEmpty(txReference))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
TransactionConfirmation confirmation;
|
|
||||||
client.PerformConfirmTransaction(txReference, out confirmation);
|
|
||||||
|
|
||||||
// Keep original fields, but also add confirmation-prefixed fields
|
|
||||||
transactionResult["CONFIRM_RESULT"] = confirmation?.Result ?? "";
|
|
||||||
transactionResult["CONFIRM_ERRORS"] = confirmation?.Errors ?? "";
|
|
||||||
if (!string.IsNullOrEmpty(confirmation.ErrorDescription))
|
|
||||||
{
|
|
||||||
transactionResult["CONFIRM_ERRORS"] = $"{confirmation.Errors} {confirmation.ErrorDescription}";
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(confirmation?.ReceiptDataCardholder))
|
|
||||||
{
|
|
||||||
transactionResult[ParameterKeys.ReceiptDataCardholder] = confirmation.ReceiptDataCardholder;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XML (omit declaration so it can be embedded)
|
|
||||||
var xml = SerializeToXml(confirmation, omitXmlDeclaration: true);
|
|
||||||
transactionResult["TRANSACTION_CONFIRMATION"] = xml;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// preserve original transaction result but add an error key
|
|
||||||
transactionResult["CONFIRM_RESULT"] = "ERROR";
|
|
||||||
transactionResult["CONFIRM_ERRORS"] = $"ConfirmTransaction failed: {ex.Message}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the final key/value list as before
|
|
||||||
var responseSerializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
var responseSerializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
||||||
context.Response.ContentType = "application/xml";
|
context.Response.ContentType = "application/xml";
|
||||||
var wrappedResult = new SerializableKeyValueList(transactionResult);
|
var wrappedResult = new SerializableKeyValueList(transactionResult);
|
||||||
@ -221,6 +313,7 @@ namespace Creditcall.ChipDna.Client
|
|||||||
{
|
{
|
||||||
context.Response.OutputStream.Close();
|
context.Response.OutputStream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetAbsolutePath(string fileName)
|
private static string GetAbsolutePath(string fileName)
|
||||||
@ -308,11 +401,8 @@ namespace Creditcall.ChipDna.Client
|
|||||||
[XmlRoot("TransactionPayload")]
|
[XmlRoot("TransactionPayload")]
|
||||||
public class TransactionPayload
|
public class TransactionPayload
|
||||||
{
|
{
|
||||||
public string amount { get; set; }
|
public string Amount { get; set; }
|
||||||
public string transactionType { get; set; }
|
public string TransactionType { get; set; }
|
||||||
|
|
||||||
// For confirm transaction
|
|
||||||
public string transactionReference { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[XmlRoot("TransactionConfirmation")]
|
[XmlRoot("TransactionConfirmation")]
|
||||||
@ -322,6 +412,20 @@ namespace Creditcall.ChipDna.Client
|
|||||||
public string Errors { get; set; }
|
public string Errors { get; set; }
|
||||||
public string ErrorDescription { get; set; }
|
public string ErrorDescription { get; set; }
|
||||||
public string ReceiptDataCardholder { get; set; }
|
public string ReceiptDataCardholder { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[XmlRoot("TransactionReferenceRequest")]
|
||||||
|
public class TransactionReferenceRequest
|
||||||
|
{
|
||||||
|
[XmlElement("TransactionReference")]
|
||||||
|
public string TransactionReference { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[XmlRoot("ConfirmTransactionRequest")]
|
||||||
|
public class ConfirmTransactionRequest
|
||||||
|
{
|
||||||
|
public string Amount { get; set; }
|
||||||
|
public string TransactionReference { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
61
ErrorLogger.cs
Normal file
61
ErrorLogger.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace Creditcall.ChipDna.Client
|
||||||
|
{
|
||||||
|
public static class ErrorLogger
|
||||||
|
{
|
||||||
|
private static readonly HttpClient httpClient = new HttpClient
|
||||||
|
{
|
||||||
|
Timeout = TimeSpan.FromSeconds(10)
|
||||||
|
};
|
||||||
|
|
||||||
|
public static async Task SendLogErrorAsync(Dictionary<string, string> statusResult)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (statusResult == null || statusResult.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var url = "http://127.0.0.1:9091/logerror";
|
||||||
|
|
||||||
|
var wrappedResult = new SerializableKeyValueList(statusResult);
|
||||||
|
var serializer = new XmlSerializer(typeof(SerializableKeyValueList));
|
||||||
|
|
||||||
|
var ns = new XmlSerializerNamespaces();
|
||||||
|
ns.Add(string.Empty, string.Empty);
|
||||||
|
var settings = new XmlWriterSettings
|
||||||
|
{
|
||||||
|
OmitXmlDeclaration = false,
|
||||||
|
Indent = false,
|
||||||
|
Encoding = new UTF8Encoding(false)
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (var xw = XmlWriter.Create(ms, settings))
|
||||||
|
{
|
||||||
|
serializer.Serialize(xw, wrappedResult, ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = new ByteArrayContent(ms.ToArray());
|
||||||
|
content.Headers.ContentType =
|
||||||
|
new MediaTypeHeaderValue("application/xml");
|
||||||
|
|
||||||
|
await httpClient.PostAsync(url, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("SendLogErrorAsync failed: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user