Create Purchase Receipt from REST API - acumatica

I'm trying to use the new OpenAPI 2.0 setup in Acumatia 21R1 to create a PO Receipt. I've tested creating several other types of records (eg: StockItems) and virtually the same code works perfectly. This instance of Acumatica has several tenants but no branches.
I've also used this same code put pointed it to an instance of Acumatica that has one tenant and multiple branches, and as long as I set the branch it works fine.
When I run it I get "curyid can not be null". This leads me to believe that somehow it's not figuring out the branch or tenant correctly, but if I use the same login code I can pull data from those tenants just fine. I've also tried passing the json directly and including the curyid set to USD, but that has the same effect.
Any thoughts on what I am doing wrong?
private createPOR()
{
string baseURL = "https://acumatica.[good url goes here].com/AcumaticaPWS";
string strLogin = baseURL + "/entity/auth/login";
var client = new RestClient(strLogin);
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
string strBody = "{ \"name\": \"admin\", \"password\": \"[proper password]\", \"tenant\": \"PWS Milwaukee\", \"branch\": \"\"}";
request.AddJsonBody(strBody);
IRestResponse response = client.Execute(request);
txtResults.Text = response.Cookies.SingleOrDefault(x => x.Name == ".ASPXAUTH").Value.ToString();
RestResponseCookie sessionCookie = response.Cookies.SingleOrDefault(x => x.Name == ".ASPXAUTH");
// Create the new one for send the data.
string strItems = baseURL + "/entity/Default/20.200.001/PurchaseReceipt";
client = new RestClient(strItems);
request = new RestRequest(Method.PUT);
request.AddCookie(sessionCookie.Name, sessionCookie.Value);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
PurchaseReceipt theRec = new PurchaseReceipt{ Type = new StringValue { Value = "Receipt" },
VendorID = new StringValue { Value = "V1002" }
};
// BaseCurrencyID = new StringValue { Value = "USD" },
// CurrencyID = new StringValue { Value = "USD" }
request.AddJsonBody(JsonConvert.SerializeObject(theRec));
response = client.Execute(request);
txtResults.Text += Environment.NewLine + "Response" + response.StatusCode.ToString();
// Setup to log out.
string strLogout = baseURL + "/entity/auth/logout";
client = new RestClient(strLogout);
request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "application/json");
response = client.Execute(request);
txtResults.Text += Environment.NewLine + response.StatusCode.ToString();
}

Like Samvel mentioned in the comments this issue is usually the result of not having provided the Branch during the login.
But once the Branch has been provided it still needs to be provided as a cookie for the other request down the line.
That cookie should have the name "UserBranch" with its value being an integer that should be returned from the login request.

Related

How to configure the user_token of Damn Vulnerable Web Application within CSRF field while Script based authentication using ZAP?

I had been following the documentation of Script Based Authentication for Damn Vulnerable Web Application using ZAP. I have navigated to http://localhost/dvwa/login.php through Manual Explore which opens up the DVWA application on my localhost as follows:
and adds the URL to the Default Context.
I've also created the dvwa script with the following configuration:
and modified the dvwa script:
Now when I try Configure Context Authentication, dvwa script does gets loaded but the CSRF field doesn't shows up.
Additionally, POST Data doesn't even shows up but Extra POST Data is shown.
Am I missing something in the steps? Can someone help me out?
The modified script within the documentation of Script Based Authentication section for Damn Vulnerable Web Application using ZAP
seems incomplete.
The complete script is available at Setting up ZAP to Test Damn Vulnerable Web App (DVWA) which is as follows:
function authenticate(helper, paramsValues, credentials) {
var loginUrl = paramsValues.get("Login URL");
var csrfTokenName = paramsValues.get("CSRF Field");
var csrfTokenValue = extractInputFieldValue(getPageContent(helper, loginUrl), csrfTokenName);
var postData = paramsValues.get("POST Data");
postData = postData.replace('{%username%}', encodeURIComponent(credentials.getParam("Username")));
postData = postData.replace('{%password%}', encodeURIComponent(credentials.getParam("Password")));
postData = postData.replace('{%' + csrfTokenName + '%}', encodeURIComponent(csrfTokenValue));
var msg = sendAndReceive(helper, loginUrl, postData);
return msg;
}
function getRequiredParamsNames() {
return [ "Login URL", "CSRF Field", "POST Data" ];
}
function getOptionalParamsNames() {
return [];
}
function getCredentialsParamsNames() {
return [ "Username", "Password" ];
}
function getPageContent(helper, url) {
var msg = sendAndReceive(helper, url);
return msg.getResponseBody().toString();
}
function sendAndReceive(helper, url, postData) {
var msg = helper.prepareMessage();
var method = "GET";
if (postData) {
method = "POST";
msg.setRequestBody(postData);
}
var requestUri = new org.apache.commons.httpclient.URI(url, true);
var requestHeader = new org.parosproxy.paros.network.HttpRequestHeader(method, requestUri, "HTTP/1.0");
msg.setRequestHeader(requestHeader);
helper.sendAndReceive(msg);
return msg;
}
function extractInputFieldValue(page, fieldName) {
// Rhino:
var src = new net.htmlparser.jericho.Source(page);
// Nashorn:
// var Source = Java.type("net.htmlparser.jericho.Source");
// var src = new Source(page);
var it = src.getAllElements('input').iterator();
while (it.hasNext()) {
var element = it.next();
if (element.getAttributeValue('name') == fieldName) {
return element.getAttributeValue('value');
}
}
return '';
}
Using this script, CSRF Field and POST Data field shows up just perfect.

