HitBTC api POST request, C# - c#

I know how to do a GET request, but POST does not work:
public string Order()
{
var client = new RestClient("http://api.hitbtc.com");
var request = new RestRequest("/api/2/order", Method.POST);
request.AddQueryParameter("nonce", GetNonce().ToString());
request.AddQueryParameter("apikey", HapiKey);
// request.AddParameter("clientOrderId", "");
request.AddParameter("symbol", "BCNUSD");
request.AddParameter("side", "sell");
request.AddParameter("quantity", "10");
request.AddParameter("type", "market");
var body = string.Join("&", request.Parameters.Where(x => x.Type == ParameterType.GetOrPost));
string sign = CalculateSignature(client.BuildUri(request).PathAndQuery + body, HapiSecret);
request.AddHeader("X-Signature", sign);
var response = client.Execute(request);
return response.Content;
}
private static long GetNonce()
{
return DateTime.Now.Ticks * 10;
}
public static string CalculateSignature(string text, string secretKey)
{
using (var hmacsha512 = new HMACSHA512(Encoding.UTF8.GetBytes(secretKey)))
{
hmacsha512.ComputeHash(Encoding.UTF8.GetBytes(text));
return string.Concat(hmacsha512.Hash.Select(b => b.ToString("x2")).ToArray());
}
}
Error: code: 1001, "Authorization required".
Where is my failure? Is "apikey" and "X-Signature" not correct for v2 anymore?
Thank you very much for helping me!

Please review authentication documentation.
You need to use Basic authentication using public and private key.
Example for RestSharp:
var client = new RestClient("https://api.hitbtc.com")
{
Authenticator = new HttpBasicAuthenticator(<PublicKey>, <SecretKey>)
};
For creating API keys you need to visit Setting page.
Also for your API action you need to set "Place/cancel orders" permission to true.
Details on the screenshot:
Also here is full code which works for me well:
var client = new RestClient("https://api.hitbtc.com")
{
Authenticator = new HttpBasicAuthenticator(PublicKey, SecretKey)
};
var request = new RestRequest("/api/2/order", Method.POST)
{
RequestFormat = DataFormat.Json
};
request.AddParameter("symbol", "BCNUSD");
request.AddParameter("side", "sell");
request.AddParameter("quantity", "10");
request.AddParameter("type", "market");
request.AddParameter("timeInForce", "IOC");
var response = client.Execute(request);
if (!response.IsSuccessful)
{
var message = $"REQUEST ERROR (Status Code: {response.StatusCode}; Content: {response.Content})";
throw new Exception(message);
}

Related

RestSharp post request - Body with x-www-form-urlencoded values

