Пример вызова на C#
---------------------------------------------------------------------------------------------------------------------------------------
непосредственный вызов: 1. проверка балансов. 2. сравнение с минимальной комиссией для перевода на адрес. 3. перевод на адрес.
---------------------------------------------------------------------------------------------------------------------------------------
private static async Task CallWebApiMethods()
{
string key = "mySecretKeyValue"; // получать здесь https://paymer.com/ci/Personal/Settings (блок "Настройка Api-ключей")
string name = "mySecretKeyName";
string bc = "TRX";
string addressToWithdraw = "TMYQbPaRSjiPEvv6txN5BEtmu9kGspnKgo";
decimal amountToWithdraw = 10000m;
string cult = "ru-RU";
Random rnd = new Random();
int extRequestId = -rnd.Next(10, 1000); // идентификатор заявки в системе вызывающего сервис
SandboxWebApiLogic swal = new SandboxWebApiLogic(key, name);
TotalBalancesResponse resptb = await swal.ExecuteTotalBalancesAsync(CancellationToken.None);
if (resptb.RetCode != 0)
{
// ошибка, неверные параметры ввода
return;
}
IssueParms issue = resptb.Issues?
.FirstOrDefault(i =>
i.Blockchain == bc &&
i.NativeBalance > 0 &&
i.OrdersSummary?.Any(o => o.Balance >= amountToWithdraw) == true);
// у вас этот элемент будет всегда единственный. в принципе их может быть несколько
if (issue == null)
{
// ошибка, выпуск с чеками с достаточным балансом и нужным блокчейном не найден
return;
}
GetFeeRequest dataf = new GetFeeRequest
{
Blockchain = bc,
Amount = amountToWithdraw,
Cult = cult
};
GetFeeResponse respf = await swal.ExecuteGetFeeAsync(dataf, CancellationToken.None);
if (respf.RetCode != 0)
{
// ошибка, неверные параметры ввода
return;
}
decimal maxFeeToWithdraw = respf.SingleFee;
if (issue.NativeBalance < maxFeeToWithdraw)
{
// ошибка, не хватает нативной валюты для проведения вывода. нужно пополнить (как правило 30 TRX)
return;
}
WithdrawRequest dataw = new WithdrawRequest
{
Address = addressToWithdraw,
Blockchain = bc,
Amount = amountToWithdraw,
ExtRequestId = extRequestId,
MaxFee = maxFeeToWithdraw,
Cult = cult
};
WithdrawResponse respw = await swal.ExecuteWithdrawAsync(dataw, CancellationToken.None);
if (respw.RetCode != 0)
{
// ошибка при создании заявки на вывод
return;
}
// txHash формируется и записывается в систему обычно через 500-1000ms
// для получения txHash нужно вызвать повторно с тем же ExtRequestId
Thread.Sleep(1000);
respw = await swal.ExecuteWithdrawAsync(dataw, CancellationToken.None);
string txHash = respw.TxParams[0].Hash;
string txHashUrl = respw.TxParams[0].HashUrl;
}
---------------------------------------------------------------------------------------------------------------------------------------
вызовы методов
---------------------------------------------------------------------------------------------------------------------------------------
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
public class SandboxWebApiLogic : CallWebApi
{
public SandboxWebApiLogic(string appKeyId, string pk)
{
AppKeyId = appKeyId;
AppKeyValue = pk;
}
public async Task<TotalBalancesResponse> ExecuteTotalBalancesAsync(CancellationToken cancellationToken)
{
string url = "https://paymer.com/ci/webapi/get_total_balance";
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url)
{
Headers =
{
{ HttpRequestHeader.ContentType.ToString(), "application/json" },
}
})
{
request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
HttpRequestMessage signedRequestMessage = await SignRequestAsync(request);
HttpResponseMessage response = await HttpClient.SendAsync(
signedRequestMessage,
HttpCompletionOption.ResponseHeadersRead,
cancellationToken);
response.EnsureSuccessStatusCode();
string stream = await response.Content.ReadAsStringAsync();
TotalBalancesResponse res =
JsonConvert.DeserializeObject<TotalBalancesResponse>(stream);
return res;
}
}
public async Task<GetFeeResponse> ExecuteGetFeeAsync(GetFeeRequest data, CancellationToken cancellationToken)
{
string url = "https://paymer.com/ci/webapi/get_fee";
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url))
{
StringContent content = new StringContent(JsonConvert.SerializeObject(data));
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
request.Content = content;
request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
HttpRequestMessage signedRequestMessage = await SignRequestAsync(request);
HttpResponseMessage response = await HttpClient.SendAsync(
signedRequestMessage,
HttpCompletionOption.ResponseHeadersRead,
cancellationToken);
response.EnsureSuccessStatusCode();
string responseText = await response.Content.ReadAsStringAsync();
GetFeeResponse res = JsonConvert.DeserializeObject<GetFeeResponse>(responseText);
return res;
}
}
public async Task<WithdrawResponse> ExecuteWithdrawAsync(WithdrawRequest data, CancellationToken cancellationToken)
{
string url = "https://paymer.com/ci/webapi/withdraw";
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url))
{
StringContent content = new StringContent(JsonConvert.SerializeObject(data));
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
request.Content = content;
request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
using (HttpRequestMessage signedRequestMessage = await SignRequestAsync(request))
{
HttpResponseMessage response = await HttpClient.SendAsync(
signedRequestMessage,
HttpCompletionOption.ResponseHeadersRead,
cancellationToken);
response.EnsureSuccessStatusCode();
string responseText = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<WithdrawResponse>(responseText);
}
}
}
}
---------------------------------------------------------------------------------------------------------------------------------------
метод подписи
---------------------------------------------------------------------------------------------------------------------------------------
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
public class CallWebApi
{
protected string AppKeyId;
protected string AppKeyValue;
protected static readonly HttpClient HttpClient = new HttpClient();
public CallWebApi(string appKeyId, string pk)
{
AppKeyId = appKeyId;
AppKeyValue = pk;
}
public string Hash(string key)
{
using (var sha256 = SHA256.Create())
{
var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(key));
return Convert.ToBase64String(hashedBytes);
}
}
public async Task<HttpRequestMessage> SignRequestAsync(HttpRequestMessage request)
{
string contentMd5 = string.Empty;
if (request.Content != null)
{
byte[] content = await request.Content.ReadAsByteArrayAsync();
using (MD5 md5 = MD5.Create())
{
byte[] contentMd5Hash = md5.ComputeHash(content);
request.Content.Headers.ContentMD5 = contentMd5Hash;
contentMd5 = Convert.ToBase64String(contentMd5Hash);
}
}
string hashedKey = Hash($"{AppKeyValue}{contentMd5}");
request.Headers.Authorization =
new AuthenticationHeaderValue(
"APIAuth-HMAC-SHA256",
$"{AppKeyId}:{hashedKey}");
return request;
}
}
---------------------------------------------------------------------------------------------------------------------------------------
структуры
---------------------------------------------------------------------------------------------------------------------------------------
// для получения баланса
[Serializable]
public class TotalBalancesRequest
{
public TotalBalancesRequest()
{
}
public decimal NeedAmount { get; set; }
public string Blockchain { get; set; }
public string Cult { get; set; }
}
[Serializable]
public class TotalBalancesResponse
{
public TotalBalancesResponse()
{
}
public TotalBalancesResponse(List<IssueParms> issues)
{
Issues = issues;
}
public List<IssueParms> Issues { get; set; }
public int RetCode { get; set; }
public string ErrorMessage { get; set; }
}
[Serializable]
public class IssueParms
{
public IssueParms()
{
}
public decimal Balance { get; set; }
public decimal NativeBalance { get; set; }
public string Blockchain { get; set; }
public int CoreIssueId { get; set; }
public List<OrderSummary> OrdersSummary { get; set; }
public ComplianceStatus AmlStatus { get; set; }
}
[Serializable]
public class OrderSummary
{
public OrderSummary()
{
}
public decimal Amount { get; set; }
public decimal Balance { get; set; }
}
// представляет допустимость транзакции
[JsonConverter (typeof (StringEnumConverter))]
public enum ComplianceStatus
{
[EnumMember (Value = "approve")]
Approve = 0,
[EnumMember (Value = "reject")]
Reject = 1,
[EnumMember (Value = "pending")]
Pending = 2,
[EnumMember (Value = "error")]
Error = 3
}
*********************************************************************************************************************
// для получения минимальной суммы комиссии, необходимой для перевода
[Serializable]
public class GetFeeRequest
{
public GetFeeRequest()
{
}
public decimal Amount { get; set; }
public string Blockchain { get; set; }
public string Cult { get; set; }
}
[Serializable]
public class GetFeeResponse
{
public GetFeeResponse()
{
}
public decimal TotalFee { get; set; }
public decimal SingleFee { get; set; }
public decimal SingleAvailableAmount { get; set; }
public int RetCode { get; set; }
public string ErrorMessage { get; set; }
}
*********************************************************************************************************************
// для перевода на адрес
[Serializable]
public class WithdrawRequest
{
public WithdrawRequest()
{
}
public string Address { get; set; }
public string Blockchain { get; set; }
public decimal Amount { get; set; }
public decimal MaxFee { get; set; }
public int ExtRequestId { get; set; }
public string Cult { get; set; }
}
[Serializable]
public class WithdrawResponse
{
public WithdrawResponse()
{
}
public int RetCode { get; set; }
public string RetDesc { get; set; }
public TxParams[] TxParams { get; set; }
}
public class TxParams
{
public TxParams()
{
}
public TxParams(string hash, string hashUrl, int reqStatus)
{
Hash = hash;
HashUrl = hashUrl;
RequestStatus = reqStatus;
}
public string Hash { get; set; }
public string HashUrl { get; set; }
public int RequestStatus { get; set; }
}