From 71b28439e43cb7283f943cf3b7637530b2e314d0 Mon Sep 17 00:00:00 2001 From: Dima YaFlay <93622229+YaFlay@users.noreply.github.com> Date: Sun, 20 Aug 2023 22:19:47 +0300 Subject: [PATCH 1/2] Update README.md --- README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 34e428f..0d13424 100644 --- a/README.md +++ b/README.md @@ -17,16 +17,14 @@ dotnet add package spworlds ## Использование ```cs -using spworlds; - ... // в теле создаете новый обект типа spworlds в // констрактор вы ОБЯЗАННЫ передать передать параметры указанные ниже. Тип данных - стринг -SPWorlds sp = new SPworlds("[ваш айди]","[ваш токен]"); +// SPWorlds sp = new SPworlds("[ваш айди]", "[ваш токен]"); //так же я советую вам использовать dependancy injection и добавить в него данный обьект как сингл тон т.к он не -//требуется более чем в одном екземпляре и так-же вам не прейдется каждый раз прописывать строки указанные выше +//требуется более чем в одном экземпляре и так-же вам не прийдется каждый раз прописывать строки указанные выше //пример: using spworlds; @@ -36,7 +34,6 @@ SPWorlds sp = new SPworlds("[ваш айди]","[ваш токен]"); IServiceProvider = new IServiceColection() .AddSomething() // какойто добавляемый микросервис может быть что угодно .AddSingletone(sp) - .AddSomething() // какойто добавляемый микросервис может быть что угодно .Build(); // получение микросервиса в другом классе @@ -44,7 +41,7 @@ public class MyClass { private readonly sp; public MyClass(SPWorlds spInCtor) - // заметте мы в констракторе должы указать именно + // заметьте, мы в конструкторе должы указать именно //тип того синглтона который мы хотим получить, а название может быть любым { this.sp = sp; // мы передаем переменную другой т.к данная переменная доступна только в конструкторе @@ -58,12 +55,12 @@ public class MyClass Если вы хотите принимать оплату в АРах на своем сайте, используйте этот метод. -Получение ссылки на страницу оплаты 16 АР, после успешной оплаты пользователь перейдет со страницы оплаты на `https://eximple.com/success`, а сайт СП отправит запрос на `https://api.example.com/webhook` с данными этого платежа, в том числе и `SomeString`. Последнее поле можно использовать, например, для ID заказа или чего-то подобного или вставить туда json а потом его десериализовать в объект. +Получение ссылки на страницу оплаты 16 АР, после успешной оплаты пользователь перейдет со страницы оплаты на `https://eximple.com/success`, а сайт СП отправит запрос на `https://api.example.com/webhook` с данными этого платежа, в том числе и `SomeString`. Последнее поле можно использовать, например, для ID заказа или чего-то подобного или вставить туда json а потом его десериализовать в объект после оплаты, так как он возвращается вместе с вебхуком об успешной оплате. ```cs const url = await sp.InitPayment( 16, - "https://eximple.com/success", + "https://example.com/success", "https://api.example.com/webhook", "SomeString" ); From 6b077865307791e5f750f3cbf884247cc991dba2 Mon Sep 17 00:00:00 2001 From: Dima YaFlay <93622229+YaFlay@users.noreply.github.com> Date: Sun, 20 Aug 2023 22:46:44 +0300 Subject: [PATCH 2/2] Add validate_webhook method --- src/spworlds.cs | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/src/spworlds.cs b/src/spworlds.cs index 361c36e..ba03877 100644 --- a/src/spworlds.cs +++ b/src/spworlds.cs @@ -1,7 +1,9 @@ -using System.Net.Http.Headers; +using System.Net.Http.Headers; using System.Text.Json; using System.Text; using System.Text.Json.Nodes; +using System.Security.Cryptography; +using System.Runtime.InteropServices; namespace spworlds; @@ -13,27 +15,48 @@ public class SPWorlds { client = new HttpClient(); var BearerToken = $"{id}:{token}"; + var token = token string Base64BearerToken = Convert.ToBase64String(Encoding.UTF8.GetBytes(BearerToken)); client.BaseAddress = new Uri("https://spworlds.ru/api/public/"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Base64BearerToken); } + private async Task ValidateWebhook(string webhook, string body_hash) + { + // Если я правильно все понял, то вот + // Конвертим из string в bytes body_hash + byte[] body = Encoding.UTF8.GetBytes(body_hash); + // потом конвертим вебхук + byte[] webhook = Encoding.UTF8.GetBytes(webhook); + // создаем объект с токеном(тоже encoded в bytes) для сопостовления + var key = new HMACSHA256(Encoding.UTF8.GetBytes(token)); + // Переводим в Base64 + string webhook_64 = Convert.ToBase64String(key.ComputeHash(webhook)); + return webhook_64.Equals(body); + /** + * Тот же код, но на Python: + hmac_data = hmac.new(token.encode('utf - 8'), webhook.encode('utf - 8'), sha256).digest() + base64_data = b64encode(hmac_data) + return hmac.compare_digest(base64_data, body_hash.encode('utf-8')) + **/ + } + private async Task SendRequest(string endpoint, Boolean getResult = true, Dictionary? body = null) { string respond; string jsonBody; - - if(body == null) + + if (body == null) { return respond = client.GetAsync(endpoint).Result.Content.ReadAsStringAsync().Result; } - else + else { jsonBody = JsonSerializer.Serialize(body); var payload = new StringContent(jsonBody, Encoding.UTF8, "application/json"); - if(getResult) + if (getResult) return respond = client.PostAsync(endpoint, payload).Result.Content.ReadAsStringAsync().Result; else await client.PostAsync(endpoint, payload); @@ -42,7 +65,7 @@ public class SPWorlds return null; } - public async Task GetBalance() + public async Task GetBalance() { string respond = await SendRequest("card"); @@ -52,7 +75,7 @@ public class SPWorlds return (int)balance; } - public async Task CreatTransaction(string receiver, int amount, string comment) + public async Task CreateTransaction(string receiver, int amount, string comment) { var transitionInfo = new Dictionary { @@ -82,9 +105,9 @@ public class SPWorlds { "data", data } }; - var payment = JsonObject.Parse(await SendRequest(endpoint: $"payment",body: paymentInfo)); + var payment = JsonObject.Parse(await SendRequest(endpoint: $"payment", body: paymentInfo)); var url = payment["url"]; return (string)url; } -} \ No newline at end of file +}