I am using postman and making an api post request where I am adding body with x-www-form-urlencoded key/values and it works fine in postman.
The issue arrises when I try it from c# using RestSharp package.
I have tried the following code below but not getting the response. I get "BadRequest" invalid_client error.
public class ClientConfig {
public string client_id { get; set; } = "value here";
public string grant_type { get; set; } = "value here";
public string client_secret { get; set; } = "value here";
public string scope { get; set; } = "value here";
public string response_type { get; set; } = "value here";
}
public void GetResponse() {
var client = new RestClient("api-url-here");
var req = new RestRequest("endpoint-here",Method.POST);
var config = new ClientConfig();//values to pass in request
req.AddHeader("Content-Type","application/x-www-form-urlencoded");
req.AddParameter("application/x-www-form-urlencoded",config,ParameterType.RequestBody);
var res = client.Execute(req);
return;
}
//Also tried this
req.AddParameter("client_id",config.client_id,"application/x-www-form-urlencoded",ParameterType.RequestBody);
req.AddParameter("grant_type",config.grant_type,"application/x-www-form-urlencoded",ParameterType.RequestBody);
req.AddParameter("client_secret",config.client_secret,"application/x-www-form-urlencoded",ParameterType.RequestBody);
req.AddParameter("scope",config.scope,ParameterType.RequestBody);
req.AddParameter("response_type",config.response_type,"application/x-www-form-urlencoded",ParameterType.RequestBody);
//tried this too
var client = new RestClient("url-here");
var req = new RestRequest("endpointhere",Method.POST);
var config = new ClientConfig();
req.AddBody(config);
var res = client.Execute(req);
this working for me, it was generator from postman
var token = new TokenValidation()
{
app_id = CloudConfigurationManager.GetSetting("appId"),
secret = CloudConfigurationManager.GetSetting("secret"),
grant_type = CloudConfigurationManager.GetSetting("grant_type"),
Username = CloudConfigurationManager.GetSetting("Username"),
Password = CloudConfigurationManager.GetSetting("Password"),
};
var client = new RestClient($"{xxx}{tokenEndPoint}");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", $"app_id={token.app_id}&secret={token.secret}&grant_type={token.grant_type}&Username={token.Username}&Password={token.Password}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
if (response.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine("Access Token cannot obtain, process terminate");
return null;
}
var tokenResponse = JsonConvert.DeserializeObject<TokenValidationResponse>(response.Content);
I personally find this way to work better for me when sending Form-UrlEncoded data.
public void GetResponse() {
var client = new RestClient("api-url-here");
var req = new RestRequest("endpoint-here",Method.POST);
var config = new ClientConfig();//values to pass in request
// Content type is not required when adding parameters this way
// This will also automatically UrlEncode the values
req.AddParameter("client_id",config.client_id, ParameterType.GetOrPost);
req.AddParameter("grant_type",config.grant_type, ParameterType.GetOrPost);
req.AddParameter("client_secret",config.client_secret, ParameterType.GetOrPost);
req.AddParameter("scope",config.scope, ParameterType.GetOrPost);
req.AddParameter("response_type",config.response_type, ParameterType.GetOrPost);
var res = client.Execute(req);
return;
}
Details on this parameter type can be found here:
https://github.com/restsharp/RestSharp/wiki/ParameterTypes-for-RestRequest#getorpost
Personally, I found AddObject() method quite useful, and cleaner when you have so many parameters to add.
public void GetResponse() {
var client = new RestClient("api-url-here");
var req = new RestRequest("endpoint-here",Method.POST);
var config = new ClientConfig();//values to pass in request
req.AddHeader("Content-Type","application/x-www-form-urlencoded");
req.AddObject(config);
var res = client.Execute(req);
return res;
}
If it worked on postman, you can just press the code button on the right hand side. This will provide a working example in multiple languages. It is the button above the information icon. I would post a screenshot of it, but I don't have 10 reputation to do so.
i have found this good for my scenario , it is working perfect,
var client = new RestClient("https://test.salesforce.com/services/oauth2/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=password&client_id=3MVG9U_dUptXGpYKew7P.oPwrIsvowP_K4CsnkxHJIEOUJzW0XBUUY3o12bLDasjeIPGVobvBZo8TNFcCY6J3&client_secret=3189542819149073716&username=integraciones%40lamarina.com.mx.dev&password=2Password!4iwZvMQKVAwkYyJRy50JlAHk", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine("Response.StatusCode: " + response.StatusCode);
Console.WriteLine("Response.Content: " + response.Content);
Console.WriteLine("Response.ErrorMessage: " + response.ErrorMessage);
https://dotnetfiddle.net/J64FR5
in my case this is what worked
req.AddParameter("client_id", "unigen-corporation", ParameterType.HttpHeader);
req.AddParameter("grant_type", "client_credentials", ParameterType.GetOrPost);
If you've copied the code from the postman, try removing the following:
request.AlwaysMultipartFormData = true;
In my case after removing this line code worked.
var client1 = new RestClient(URI);
var request1 = new RestRequest(Method.POST);
request1.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request1.AddParameter("client_id", "XX");
request1.AddParameter("client_secret", "XX");
request1.AddParameter("grant_type", "XX");
request1.AddParameter("role", "XX");
IRestResponse response1 = client1.Execute(request1);
System.Console.WriteLine(response1.Content);
Add parameters according to your needs. This work fine!
for my code, this works perfect.
// extention function for object->formed data body string
public static string toFormDataBodyString(this object src)
{
var res = new List<string>();
foreach (var key in src.GetType().GetProperties())
{
res.Add($"{key.Name}={src.GetType().GetProperty(key.Name)?.GetValue(src)}");
}
return string.Join("&", res);
}
//--------------------------------------
var data = new {
param1 = xxxx,
param2 = xxxx
}
var translateReq = new RestRequest("url_here")
.AddHeader("Content-Type", "application/x-www-form-urlencoded")
.AddParameter("application/x-www-form-urlencoded", data.toFormDataBodyString(), ParameterType.RequestBody);

How to mimic this using RESTSHARP C# restclient instead of using httpclient?

I am using httpclient to invoke a endpoint , this is working fine for me. But i need to invoke the endpoint using the restsharp restclient object. How can i do that? Here is the code that works for me using the http client postasync.
//Input Parameters and request headers
string userID = "testuser";
string memberId = "001";
string baseURL = "https://www.test.com";
string urlParameters ="TestServices/GetAll/{0}/{1}/{2}/{3}/{4}/{5}";
string contentType = "application/json";
string role = "USER";
string Caller = "PREVIEW";
string ticks = DateTime.Now.Ticks.ToString();
string systemId = "613e70b3-e3ec-4205-bcd6-094d6a9f7a41";
string encryptedToken = “XXXXXXXXXXXXXXXXXXXX”
string sessionID = "8303d34a-5c8a-4984-9bf9-4ba39be21352";
//data to be send as stringcontent
string postData = "{\"TheContentAreas\":[{\"ControlTypeID\":\"230c5669-aa0d-41bc-9069-559b5e7d0ece\",\"PlaceholderID\":\"a16a471e-9416-43fc-8ceb-fddb97509e0c\"}]}";
string response = string.Empty;
//call the end point
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(baseURL);
client.DefaultRequestHeaders.Add("Authorization", "XXXXXXXXXXXXXXXXXXXXXXX");
client.DefaultRequestHeaders.Add("Session", sessionID);
client.DefaultRequestHeaders.Add("EncryptedKey", encryptedToken);
try
{
HttpResponseMessage resp = client
.PostAsync(string.Format(urlParameters, role, systemId, Caller, ticks, userID, memberId),
new StringContent(postData, System.Text.Encoding.UTF8, "application/json")).Result;
if (resp.IsSuccessStatusCode)
{
response = resp.Content.ReadAsStringAsync().Result;
}
}
I spent some time working on it, here is my solution.
I created a generic service invoker class and called it from my main class.
//Main class calling the service invoker
try
{
var _restMethodInvoker = new RestEndPointInvoker();
var headers = new Dictionary<string, string>
{
{ "Authorization", "xxx" },
{ "Session", "xxx" } ,
{ "EncryptedKey", "xxx"}
};
var inputParameters = new Dictionary<string, string>
{
{ "Role", "MEMBER" },
{ "SystemID", "xxx" } ,
{ "Caller", "PREVIEW" } ,
{ "Ticks", "1234" } ,
{ "UserID", "TestUser" } ,
{ "MemberId", "TestMEmber" }
var request1 = new RestClientRequest
{
_apiMethod = "TestServices/GetAll/{Role}/{SystemID}/{Caller}/{Ticks}/{UserID}/{MemberId}",
_environmentType = "xx",
_inputParameters = inputParameters,
_requestHeaders = headers
};
var result1 = _restMethodInvoker.GetAsync<List<ReturnType>>(request1);
var result = result1.Result;
}
catch (Exception ex)
{
throw ex;
}
Rest Invoker class using restsharp
namespace RestServiceInvoker
{
public class RestEndPointInvoker : IRestEndPointInvoker
{
public RestEndPointInvoker()
{
_httpClient = new RestClient();
}
private void BuildRestClient(RestClientRequest request)
{
//Set the headers
foreach (var header in request._requestHeaders)
{
_httpClient.AddDefaultHeader(header.Key, header.Value);
}
}
public async Task<IRestResponse<T>> GetAsync<T>(RestClientRequest request) where T: new()
{
//Build the client object
BuildRestClient(request);
//Build request object
var restRequest = BuildRestReqestObject(request);
//var response11 = _httpClient.Execute<T>(restRequest);
var taskSource = new TaskCompletionSource<IRestResponse<T>>();
//Execute the request
_httpClient.ExecuteAsync<T>(restRequest, response =>
{
if (response.ErrorException != null)
taskSource.TrySetException(response.ErrorException);
else
taskSource.TrySetResult(response);
});
return await taskSource.Task;
}
private RestRequest BuildRestReqestObject(RestClientRequest requestObj)
{
var request = new RestRequest {Resource = requestObj._apiMethod};
if (requestObj._inputParameters == null || requestObj._inputParameters.Count <= 0) return request;
foreach (var inputParam in requestObj._inputParameters)
{
request.AddParameter(inputParam.Key, inputParam.Value, ParameterType.UrlSegment);
}
request.Method = Method.POST; //This could be parameterized from the client. For now we are only supporting get calls
//This would be sent as input parameter. Just was lazy to hardcode it here
string jsonToSend = #"xxxxxxxxxxx";
request.AddParameter("application/json; charset=utf-8", jsonToSend, ParameterType.RequestBody);
return request;
}
}
}

How to implement apple token based push notifications (using p8 file) in C#?

For an app with some kind of chat based features I want to add push notification support for receiving new messages.
What I want to do is use the new token based authentication (.p8 file) from Apple, but I can't find much info about the server part.
I came across the following post:
How to use APNs Auth Key (.p8 file) in C#?
However the answer was not satisfying as there was not much detail about how to:
establish a connection with APNs
use the p8 file (except for some kind of encoding)
send data to the Apple Push Notification Service
You can't really do this on raw .NET Framework at the moment. The new JWT-based APNS server uses HTTP/2 only, which .NET Framework does not yet support.
.NET Core's version of System.Net.Http, however, does, provided you meet the following prerequisites:
On Windows, you must be running Windows 10 Anniversary Edition (v1607) or higher, or the equivalent build of Windows Server 2016 (I think).
On Linux, you must have a version of libcurl that supports HTTP/2.
On macOS, you have to compile libcurl with support for HTTP/2, then use the DYLD_INSERT_LIBRARIES environment variable in order to load your custom build of libcurl.
You should be able to use .NET Core's version of System.Net.Http in the .NET Framework if you really want.
I have no idea what happens on Mono, Xamarin or UWP.
There are then three things you have to do:
Parse the private key that you have been given. This is currently an ECDSA key, and you can load this into a System.Security.Cryptography.ECDsa object.
On Windows, you can use the CNG APIs. After parsing the base64-encoded DER part of the key file, you can then create a key with new ECDsaCng(CngKey.Import(data, CngKeyBlobFormat.Pkcs8PrivateBlob)).
On macOS or Linux there is no supported API and you have to parse the DER structure yourself, or use a third-party library.
Create a JSON Web Token / Bearer Token. If you use the System.IdentityModel.Tokens.Jwt package from NuGet, this is fairly simple. You will need the Key ID and Team ID from Apple.
public static string CreateToken(ECDsa key, string keyID, string teamID)
{
var securityKey = new ECDsaSecurityKey(key) { KeyId = keyID };
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.EcdsaSha256);
var descriptor = new SecurityTokenDescriptor
{
IssuedAt = DateTime.Now,
Issuer = teamID,
SigningCredentials = credentials
};
var handler = new JwtSecurityTokenHandler();
var encodedToken = handler.CreateEncodedJwt(descriptor);
return encodedToken;
}
Send an HTTP/2 request. This is as normal, but you need to do two extra things:
Set yourRequestMessage.Version to new Version(2, 0) in order to make the request using HTTP/2.
Set yourRequestMessage.Headers.Authorization to new AuthenticationHeaderValue("bearer", token) in order to provide the bearer authentication token / JWT with your request.
Then just put your JSON into the HTTP request and POST it to the correct URL.
Because Token (.p8) APNs only works in HTTP/2, thus most of the solutions only work in .net Core. Since my project is using .net Framework, some tweak is needed. If you're using .net Framework like me, please read on.
I search here and there and encountered several issues, which I managed to fix and pieced them together.
Below is the APNs class that actually works. I created a new class library for it, and placed the .P8 files within the AuthKeys folder of the class library. REMEMBER to right click on the .P8 files and set it to "Always Copy". Refer Get relative file path in a class library project that is being referenced by a web project.
After that, to get the location of the P8 files, please use AppDomain.CurrentDomain.RelativeSearchPath for web project or AppDomain.CurrentDomain.BaseDirectory for win application. Refer Why AppDomain.CurrentDomain.BaseDirectory not contains "bin" in asp.net app?
To get the token from the P8, you'll need to use the BouncyCastle class, please download it from Nuget.
using Jose;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Security.Cryptography;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace PushLibrary
{
public class ApplePushNotificationPush
{
//private const string WEB_ADDRESS = "https://api.sandbox.push.apple.com:443/3/device/{0}";
private const string WEB_ADDRESS = "https://api.push.apple.com:443/3/device/{0}";
private string P8_PATH = AppDomain.CurrentDomain.RelativeSearchPath + #"\AuthKeys\APNs_AuthKey.p8";
public ApplePushNotificationPush()
{
}
public async Task<bool> SendNotification(string deviceToken, string title, string content, int badge = 0, List<Tuple<string, string>> parameters = null)
{
bool success = true;
try
{
string data = System.IO.File.ReadAllText(P8_PATH);
List<string> list = data.Split('\n').ToList();
parameters = parameters ?? new List<Tuple<string, string>>();
string prk = list.Where((s, i) => i != 0 && i != list.Count - 1).Aggregate((agg, s) => agg + s);
ECDsaCng key = new ECDsaCng(CngKey.Import(Convert.FromBase64String(prk), CngKeyBlobFormat.Pkcs8PrivateBlob));
string token = GetProviderToken();
string url = string.Format(WEB_ADDRESS, deviceToken);
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
httpRequestMessage.Headers.TryAddWithoutValidation("apns-push-type", "alert"); // or background
httpRequestMessage.Headers.TryAddWithoutValidation("apns-id", Guid.NewGuid().ToString("D"));
//Expiry
//
httpRequestMessage.Headers.TryAddWithoutValidation("apns-expiration", Convert.ToString(0));
//Send imediately
httpRequestMessage.Headers.TryAddWithoutValidation("apns-priority", Convert.ToString(10));
//App Bundle
httpRequestMessage.Headers.TryAddWithoutValidation("apns-topic", "com.xxx.yyy");
//Category
httpRequestMessage.Headers.TryAddWithoutValidation("apns-collapse-id", "test");
//
var body = JsonConvert.SerializeObject(new
{
aps = new
{
alert = new
{
title = title,
body = content,
time = DateTime.Now.ToString()
},
badge = 1,
sound = "default"
},
acme2 = new string[] { "bang", "whiz" }
});
httpRequestMessage.Version = new Version(2, 0);
using (var stringContent = new StringContent(body, Encoding.UTF8, "application/json"))
{
//Set Body
httpRequestMessage.Content = stringContent;
Http2Handler.Http2CustomHandler handler = new Http2Handler.Http2CustomHandler();
handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls;
//handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
//Continue
using (HttpClient client = new HttpClient(handler))
{
HttpResponseMessage resp = await client.SendAsync(httpRequestMessage).ContinueWith(responseTask =>
{
return responseTask.Result;
});
if (resp != null)
{
string apnsResponseString = await resp.Content.ReadAsStringAsync();
handler.Dispose();
}
handler.Dispose();
}
}
}
catch (Exception ex)
{
success = false;
}
return success;
}
private string GetProviderToken()
{
double epochNow = (int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
Dictionary<string, object> payload = new Dictionary<string, object>()
{
{ "iss", "YOUR APPLE TEAM ID" },
{ "iat", epochNow }
};
var extraHeaders = new Dictionary<string, object>()
{
{ "kid", "YOUR AUTH KEY ID" },
{ "alg", "ES256" }
};
CngKey privateKey = GetPrivateKey();
return JWT.Encode(payload, privateKey, JwsAlgorithm.ES256, extraHeaders);
}
private CngKey GetPrivateKey()
{
using (var reader = File.OpenText(P8_PATH))
{
ECPrivateKeyParameters ecPrivateKeyParameters = (ECPrivateKeyParameters)new PemReader(reader).ReadObject();
var x = ecPrivateKeyParameters.Parameters.G.AffineXCoord.GetEncoded();
var y = ecPrivateKeyParameters.Parameters.G.AffineYCoord.GetEncoded();
var d = ecPrivateKeyParameters.D.ToByteArrayUnsigned();
return EccKey.New(x, y, d);
}
}
}
}
Secondly, if you noticed, I am using the custom WinHTTPHandler to make the code to support HTTP/2 based on How to make the .net HttpClient use http 2.0?. I am creating this using another class library, remember to download WinHTTPHandler from Nuget.
public class Http2CustomHandler : WinHttpHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Version = new Version("2.0");
return base.SendAsync(request, cancellationToken);
}
}
After that, just call the "SendNotification" on the ApplePushNotificationPush class and you should get the message on your iPhone.
private string GetToken()
{
var dsa = GetECDsa();
return CreateJwt(dsa, "keyId", "teamId");
}
private ECDsa GetECDsa()
{
using (TextReader reader = System.IO.File.OpenText("AuthKey_xxxxxxx.p8"))
{
var ecPrivateKeyParameters =
(ECPrivateKeyParameters)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
var q = ecPrivateKeyParameters.Parameters.G.Multiply(ecPrivateKeyParameters.D).Normalize();
var qx = q.AffineXCoord.GetEncoded();
var qy = q.AffineYCoord.GetEncoded();
var d = ecPrivateKeyParameters.D.ToByteArrayUnsigned();
// Convert the BouncyCastle key to a Native Key.
var msEcp = new ECParameters {Curve = ECCurve.NamedCurves.nistP256, Q = {X = qx, Y = qy}, D = d};
return ECDsa.Create(msEcp);
}
}
private string CreateJwt(ECDsa key, string keyId, string teamId)
{
var securityKey = new ECDsaSecurityKey(key) { KeyId = keyId };
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.EcdsaSha256);
var descriptor = new SecurityTokenDescriptor
{
IssuedAt = DateTime.Now,
Issuer = teamId,
SigningCredentials = credentials,
};
var handler = new JwtSecurityTokenHandler();
var encodedToken = handler.CreateEncodedJwt(descriptor);
return encodedToken;
}
It have tried the above on ASP.NET CORE 2.1 and 2.2 to no avail. The response I always got was "The message received was unexpected or badly formatted" with HttpVersion20 enabled, which made me doubt whether http2 implementation is concrete.
Below is what worked on ASP.NET CORE 3.0;
var teamId = "YOURTEAMID";
var keyId = "YOURKEYID";
try
{
//
var data = await System.IO.File.ReadAllTextAsync(Path.Combine(_environment.ContentRootPath, "apns/"+config.P8FileName));
var list = data.Split('\n').ToList();
var prk = list.Where((s, i) => i != 0 && i != list.Count - 1).Aggregate((agg, s) => agg + s);
//
var key = new ECDsaCng(CngKey.Import(Convert.FromBase64String(prk), CngKeyBlobFormat.Pkcs8PrivateBlob));
//
var token = CreateToken(key, keyId, teamId);
//
var deviceToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var url = string.Format("https://api.sandbox.push.apple.com/3/device/{0}", deviceToken);
var request = new HttpRequestMessage(HttpMethod.Post, url);
//
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
//
request.Headers.TryAddWithoutValidation("apns-push-type", "alert"); // or background
request.Headers.TryAddWithoutValidation("apns-id", Guid.NewGuid().ToString("D"));
//Expiry
//
request.Headers.TryAddWithoutValidation("apns-expiration", Convert.ToString(0));
//Send imediately
request.Headers.TryAddWithoutValidation("apns-priority", Convert.ToString(10));
//App Bundle
request.Headers.TryAddWithoutValidation("apns-topic", "com.xx.yy");
//Category
request.Headers.TryAddWithoutValidation("apns-collapse-id", "test");
//
var body = JsonConvert.SerializeObject(new
{
aps = new
{
alert = new
{
title = "Test",
body = "Sample Test APNS",
time = DateTime.Now.ToString()
},
badge = 1,
sound = "default"
},
acme2 = new string[] { "bang", "whiz" }
})
//
request.Version = HttpVersion.Version20;
//
using (var stringContent = new StringContent(body, Encoding.UTF8, "application/json"))
{
//Set Body
request.Content = stringContent;
_logger.LogInformation(request.ToString());
//
var handler = new HttpClientHandler();
//
handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
//
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
//Continue
using (HttpClient client = new HttpClient(handler))
{
//
HttpResponseMessage resp = await client.SendAsync(request).ContinueWith(responseTask =>
{
return responseTask.Result;
//
});
//
_logger.LogInformation(resp.ToString());
//
if (resp != null)
{
string apnsResponseString = await resp.Content.ReadAsStringAsync();
//
handler.Dispose();
//ALL GOOD ....
return;
}
//
handler.Dispose();
}
}
}
catch (HttpRequestException e)
{
_logger.LogError(5, e.StackTrace, e);
}
For CreateToken() Refer Above Recommended solution by yaakov,
I has a problem like you. And i seen #gorniv answer. So it's work with me!
May be you can use: https://www.nuget.org/packages/Apple.Auth.Signin for it!
Goodluck!

