In this blog article, I cover a simple assignment of working with one of the .NET SDK OrderCloud examples. As with any API model, it is important to setup all the necessary relationships/plumbing to get the concerned code block working. So, this blog post is about the steps I took to make the concerned code block execute successfully!
As ever, a simplified representation of OrderCloud API invocation (as covered in this article):
Code Block from .NET SDK examples:
///////////////////////////////////////////////////////////////////////////////////////////////////
using OrderCloud.SDK;
var client = new OrderCloudClient(new OrderCloudClientConfig {
ClientId = "my-client-id",
// client credentials grant flow:
ClientSecret = "my-client-secret"
// OR password grant flow:
Username = u,
Password = p,
Roles = new[] { ApiRole.OrderAdmin }
});
var orders = await client.Orders.ListAsync(OrderDirection.Incoming, filters: new { Status = OrderStatus.Open });
Console.WriteLine($"{orders.Meta.TotalCount} open orders found.");
Console.WriteLine($"Fetched page {orders.Meta.Page} of {orders.Meta.TotalPages}.");
foreach (var order in orders.Items) {
Console.WriteLine($"ID: {order.ID}, Total: {order.Total:C}");
}
///////////////////////////////////////////////////////////////////////////////////////////////////
Step-by-Step:
Pre-requisite: Market Place
Since I decided to use the Client credentials grant flow, had to create the ClientId and ClientSecret.
So, logon to https://portal.ordercloud.io/ and go to Seller > API Client
Create New API Client:
Provide a name and generate random client secret:
My New API Client:
So, that gives me the client id and secret for my code:
.NET Core Console App: Install OrderCloud SDK nuget packageAdd the much needed client id and client secret generated from OrderCloud to the code:
Now, one of the most important pre-requisites for the above code block to work fine is to setup a default context user within the API Client:
Create a new admin user:
Seller > Admin Users
POST Create a new admin user
Request Body:
{
"Username": "navanuser",
"FirstName": "navan",
"LastName": "ksr",
"Email": "contactnavaneeth@gmail.com",
"Active": true
}
Response:
Update API Client with Default Context User:
Seller > API Client
PUT Update an API client
Request Body:
{
"AppName": "My API Client",
"AccessTokenDuration": 600,
"AllowAnyBuyer": true,
"AllowSeller": true,
"DefaultContextUserName": "navanuser",
"Active": true
}
Response:
Check User Permissions
At this point, if you perform a get on the admin user - navanuser, you will find that there are no roles assigned for the user:
Seller > Admin Users
GET Get a list of admin users
Response:
POST Create a new security profile
Request:
{
"Name": "myorderadminprofile",
"Roles": [
"OrderAdmin"
]
}
Response:
Assign necessary roles for the admin user
Seller > Admin Users
POST Create or Update a security profile assignment
Request:
{
"SecurityProfileID": "b_4OaV6-zkmgo-turqmQNA",
"UserID": "WshjEIexEEmxUvFne5-1oQ"
}
Now, check the assignment:
Seller > Admin Users
GET Get a list of admin users
Looks good so far!
So, time to check if the code executes fine and no wonder it does although order count is zero, which is known!
Few exceptions / Cause and solution:
Exception - 1:
OrderCloud.SDK.OrderCloudException
HResult=0x80131500
Message=invalid_grant: Default context user required for client credentials grant
Source=OrderCloud.SDK
StackTrace:
at OrderCloud.SDK.OrderCloudClient.<ThrowAuthExceptionAsync>d__196.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.FlurlRequest.<HandleExceptionAsync>d__35.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.FlurlRequest.<SendAsync>d__29.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Flurl.Http.FlurlRequest.<SendAsync>d__29.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.ResponseExtensions.<ReceiveJson>d__0`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at OrderCloud.SDK.OrderCloudClient.<AuthenticateAsync>d__198.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at OrderCloud.SDK.OrderCloudClient.<AuthenticateAsync>d__186.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at OrderCloud.SDK.OrderCloudClient.<EnsureTokenAsync>d__197.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.FlurlRequest.<SendAsync>d__29.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.ResponseExtensions.<ReceiveJson>d__0`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at ConsoleApp6.Program.<Main>d__0.MoveNext() in C:\Users\conta\source\repos\ConsoleApp6\ConsoleApp6\Program.cs:line 47
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
FlurlHttpException: Call failed with status code 400 (Bad Request): POST https://sandboxapi.ordercloud.io/oauth/token
Reason:
API Client does not have a DefaultContextUserName
For instance, GET on the concerned API Client looks like this:
Solution: Execute PATCH Partially update a API Client passing API Client ID with the following request body:
{
"DefaultContextUserName": "navanuser"
}
Exception-2:
OrderCloud.SDK.OrderCloudException
HResult=0x80131500
Message=Auth.InsufficientRoles: User does not have role(s) required to perform this action.
Source=OrderCloud.SDK
StackTrace:
at OrderCloud.SDK.OrderCloudClient.<ThrowApiExceptionAsync>d__195.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.FlurlRequest.<HandleExceptionAsync>d__35.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.FlurlRequest.<SendAsync>d__29.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Flurl.Http.FlurlRequest.<SendAsync>d__29.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Flurl.Http.ResponseExtensions.<ReceiveJson>d__0`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at ConsoleApp6.Program.<Main>d__0.MoveNext() in C:\Users\conta\source\repos\ConsoleApp6\ConsoleApp6\Program.cs:line 47
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
FlurlHttpException: Call failed with status code 403 (Forbidden): GET https://sandboxapi.ordercloud.io/v1/orders/Incoming?searchType=AnyTerm&page=1&pageSize=20&Status=Open
Cause:
Security profile does not have enough permission or roles assigned to it:
Solution: Execute PUT Create or update security profile for the concerned Security Profile Id with the following request body:
{
"Roles": [
"OrderAdmin"
],
"Name": "myorderadminprofile"
}
If Security Profile has the roles, ensure Security Profile and the concerned user are linked:
For instance, GET Get a list of security profile assignments, notice nothing returned in the items array:
After POST Create or update a security profile assignment:
Request Body:
{
"SecurityProfileID": "4-9b0rnQ7U6tA1Vs1YLuAA",
"UserID": "WshjEIexEEmxUvFne5-1oQ"
}
Now, check back GET Get a list of security profile assignments:
So, this should setup the link between the security profile and the concerned user!
References:
https://ordercloud.io/learn/getting-started/establishing-api-access
https://stackoverflow.com/questions/69245963/ordercloud-invalid-client-error-when-using-postman-or-net-sdk
Comments
Post a Comment