I have a webhook call from a third party which is a complex JSON object, in this object, there are some datetime fields like this 2023-04-05T14:13:47+0200
, so when I parse this JSON with C#, the result is 2023-04-05T14:13:47+02:00
, and that causes an issue when calculating the hash code.
This is the JSON:
{
"message": "OK",
"code": 200,
"current_time": "2023-04-05T14:13:50+0200",
"order": {
"uuid": "45B32B3C-B01A-4D82-A03B-D5D9709DC92C",
"created": "2023-04-05T14:13:47+0200",
"created_from_client_timezone": "2023-04-05T14:13:47+0200",
"amount": 1000,
"currency": "978",
"paid": false,
"status": "CREATED",
"safe": true,
"refunded": 0,
"additional": null,
"service": "REDSYSPSD2",
"service_uuid": "F9D76AE8-DDBB-4F17-8074-C2DABEE0A919",
"customer": "test2222",
"cof_txnid": null,
"transactions": [],
"token": "345e77cc5a2616030ef5965d5513e1088adbd087b637da99eefc80f0729c943a26ef5e3a45b454819c62015e3d74f3282ecd2e1ab0b99a34de46d8aa37106a3d",
"ip": null,
"urls": {
"payment_card":"http:\/\/ws.paylands.loc\/su\/QY6cnT3MasUB",
"bizum":"http:\/\/ws.paylands.loc\/su\/0SWxTAvN0QkJ",
"3ds_tokenized":"http:\/\/ws.paylands.loc\/su\/3wEDqxIhjjsD"
},
"reference": null,
"dynamic_descriptor": "\u00eb\u00f1a,\u00e1ds,\u00f4 \u00f2,",
"threeds_data": null
},
"client": {
"uuid":"42B8CF56-A7D7-4D4A-8349-4E27263CB2D5"
},
"validation_hash": "414c8190e6b15ac767ff3217e994ef8687368ec8ebe6ab9ad570799d2f746cb7"
}
And this is how the validation_hash is calculated:
var jsonDe = JsonConvert.DeserializeObject<dynamic>(requestBody);
var signatureData = JsonConvert.SerializeObject(new Dictionary<string, object>
{
{ "order", jsonDe.order },
{ "client", jsonDe.client },
});
var signature = CalculateSHA256Hash(signatureData + settings.Signature);
if (signature != dto.ValidationHash)
{
serviceResult.AddError(0, _localizationRepository.Get("The request is invalid."));
return serviceResult;
}
static string CalculateSHA256Hash(string input)
{
using (SHA256 sha256Hash = SHA256.Create())
{
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
builder.Append(bytes[i].ToString("x2"));
}
return builder.ToString();
}
}
I have tested several converters, but none of them could fix the issue of not adding :
to the DateTime field.
I modified the fields after the DeserializeObject and removed the last :
but that's not something I would prefer, so is there any other solution for this issue?
FYI, this is an example from their support with PHP: https://onlinephp.io/c/4a0c8
If you are using Newtonsoft's Json.NET (the one with JsonConvert
) - then simply disable the automatic DateTime
handling (also I recommend switching from using dynamic
to types exposed by the library for dynamic JSON handling):
var requestBody = """
{
"current_time": "2023-04-05T14:13:50+0200",
"order": {
"uuid": "45B32B3C-B01A-4D82-A03B-D5D9709DC92C",
"created": "2023-04-05T14:13:47+0200",
"created_from_client_timezone": "2023-04-05T14:13:47+0200",
}
}
""";
var jsonDe = JsonConvert.DeserializeObject<JToken>(requestBody, new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None
});
Console.WriteLine(jsonDe["current_time"].ToString()); //2023-04-05T14:13:50+0200
Console.WriteLine(jsonDe["order"]["created_from_client_timezone"].ToString()); // 2023-04-05T14:13:47+0200
var signatureData = JsonConvert.SerializeObject(new Dictionary<string, object>
{
{ "order", jsonDe["order"] },
{ "client", jsonDe["client"] },
}); // {"order":{"uuid":"45B32B3C-B01A-4D82-A03B-D5D9709DC92C","created":"2023-04-05T14:13:47+0200","created_from_client_timezone":"2023-04-05T14:13:47+0200"},"client":null}
For System.Text.Json
(if you decide to switch) - use similar API for example JsonNode
(works out of the box for me, no date handling happening):
var jsonNode = JsonSerializer.Deserialize<JsonNode>(requestBody); // or JsonNode.Parse
Console.WriteLine(jsonNode["order"]["created_from_client_timezone"].ToString()); // 2023-04-05T14:13:47+0200
P.S.
Be sure that indentation is also handled in the same way on both sides.