Yandex.Checkout.V3
Yandex.Checkout.V3 copied to clipboard
Неверная сериализация в AsyncClient.CreatePayoutAsync
Столкнулся с проблемой, что у Юкассы в этом методе особо хитрое требование к формату валюты. Требуется два нуля после запятой, чего при обычной сериализации не бывает.
Например если вызвать Serializer.SerializeObject(payout);
То получится следующий JSON
{
"amount": {
"value": 169.0, <== ТУТ
"currency": "RUB"
},
"description": "Выплата",
"metadata": {
"paymentId": "08f2ac771d80496f91c083832bbfd54d",
"payoutId": "03f3137e83d94d8494b70db54088bbaf",
"salt": "ba6a6accd9844ce3af991465ccbdfe24"
},
"payout_token": "16VCK88aSGbyWsYpGhAa31QR.SC.003.202403",
"deal": {
"id": "dl-2e567c1f-0022-5000-8000-064e574a201a"
}
}
Однако его отправка приводит к ошибке
Yandex.Checkout.V3.YandexCheckoutException: Error in the payout amount. Specify the amount in the correct format. For example, 100.00 amount.value
Из-за это приходится использовать вот такой костыль)
public async Task<Payout> CreatePayoutAsync(NewPayout payout, string idempotenceKey, CancellationToken ct)
{
// В клиенте есть нужный метод, но он вызывает ошибку
// Yandex.Checkout.V3.YandexCheckoutException: Error in the payout amount. Specify the amount in the correct format. For example, 100.00 amount.value
// return await _client.CreatePayoutAsync(payout, idempotenceKey, ct);
// Последний раз проверял на версии 4.2.0
var badJson = Serializer.SerializeObject(payout);
// Надо поменять "value":4250.0, на "value":"4250.00",
var start = badJson.IndexOf("\"value\":", StringComparison.InvariantCulture) + 8;
var end = badJson.IndexOf(',', start);
var amount = badJson.Substring(start, end - start);
var requestJson = badJson.Replace(amount, $"\"{amount}0\"");
if (badJson == requestJson)
{
throw new InvalidOperationException($"Nothing replaced. Amount={amount} Json={badJson}");
}
var authenticationString = $"{_options.ShopId}:{_options.SecretKey}";
var base64String = Convert.ToBase64String(Encoding.ASCII.GetBytes(authenticationString));
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.yookassa.ru/v3/payouts")
{
Content = new StringContent(requestJson, Encoding.UTF8, "application/json"),
};
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64String);
request.Headers.Add("Idempotence-Key", idempotenceKey);
using var httpClient = _httpClientFactory.CreateClient();
var response = await httpClient.SendAsync(request, ct);
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException($"Cannot create payout. Request={requestJson} Response={json}");
}
return Serializer.DeserializeObject<Payout>(json);
}