How can I receive returnurl events from embedded app?

I sent envelope at embed app without client_id. Then, I can check the envelope by email, and if I signed the envelope in the email, is there a way to get an event on the embed app?
public Map<String,Object> createRecipientView(Map<String,Object> recipientInfo) {
Map<String,Object> result = new HashMap<String,Object>();
// instantiate a new EnvelopesApi object
EnvelopesApi envelopesApi = new EnvelopesApi();
// set the url where you want the recipient to go once they are done signing
RecipientViewRequest view = new RecipientViewRequest();
//view.setReturnUrl("https://www.docusign.com");
view.setReturnUrl(serverUrl+"/"+recipientInfo.get("usr_cls")+"/docusign/returnRecipientView.do?ds_usr_id="+recipientInfo.get("ds_usr_id") + "&docusign_id=" + recipientInfo.get("docusign_id")+ "&usr_cls=" + recipientInfo.get("usr_cls") + "&uiId=" +recipientInfo.get("uiId"));
view.setAuthenticationMethod("email");
// recipient information must match embedded recipient info we provided in step #2
String email = (String)recipientInfo.get("email");
String userName = (String)recipientInfo.get("usr_nm");
String recipientId = (String)recipientInfo.get("recipient_id");
String clientId = (String)recipientInfo.get("client_id");
String envelopeId = (String)recipientInfo.get("envelope_id");
view.setEmail(email);
view.setUserName(userName);
view.setRecipientId(recipientId);
//view.seta
//view.setClientUserId(clientId);
// call the CreateRecipientView API
ViewUrl recipientView;
try {
recipientView = envelopesApi.createRecipientView(accountId, envelopeId, view);
log.info("Signing URL = " + recipientView.getUrl());
result.put("url", recipientView.getUrl());
result.put("result_status", "S");
} catch (ApiException e) {
log.error("error : " + e.toString());
result.put("result_status", "F");
result.put("result_message", e.toString());
}
return result;
}
Yes, you can use webhook to get notifications about the envelope to your app.
You can read this blog post about it.
You can also look at this code example.
Here is some C# code taken from here:
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
var eventNotification = new EventNotification();
\\ Set up the endpoint URL to call (it must be using HTTPS and at least TLS1.1 or higher)
eventNotification.Url = "https:\\myapp.somedomain.com";
\\ DocuSign will retry on failure if this is set
eventNotification.RequireAcknowledgment = "true";
\\ This would send the documents together with the event to the endpoint
eventNotification.IncludeDocuments = "true";
\\ Allows you to see this in the DocuSign Admin Connect logs section
eventNotification.LoggingEnabled = "true";
var envelopeEvents = new List<EnvelopeEvent>();
\\ In this case we only add a single envelope event, when the envelope is completed. You can also add events for recipients
envelopeEvents.Add(new EnvelopeEvent { EnvelopeEventStatusCode = "completed", IncludeDocuments = "true" });
eventNotification.EnvelopeEvents = envelopeEvents;
envelopeDefinition.EventNotification = eventNotification;

Unable to get a Stripe Checkout session object