Passing json urlencode via RestSharp

I have this code which I am attempting to use to communicate an API via RestSharp.
const string task = "pay";
const string command_api_token = "9ufks6FjffGplu9HbaN7uq6XXPPVQXBP";
const string merchant_email_on_voguepay = "mymail#mail.com";
Random rnd = new Random();
string refl = DateTime.Now + rnd.Next(0,9999999).ToString();
byte[] hash_target = Encoding.Default.GetBytes(command_api_token + task + merchant_email_on_voguepay + refl);
string hashD = BitConverter.ToString(new SHA512CryptoServiceProvider().ComputeHash(hash_target)).Replace("-", string.Empty).ToUpper();
var keyValues = new Dictionary<string, string>
{
{ "task", "pay"},
{ "merchant", "3333-4444"},
{ "ref",refl},
{ "hash",hashD},
{ "amount", "20"},
{ "seller", "seller#mail.com"},
{ "remarks", "payment"},
};
//serialization using Newtonsoft JSON
string json = JsonConvert.SerializeObject(keyValues);
//url encode the json
var postString = Server.UrlEncode(json);
//calling API with Restsharp
var client = new RestClient("https://voguepay.com/api/");
var request = new RestRequest(Method.POST);
request.AddParameter("json",json);
IRestResponse response = client.Execute(request);
Textbox1.Text = response.Content;
I think the arrangement of my code is not really ok, because I keep getting error message on each move I make.
If I try to post it as it is above, I get
"response":"X006","description":"Invalid hash"...
If try to get "url encode the json" involved in the "calling API with Restsharp", I get error message as
"response":"X001","description":"Invalid Merchant Id"...
I think I am not placing things right, can someone look at my work and point out what could be the issue with this code?
I am using below code for calling API may this one help u.Here i am passing one class object u replace this by Dictionary and try..
public void insertData(OCMDataClass kycinfo, string clientId, string type)
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(System.Configuration.ConfigurationManager.AppSettings["CBService"]);
string postBody = Newtonsoft.Json.JsonConvert.SerializeObject(kycinfo);
var jsonString = JsonConvert.SerializeObject(kycinfo);
var content = new StringContent(jsonString, System.Text.Encoding.UTF8, "application/json");
var myContent = JsonConvert.SerializeObject(kycinfo);
var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);
var result = client.PostAsync("Bfilvid/api/SvcVId/CreateKYCRepository", content).Result;
if (result.IsSuccessStatusCode)
{
string resultContent = result.Content.ReadAsStringAsync().Result;
}
else
{
string resultContent = result.Content.ReadAsStringAsync().Result;
}
}
}
catch (Exception ex)
{
}

