I am tying to fetch Accounts Before a certain date
I use the following code
TimeZoneInfo pst = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
DateTime now = TimeZoneInfo.ConvertTime(new DateTime(2012, 06, 30), pst);
accountQuery.CreateTime = now;
accountQuery.SpecifyOperatorOption(FilterProperty.CreateTime,
FilterOperatorType.BEFORE);
accountQuery.PageNumber = 1;
accountQuery.ResultsPerPage = 100;
string a = Response.ToString();
List<Intuit.Ipp.Data.Qbo.Account> accounts =
accountQuery.ExecuteQuery<Intuit.Ipp.Data.Qbo.Account>(context)
.ToList<Intuit.Ipp.Data.Qbo.Account>();
But I get an error Unauthorized OAuth Token: signature_invalid
Related
I am attempting to make an HTTP PUT request from XLRelease to update data in Adobe Workfront. I have been able to successfully login using the API client and GET data. I have also been able to successfully update data using Postman as well as using a native Python script. I am using the HttpRequest library within XLR. I am receiving the same response back in XLR as I am when successfully updating when using Postman, however, the data is not updated when using XLR.
My code is as follows:
import json
WORKFRONT_API_HOST = releaseVariables['url']
WORKFRONT_API_VERSION = releaseVariables['wfApiVersion']
WORKFRONT_API_KEY = releaseVariables['apiKey']
WORKFRONT_USERNAME = releaseVariables['wfUsername']
FI_ID = releaseVariables['target_customer_id']
newPortfolioId = releaseVariables['target_portfolio_id']
WORKFRONT_API_URL = WORKFRONT_API_HOST + WORKFRONT_API_VERSION
def wfLogin():
sessionID = ""
login_endpoint = "/login"
login_request = HttpRequest({'url': WORKFRONT_API_URL})
login_response = login_request.get(login_endpoint + "?apiKey=" + str(WORKFRONT_API_KEY).replace("u'","'") + "&username=" + WORKFRONT_USERNAME, contentType='application/json')
if login_response.getStatus() != 200:
print('# Error logging into WF\n')
print(login_response.getStatus())
print(login_response.errorDump())
sys.exit(1)
else:
json_response = json.loads(login_response.getResponse())
print ("Logged in to WF")
sessionID = json_response['data']['sessionID']
return sessionID
def wfLogout(sessionID):
logout_endpoint = "/logout"
logout_request = HttpRequest({'url': WORKFRONT_API_URL})
logout_response = logout_request.get(logout_endpoint + "?sessionID=" + sessionID, contentType='application/json')
if logout_response.getStatus() != 200:
print('# Error logging out of WF\n')
print(logout_response.getStatus())
print(logout_response.errorDump())
sys.exit(1)
else:
json_response = json.loads(logout_response.getResponse())
print ("Logged out of WF")
result = []
session_id = wfLogin()
if session_id != "":
customer_request = HttpRequest({'url': WORKFRONT_API_URL})
endpoint = '/prgm/%s?sessionID=%s&portfolioID=%s&customerID=%s' % (FI_ID, session_id, newPortfolioId, FI_ID)
jsonObj = "{}"
payload = {}
customer_response = customer_request.put(endpoint, jsonObj, contentType='application/json')
if customer_response.getStatus() != 200:
print('# Error connecting to WF\n')
print(customer_response)
print(customer_response.getStatus())
print(customer_response.errorDump())
sys.exit(1)
else:
response_json = json.loads(customer_response.getResponse())
print ("response_json: ", response_json)
#log out of current session
wfLogout(session_id)
else:
print ("No sessionID is available")
sys.exit(1)
SoftLayer Object Storage is based on the OpenStack Swift object store.
SoftLayer provide SDKs for their object storage in Python, Ruby, Java and PHP, but not in .NET. Searching for .NET SDKs for OpenStack, I came across OpenStack.NET.
Based on this question OpenStack.NET is designed for use with Rackspace by default, but can be made to work with other OpenStack providers using CloudIdentityWithProject and OpenStackIdentityProvider.
SoftLayer provide the following information for connecting to their Object Storage:
Authentication Endpoint
Public: https://mel01.objectstorage.softlayer.net/auth/v1.0/
Private: https://mel01.objectstorage.service.networklayer.com/auth/v1.0/
Username:
SLOS123456-1:email#example.com
API Key (Password):
1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
It's not obvious how this would map to the fields of CloudIdentityWithProject, and OpenStackIdentityProvider but I tried the following and a few other combinations of project name / username / uri:
var cloudIdentity = new CloudIdentityWithProject()
{
ProjectName = "SLOS123456-1",
Username = "email#example.com",
Password = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
};
var identityProvider = new OpenStackIdentityProvider(
new Uri("https://mel01.objectstorage.softlayer.net/auth/v1.0/"),
cloudIdentity);
var token = identityProvider.GetToken(null);
However, in all cases I received the following error:
Unable to authenticate user and retrieve authorized service endpoints
Based on reviewing the source code for SoftLayer's other language libraries and for OpenStack.NET, it looks like SoftLayer's object storage uses V1 auth, while OpenStack.NET is using V2 auth.
Based on this article from SoftLayer and this article from SwiftStack, V1 auth uses a /auth/v1.0/ path (like the one provided by SoftLayer), with X-Auth-User and X-Auth-Key headers as arguments, and with the response contained in headers like the following:
X-Auth-Token-Expires = 83436
X-Auth-Token = AUTH_tk1234567890abcdef1234567890abcdef
X-Storage-Token = AUTH_tk1234567890abcdef1234567890abcdef
X-Storage-Url = https://mel01.objectstorage.softlayer.net/v1/AUTH_12345678-1234-1234-1234-1234567890ab
X-Trans-Id = txbc1234567890abcdef123-1234567890
Connection = keep-alive
Content-Length = 1300
Content-Type = text/html; charset=UTF-8
Date = Wed, 14 Oct 2015 01:19:45 GMT
Whereas V2 auth (identity API V2.0) uses a /v2.0/tokens path, with the request and response in JSON objects in the message body.
Based on the OpenStackIdentityProvider class in OpenStack.NET I hacked together my own SoftLayerOpenStackIdentityProvider like this:
using JSIStudios.SimpleRESTServices.Client;
using net.openstack.Core.Domain;
using net.openstack.Providers.Rackspace;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OpenStack.Authentication;
using System;
using System.Linq;
using System.Collections.Generic;
namespace OpenStackTest1
{
public class SoftLayerOpenStackIdentityProvider : CloudIdentityProvider
{
public SoftLayerOpenStackIdentityProvider(
Uri urlBase, CloudIdentity defaultIdentity)
: base(defaultIdentity, null, null, urlBase)
{
if (urlBase == null)
throw new ArgumentNullException("urlBase");
}
public override UserAccess GetUserAccess(
CloudIdentity identity, bool forceCacheRefresh = false)
{
identity = identity ?? DefaultIdentity;
Func<UserAccess> refreshCallback =
() =>
{
// Set up request headers.
Dictionary<string, string> headers =
new Dictionary<string, string>();
headers["X-Auth-User"] = identity.Username;
headers["X-Auth-Key"] = identity.APIKey;
// Make the request.
JObject requestBody = null;
var response = ExecuteRESTRequest<JObject>(
identity,
UrlBase,
HttpMethod.GET,
requestBody,
headers: headers,
isTokenRequest: true);
if (response == null || response.Data == null)
return null;
// Get response headers.
string authToken = response.Headers.Single(
h => h.Key == "X-Auth-Token").Value;
string storageUrl = response.Headers.Single(
h => h.Key == "X-Storage-Url").Value;
string tokenExpires = response.Headers.Single(
h => h.Key == "X-Auth-Token-Expires").Value;
// Convert expiry from seconds to a date.
int tokenExpiresSeconds = Int32.Parse(tokenExpires);
DateTimeOffset tokenExpiresDate =
DateTimeOffset.UtcNow.AddSeconds(tokenExpiresSeconds);
// Create UserAccess via JSON deseralization.
UserAccess access = JsonConvert.DeserializeObject<UserAccess>(
String.Format(
"{{ " +
" token: {{ id: '{0}', expires: '{1}' }}, " +
" serviceCatalog: " +
" [ " +
" {{ " +
" endpoints: [ {{ publicUrl: '{2}' }} ], " +
" type: 'object-store', " +
" name: 'swift' " +
" }} " +
" ], " +
" user: {{ }} " +
"}}",
authToken,
tokenExpiresDate,
storageUrl));
if (access == null || access.Token == null)
return null;
return access;
};
string key = string.Format("{0}:{1}", UrlBase, identity.Username);
var userAccess = TokenCache.Get(key, refreshCallback, forceCacheRefresh);
return userAccess;
}
protected override string LookupServiceTypeKey(IServiceType serviceType)
{
return serviceType.Type;
}
}
}
Because some of the members of UserAccess (like IdentityToken and Endpoint) have no way to set their fields (the objects have only a default constructor and only read-only members), I had to create the UserAccess object by deserializing some temporary JSON in a similar format as returned by the V2 API.
This works, ie I can now connect like this:
var cloudIdentity = new CloudIdentity()
{
Username = "SLOS123456-1:email#example.com",
APIKey = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
};
var identityProvider = new SoftLayerOpenStackIdentityProvider(
new Uri("https://mel01.objectstorage.softlayer.net/auth/v1.0/"),
cloudIdentity);
var token = identityProvider.GetToken(null);
And then get access to files etc like this:
var cloudFilesProvider = new CloudFilesProvider(identityProvider);
var containers = cloudFilesProvider.ListContainers();
var stream = new MemoryStream();
cloudFilesProvider.GetObject("testcontainer", "testfile.dat", stream);
However, is there a better way than this to use SoftLayer Object Storage from .NET?
I briefly also looked at the OpenStack SDK for .NET (a different library to OpenStack.NET), but it too seems to be based on V2 auth.
I'm trying to connect my asp.net REST api to salesforce. I'm succesfully going through authentification, but when I start to send POST requests, I'm getting an error
{"errorCode":"INVALID_SESSION_ID","message":"Session expired or invalid"}
Here is my POST request:
//SFServerUrl = "https://na17.salesforce.com/services/";
//url = "data/v28.0/sobjects/Account";
ASCIIEncoding ascii = new ASCIIEncoding();
byte[] postBytes = ascii.GetBytes(postBody);
HttpWebRequest request = WebRequest.Create(Globals.SFServerUrl + url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = postBytes.Length;
Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
HttpCookie cookie = HttpContext.Current.Request.Cookies[Globals.SFCookie];
var ticket = FormsAuthentication.Decrypt(cookie.Value);
string authToken = ticket.UserData;
request.Headers.Add("Authorization", "Bearer " + authToken);
postStream.Close();
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
StringBuilder sb = new StringBuilder();
byte[] buf = new byte[8192];
Stream resStream = response.GetResponseStream();
string tempString = null;
int count = 0;
do
{
count = resStream.Read(buf, 0, buf.Length);
if (count != 0)
{
tempString = Encoding.ASCII.GetString(buf, 0, count);
sb.Append(tempString);
}
}
while (count > 0);
return new Tuple<bool, string>(true, sb.ToString());
When I'm trying to send GET request - I recieve 200 response.
Also, I've tried to send a POST Request with the same token from Simple Rest Client and it get's 200 response. I tried to change my "Authorization : Bearer" Header to "Authorization : Oauth", but nothing changed. I also tried to catch this error, get refresh token and send a request again with refreshed token, but nothing changed. Please, help me with this.
Using workbench I was able to POST the following JSON to /services/data/v29.0/sobjects/Account and create a new Account.
{
"Name" : "Express Logistics and Transport"
}
Raw Response
HTTP/1.1 201 Created
Date: Sun, 07 Sep 2014 21:32:06 GMT
Set-Cookie: BrowserId=_HC-bzpTQABC1237vFu2hA;Path=/;Domain=.salesforce.com;Expires=Thu, 06-Nov-2014 21:32:06 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Sforce-Limit-Info: api-usage=209/15000
Location: /services/data/v29.0/sobjects/Account/0010000000000001AAA
Content-Type: application/json;charset=UTF-8
Content-Encoding: gzip
Transfer-Encoding: chunked
{
"id" : "0010000000000001AAA",
"success" : true,
"errors" : [ ]
}
Things to check:
Your URL. It appears to be missing the leading /services
Is SFServerUrl the same Salesforce pod/server that the Session Id was issued to? If the Session Id came from another pod then it would be invalid on na17.
How did you create the Session Id? If you used OAuth, what scopes did you request?
Is the Session Id coming out of the cookie valid?
Has something else using the same Session Id called logout and invalidated the session?
Incidentally, the Salesforce StackExchange site is a great place to ask Salesforce specific questions.
See also:
Using REST API Resources - Create a Record
The problem was that I added Headers after Content. When I switched these lines of code everything worked.
I keep getting a 401 when I try to add a customer with QB Online API v3. The xml works in the API Explorer, and I'm able to query customers from my program. I just can't POST. What am I doing wrong?
string reqBody = "<Customer xmlns=\"http://schema.intuit.com/finance/v3\" domain=\"QBO\" sparse=\"false\"><DisplayName>Empire Records</DisplayName>"
+ "<BillAddr><Line1>201 S King St</Line1><City>Seattle</City><CountrySubDivisionCode>WA</CountrySubDivisionCode><PostalCode>98104</PostalCode></BillAddr>"
+ "<PrimaryPhone><FreeFormNumber>425-867-5309</FreeFormNumber></PrimaryPhone><PrimaryEmailAddr><Address>helpme#thefly.con</Address></PrimaryEmailAddr></Customer>";
IConsumerRequest req = session.Request();
req = req.Post().WithRawContentType("application/xml").WithRawContent(System.Text.Encoding.ASCII.GetBytes(reqBody));
req.AcceptsType = "application/xml";
string response = req.Post().ForUrl("https://quickbooks.api.intuit.com/v3/company/" + realmID + "/customer").ToString()
OAuthConsumerContext consumerContext1 = new OAuthConsumerContext
{
ConsumerKey = ConfigurationManager.AppSettings["consumerKey"].ToString(),
SignatureMethod = SignatureMethod.HmacSha1,
ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"].ToString()
};
OAuthSession oSession1 = new OAuthSession(consumerContext1, "https://oauth.intuit.com/oauth/v1/get_request_token",
"https://workplace.intuit.com/Connect/Begin",
"https://oauth.intuit.com/oauth/v1/get_access_token");
oSession1.ConsumerContext.UseHeaderForOAuthParameters = true;
I keep getting the Invalid Token Error when i call the CreateRecurringPaymentsProfile NVP API.
Please find the sequence of my API calls below:
SetExpressCheckout
METHOD = SetExpressCheckout
VERSION = 98
PWD = <pwd>
USER = <user>
SIGNATURE = <signature>
ReturnUrl = http://google.com
CANCELURL = http://google.com
PAYMENTREQUEST_0_PAYMENTACTION = Authorization
PAYMENTREQUEST_0_AMT = 100.00
PAYMENTREQUEST_0_CURRENCYCODE = USD
L_PAYMENTREQUEST_0_NAME0 = Item1
L_PAYMENTREQUEST_0_QTY0 = 1
L_PAYMENTREQUEST_0_AMT0 = 100.00
PAYMENTREQUEST_0_SELLERPAYPALACCOUNTID = rahul.katikineni#sap.com
LOCALECODE = US
L_BILLINGTYPE0 = RecurringPayments
L_BILLINGAGREEMENTDESCRIPTION0 = SameEveryTime
I get back a token with ACK=*Success* as response. I then navigate to the paypal website using the URL [https://www.sandbox.paypal.com/webscr&cmd=_express-checkout&token=token] and login with a paypal account and click on "Agree and Continue".
After agreeing and successfully redirecting to the redirect URL, I make the GetExpressCheckoutDetails API call with the following parameters
METHOD = GetExpressCheckoutDetails
VERSION = 98
PWD = <pwd>
USER = <user>
SIGNATURE = <signature>
TOKEN = <token from the SetExpressCheckout response>
After successfully getting the the payer details as response, i make the DoExpressCheckoutPayment API call
METHOD = DoExpressCheckoutPayment
VERSION = 98
PWD = <pwd>
USER = <user>
SIGNATURE = <signature>
TOKEN = <token from the SetExpressCheckout response>
PAYERID = <payer ID from the GetExpressCheckoutDetails response>
PAYMENTREQUEST_0_AMT = 100
PAYMENTREQUEST_0_PAYMENTACTION = Sale
PAYMENTREQUEST_0_CURRENCYCODE = USD
L_PAYMENTREQUEST_0_NAME0 = Item1
L_PAYMENTREQUEST_0_QTY0 = 1
L_PAYMENTREQUEST_0_AMT0 = 100.00
PAYMENTREQUEST_0_SELLERPAYPALACCOUNTID = rahul.katikineni#sap.com
I now make the CreateRecurringPaymentsProfile API call
METHOD = CreateRecurringPaymentsProfile
VERSION = 98
PWD = <pwd>
USER = <user>
SIGNATURE = <signature>
TOKEN = <token from the SetExpressCheckout response>
PAYERID = <payer ID from the GetExpressCheckoutDetails response>
DESC = SameEveryTime
BILLINGPERIOD = Month
BILLINGFREQUENCY = 1
PROFILESTARTDATE = 2013-05-16T00:00:00Z
MAXFAILEDPAYMENTS = 1
AMT = 100.00
CURRENCYCODE = USD
L_PAYMENTREQUEST_0_NAME0 = Item1
L_PAYMENTREQUEST_0_QTY0 = 1
L_PAYMENTREQUEST_0_AMT0 = 100.00
AUTOBILLAMT = AddToNextBilling
I keep getting the following response
TIMESTAMP = 2013-04-17T05:31:24Z
CORRELATIONID = d2c1d30c1d31
ACK = Failure
VERSION = 98
BUILD = 5650305
L_ERRORCODE0 = 11502
L_SHORTMESSAGE0 = Invalid Token
L_LONGMESSAGE0 = The token is invalid
L_SEVERITYCODE0 = Error
I have tried looking for a solution in many forums but could not figure out if i have missed any parameters.
Can anyone help me on this?
Thanks in advance,
Rahul
This error returned by Paypal is vague. Most common reason for this error is discrepancy between BillingDescription value in SetExpressCheckout call and ScheduleDEtails.Description in CreateRecurringprofile call. Make sure these two are exactly the same for this to work.
Eg:
public CreateRecurringPaymentsProfileResponseType createRecurringProfile(string tokenin){
var scheduleDetails = new ScheduleDetailsType();
scheduleDetails.PaymentPeriod = paymentPeriod;
scheduleDetails.Description = "RecurringBilling";
}
public SetExpressCheckoutResponseType setExpressCheckout()
{
....
var billingAgreement = new BillingAgreementDetailsType();
billingAgreement.BillingAgreementDescription = "RecurringBilling";
billingAgreement.BillingType = BillingCodeType.RECURRINGPAYMENTS;
billingAgreement.PaymentType = MerchantPullPaymentCodeType.ANY;
ecDetails.BillingAgreementDetails.Add(billingAgreement);
...
}