Stripe.Net v34.16.0 bounces my code on the creation of the checkout session object responding with:
StripeException: No such plan: plan_myPlanId; a similar object exists in live mode, but a test mode key was used to make this request.
I do not see a means in the Stripe Dashboard to designate a given plan as a test plan .I also do not see
anything resembling a mode property.. my code
public async Task<IActionResult> Index()
{
//var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
//user = await _userManager.FindByIdAsync(userId);
StripeConfiguration.ApiKey = "sk_test_mytestkey";
var options = new Stripe.Checkout.SessionCreateOptions
{
PaymentMethodTypes = new List<string> {
"card",
},
SubscriptionData = new Stripe.Checkout.SessionSubscriptionDataOptions
{
Items = new List<SessionSubscriptionDataItemOptions> {
new SessionSubscriptionDataItemOptions {
Plan = "plan_myplanid",
},
},
},
//to do
SuccessUrl = "localhost://home",
CancelUrl = "localhost://home",
//CancelUrl = "https://example.com/cancel",
};
var service = new Stripe.Checkout.SessionService();
Stripe.Checkout.Session session = service.Create(options); //error out here
StripeCheckoutSessionId stripeCheckoutSessionId = new StripeCheckoutSessionId();
stripeCheckoutSessionId.StripeSessionID = session.Id;
return View(stripeCheckoutSessionId);
}
I am referring to Stripe sample code in the .Net tab here: https://stripe.com/docs/payments/checkout/subscriptions/starting
I appreciate your guidance in correcting my errors.

oAuth2 web request works in browser but not in app

I have the following code sample with which I'm trying to authenticate an Azure active directory user within a Xamarin forms app
The URL (I've removed the actual client ID) works fine in a browser but fails when trying to send the http request
The error message says 'the response type must include client_id'
string URL = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?"
+ "client_id=xxxx-xxxxx-xxxxx-xxxxx-xxx"
+ "&response_type=code"
+ "&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient"
+ "&response_mode=query"
+ "&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read"
+ "&state=12345";
var webRequest = System.Net.WebRequest.Create(URL) as HttpWebRequest;
System.Console.WriteLine(URL);
if (webRequest != null)
{
webRequest.Method = "POST";
webRequest.ServicePoint.Expect100Continue = false;
webRequest.Timeout = 20000;
webRequest.ContentType = "text/html";
//POST the data.
using (requestWriter = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter.Write(postData);
}
}
HttpWebResponse resp = (HttpWebResponse)webRequest.GetResponse();
Stream resStream = resp.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
ret = reader.ReadToEnd();
You put parameters in the URL, so you need to use GET method, instead of POST (like your browser does when you paste the URL in its address bar).
So, replace:
webRequest.Method = "POST";
by:
webRequest.Method = "GET";
and remove:
//POST the data.
using (requestWriter = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter.Write(postData);
}

Trying to get all records of a generic list using Sharepoint and Microsoft Graph api

When trying to get records of a list in SharePoint i keep getting Response like:
{"#odata.context":"https://graph.microsoft.com/beta/$metadata#users('123')/sharepoint/sites('456')/lists('789')/items","value":[]}
I was able to run through all sites and lists but still fail on items. The list has the GenericList template. However on another list with the template DesignCatalog i were able to get all items. Is "/items" the wrong way to get records of a generic list?
Here is a snippet of my current Code:
const string serviceEndpoint = "https://graph.microsoft.com/beta/";
HttpClient client = new HttpClient();
var token = await _authenticationHelper.GetTokenAsync();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
// get the site
HttpResponseMessage responseGetSites = await client.GetAsync(new Uri(serviceEndpoint + "sharePoint:/Intranet"));
if (responseGetSites.IsSuccessStatusCode)
{
string responseContent = await responseGetSites.Content.ReadAsStringAsync();
var jResult = JObject.Parse(responseContent);
siteItem = JsonConvert.DeserializeObject<SiteItemModel>(jResult.ToString());
// get all lists with the given site id
HttpResponseMessage responseGetLists = await client.GetAsync(new Uri(serviceEndpoint + "sharepoint/sites/" + siteItem.SiteId + "/lists"));
if (responseGetLists.IsSuccessStatusCode)
{
string responseContent2 = await responseGetLists.Content.ReadAsStringAsync();
var jResult2 = JObject.Parse(responseContent2);
foreach (JObject listresponse in jResult2["value"])
{
ListItemModel desiralizedItemModel = JsonConvert.DeserializeObject<ListItemModel>(listresponse.ToString());
listItemCollection.Add(desiralizedItemModel);
}
// find a specific list
string listId = listItemCollection.Where(w => w.listName == "MyTestlist").First().listId;
// get all records with of the given list
HttpResponseMessage responseGetItems = await client.GetAsync(new Uri(serviceEndpoint + "sharepoint/sites/" + siteItem.SiteId + "/lists/" + listId + "/items"));
if (responseGetItems.IsSuccessStatusCode)
{
string responseContent3 = await responseGetItems.Content.ReadAsStringAsync();
var jResult3 = JObject.Parse(responseContent3);
I had the same problem. I had to add "Sites.ReadWrite.All" permission under MS Graph, not under sharepoint (I was writing to the list as well, but "Sites.Read.All" should work).

Resources