How to POST request using RestSharp

I m trying to POST the request using RestSharp client as follows
I m passing the Auth Code to following function
public void ExchangeCodeForToken(string code)
{
if (string.IsNullOrEmpty(code))
{
OnAuthenticationFailed();
}
else
{
var request = new RestRequest(this.TokenEndPoint, Method.POST);
request.AddParameter("code", code);
request.AddParameter("client_id", this.ClientId);
request.AddParameter("client_secret", this.Secret);
request.AddParameter("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");
request.AddParameter("grant_type", "authorization_code");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
client.ExecuteAsync<AuthResult>(request, GetAccessToken);
}
}
void GetAccessToken(IRestResponse<AuthResult> response)
{
if (response == null || response.StatusCode != HttpStatusCode.OK
|| response.Data == null
|| string.IsNullOrEmpty(response.Data.access_token))
{
OnAuthenticationFailed();
}
else
{
Debug.Assert(response.Data != null);
AuthResult = response.Data;
OnAuthenticated();
}
}
But i am getting response.StatusCode = Bad Request. Can anyone help me for how do i POST the request using Restsharp client.
My RestSharp POST method:
var client = new RestClient(ServiceUrl);
var request = new RestRequest("/resource/", Method.POST);
// Json to post.
string jsonToSend = JsonHelper.ToJson(json);
request.AddParameter("application/json; charset=utf-8", jsonToSend, ParameterType.RequestBody);
request.RequestFormat = DataFormat.Json;
try
{
client.ExecuteAsync(request, response =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
// OK
}
else
{
// NOK
}
});
}
catch (Exception error)
{
// Log
}
This way works fine for me:
var request = new RestSharp.RestRequest("RESOURCE", RestSharp.Method.POST) { RequestFormat = RestSharp.DataFormat.Json }
.AddBody(BODY);
var response = Client.Execute(request);
// Handle response errors
HandleResponseErrors(response);
if (Errors.Length == 0)
{ }
else
{ }
Hope this helps! (Although it is a bit late)
As of 2017 I post to a rest service and getting the results from it like that:
var loginModel = new LoginModel();
loginModel.DatabaseName = "TestDB";
loginModel.UserGroupCode = "G1";
loginModel.UserName = "test1";
loginModel.Password = "123";
var client = new RestClient(BaseUrl);
var request = new RestRequest("/Connect?", Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddBody(loginModel);
var response = client.Execute(request);
var obj = JObject.Parse(response.Content);
LoginResult result = new LoginResult
{
Status = obj["Status"].ToString(),
Authority = response.ResponseUri.Authority,
SessionID = obj["SessionID"].ToString()
};
it is better to use json after post your resuest like below
var clien = new RestClient("https://smple.com/");
var request = new RestRequest("index", Method.POST);
request.AddHeader("Sign", signinstance);
request.AddJsonBody(JsonConvert.SerializeObject(yourclass));
var response = client.Execute<YourReturnclassSample>(request);
if (response.StatusCode == System.Net.HttpStatusCode.Created)
{
return Ok(response.Content);
}
I added this helper method to handle my POST requests that return an object I care about.
For REST purists, I know, POSTs should not return anything besides a status. However, I had a large collection of ids that was too big for a query string parameter.
Helper Method:
public TResponse Post<TResponse>(string relativeUri, object postBody) where TResponse : new()
{
//Note: Ideally the RestClient isn't created for each request.
var restClient = new RestClient("http://localhost:999");
var restRequest = new RestRequest(relativeUri, Method.POST)
{
RequestFormat = DataFormat.Json
};
restRequest.AddBody(postBody);
var result = restClient.Post<TResponse>(restRequest);
if (!result.IsSuccessful)
{
throw new HttpException($"Item not found: {result.ErrorMessage}");
}
return result.Data;
}
Usage:
public List<WhateverReturnType> GetFromApi()
{
var idsForLookup = new List<int> {1, 2, 3, 4, 5};
var relativeUri = "/api/idLookup";
var restResponse = Post<List<WhateverReturnType>>(relativeUri, idsForLookup);
return restResponse;
}
It's better to specify the Json data body.
var client = new RestClient("URL");
var request = new RestRequest("Resources",Method.POST);
request.RequestFormat = RestSharp.DataFormat.Json;
request.AddBody(new classname
{
id = value1;
Name = "";
});
var response = client.Execute(request);
Check statusCode from response.
Always ensure that status code should be OK.

Categories

Resources