Need help interfacing with the National Rail Enquiries (UK) API (LDBWS) - c#

I've registered for a token to access the National Rail (UK), Live Departure Boards API, but I can't seem to get it to work. Can anybody point out what I'm doing wrong?
I used WSDL.EXE to build a C# SOAP Proxy class, as specified here: https://realtime.nationalrail.co.uk/ldbws/
The generated .cs proxy file is 1318 lines long, but it looks correct.
My code is as follows: (LDBServiceSoap is the generated proxy class)
static void Main(string[] args)
{
LDBServiceSoap ldb = new LDBServiceSoap();
ldb.AccessTokenValue = new AccessToken() {
TokenValue = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
};
StationBoard sb = ldb.GetDepartureBoard(4, "WAT", "VIC", FilterType.from, 0, 120);
}
The Url is set inside the proxy class, so I can't think of anything else I need to do.
But when the debugger gets up to the GetDepartureBoard method, it throws a WebException "The request failed with HTTP status 401: Unauthorized."
Does anybody know what I'm missing / doing wrong here?
You're awesome!

If you obtained your access token through the OpenLDWS signup then your token will only work on the https://realtime.nationalrail.co.uk/OpenLDBWS/ endpoint that could be your problem

Not sure how you've generated your sources but I've managed to get a working version using this Web service client given WSDL to generate the sources from the WSDL:
wsimport -extension -keep -XadditionalHeaders https://lite.realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2016-02-16
Then I call the method once the sources are on the classpath with the following:
AccessToken token = new AccessToken(); // This class is generated from the WSDL
token.setTokenValue("yourTokenHere");
Ldb ldb = new Ldb();
LDBServiceSoap api = ldb.getLDBServiceSoap();
GetBoardRequestParams reqParams = new GetBoardRequestParams();
reqParams.setCrs("STA"); // Station Code
reqParams.setNumRows(10);
reqParams.setTimeOffset(-120);
StationBoardResponseType departures = api.getDepartureBoard(reqParams, token);

Though the answer from Rob Evans did not completely provide the solution, it did show me the right direction. I had to implement this in C# and below code worked for me.
AccessToken token = new AccessToken();
token.TokenValue = "xxx-xxx-xxx";
ldb client = new ldb();
client.AccessTokenValue = token;
StationBoard sb = client.GetDepartureBoard(10, "ABW", "", FilterType.to, 0, 120);

Related

Zoho API C# ERROR: "OAUTH_SCOPE_MISMATCH", "status": "error", "message": "invalid oauth scope to access this URL"

I have a problem with authorization throught C# code fro Zoho API. I already tried it with Postman and it's working. I can create a Lead if I will use Postman, but I need to do it in C# code. I'm using ZOHOCRMSDK-2.1 version.
They have API Console, where I created
I have client_secret, client_id and all what I need.
For the C# app I'm using WebAPI, so it should work there. I also created appsettings.json and put there all credentials which I need:
I'm getting this error, when I'm trying to GET all accounts which I have in ZohoCRM:
I'm not getting error here, but I'm getting it in the next section of my code. My code is below:
public static void Get(Settings settings)
{
Logger logger = new Logger.Builder().Level(Logger.Levels.ALL).FilePath("/Users/matias/csharp_sdk_log.log").Build();
UserSignature user = new UserSignature(settings.Email);
Environment environment = EUDataCenter.PRODUCTION;
Token token = new OAuthToken.Builder()
.ClientId(settings.ClientId)
.ClientSecret(settings.ClientSecret)
.RefreshToken(settings.RefreshToken)
.Build();
TokenStore tokenStore = new FileStore("C:\\TokenStore\\sdktoken.txt");
SDKConfig config = new SDKConfig.Builder().AutoRefreshFields(true).PickListValidation(true).Build();
new SDKInitializer.Builder()
.User(user)
.Environment(environment)
.Token(token)
.Store(tokenStore)
.SDKConfig(config)
//.ResourcePath(resourcePath)
.Logger(logger)
.Initialize();
GetRecordsContacts("Accounts");
}
Next section of my code:
public static void GetRecordsContacts(string moduleAPIName)
{
RecordOperations recordOperations = new RecordOperations();
ParameterMap paramInstance = new ParameterMap();
paramInstance.Add(GetRecordsParam.PAGE, 1);
paramInstance.Add(GetRecordsParam.PER_PAGE, 200);
paramInstance.Add(GetRecordsParam.APPROVED, "both");
HeaderMap headerInstance = new HeaderMap();
APIResponse<ResponseHandler> response = recordOperations.GetRecords(moduleAPIName, paramInstance, headerInstance);
}
So, why it's not working with C# code, but it's working in Postman? What I'm missing here?

Google plus API returns error code 401 when publishing

I am using Google Plus API for .Net for implementing sharing on google plus using WebAuthenticationBroker. It returns a token after the user gets logged in but when I send a moments post request it returns error 401.
My code on clicking on image is
String GoogleURL = "https://accounts.google.com/o/oauth2/auth?client_id=xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=http://www.google.com&response_type=code&scope=" + Uri.EscapeDataString("https://www.googleapis.com/auth/plus.stream.write https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.login");
PlusService service = new PlusService();
System.Uri StartUri = new Uri(GoogleURL);
System.Uri EndUri = new Uri("https://accounts.google.com/o/oauth2/approval?");
WebAuthenticationBroker.AuthenticateAndContinue(new Uri(GoogleURL), EndUri);
now when it returns after authenticating I have called method upload on google in continue which is as follows--
PlusService service = new PlusService();
Moment body = new Moment();
ItemScope itemScope = new ItemScope();
itemScope.Id = "replacewithuniqueforaddtarget";
itemScope.Image = "http://www.google.com/s2/static/images/GoogleyEyes.png";
itemScope.Type = "";
itemScope.Description = "The description for the action";
itemScope.Name = "An example of add activity";
body.Object = itemScope;
body.Type = "http://schema.org/AddAction";
MomentsResource.InsertRequest insert =
new MomentsResource.InsertRequest(
service,
body,
"me",
MomentsResource.InsertRequest.CollectionEnum.Vault);
Moment wrote = insert.Execute();
But it returns exception 401. The code to post I found on Google Console Help. Can somebody help in this?
I finally found out that google APIs are not directly open to third party developers and it just made my case void and had to use HTTP method for this. Thanks #DalmTo for answering.

Google Analytics Api on Azure

I want to use the google analytics api in my MVC website, im authenticating using the api service account and oauth2 with have no issues on my localhost but as soon as I deploy to Azure i get a 502 error:
"502 - Web server received an invalid response while acting as a
gateway or proxy server. There is a problem with the page you are
looking for, and it cannot be displayed. When the Web server (while
acting as a gateway or proxy) contacted the upstream content server,
it received an invalid response from the content server."
heres my code:
const string ServiceAccountUser = "xxxxxxxxxx-cpla4j8focrebami0l87mbcto09j9j6k#developer.gserviceaccount.com";
AssertionFlowClient client = new AssertionFlowClient(
GoogleAuthenticationServer.Description,
new X509Certificate2(System.Web.Hosting.HostingEnvironment.MapPath("/Areas/Admin/xxxxxxxxxxxxxxxxxx-privatekey.p12"),
"notasecret", X509KeyStorageFlags.Exportable))
{
Scope = AnalyticsService.Scopes.AnalyticsReadonly.GetStringValue(),
ServiceAccountId = ServiceAccountUser //Bug, why does ServiceAccountUser have to be assigned to ServiceAccountId
//,ServiceAccountUser = ServiceAccountUser
};
OAuth2Authenticator<AssertionFlowClient> authenticator = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
I cant figure out whats causing it? Am im missing something within Azure?
Thanks for any help.
I also ran into the same issue but passing X509KeyStorageFlags.MachineKeySet into the constructor as well fixed the issue for me.
X509Certificate2 certificate = new X509Certificate2(file, "key", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
After hours of pain on this exact same problem, I found a work around by piecing together various sources of info.
The problem arises from trying to read the p12 file from the Azure web site, i.e. this line in my code fails
var key = new X509Certificate2(keyFile, keyPassword, X509KeyStorageFlags.Exportable);
No idea why, but it works if you split the file into a cer and key.xml file?
Firstly, extract these files, (I just used a console app)
// load pfx/p12 as "exportable"
var p12Cert = new X509Certificate2(#"c:\Temp\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable);
// export .cer from .pfx/.p12
File.WriteAllBytes(#"C:\Temp\MyCert.cer", p12Cert.Export(X509ContentType.Cert));
// export private key XML
string privateKeyXml = p12Cert.PrivateKey.ToXmlString(true);
File.WriteAllText(#"C:\Temp\PrivateKey.xml", privateKeyXml);
Then copy them to your website then load them in like so
//Store the authentication description
AuthorizationServerDescription desc = GoogleAuthenticationServer.Description;
//Create a certificate object to use when authenticating
var rsaCryptoServiceProvider = new RSACryptoServiceProvider();
rsaCryptoServiceProvider.FromXmlString(File.ReadAllText(keyFile));
var key = new X509Certificate2(certFile) {PrivateKey = rsaCryptoServiceProvider};
//Now, we will log in and authenticate, passing in the description
//and key from above, then setting the accountId and scope
var client = new AssertionFlowClient(desc, key)
{
//cliendId is your SERVICE ACCOUNT Email Address from Google APIs Console
//looks something like 12345-randomstring#developer.gserviceaccount.com
//~IMPORTANT~: this email address has to be added to your Google Analytics profile
// and given Read & Analyze permissions
ServiceAccountId = clientId,
Scope = "https://www.googleapis.com/auth/analytics.readonly"
};
//Finally, complete the authentication process
//NOTE: This is the first change from the update above
var auth = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
//First, create a new service object
//NOTE: this is the second change from the update
//above. Thanks to James for pointing this out
var gas = new AnalyticsService(new BaseClientService.Initializer { Authenticator = auth });
This now works for me and I hope it helps you.

setExpressCheckout and SSL/TLS error

I'm trying to develop a simple application that will enable users to purchase services off a website through the Paypal API. This application is running on ASP.NET with C#.
I have had very little luck trying to get the Paypal API to co-operate. The method I'm calling is SetExpressCheckout with all the appropriate variables.
I did my research and discovered that since I'm testing in Localhost, it may affect Paypal's ability to communicate with the application. So the next thing I tried was accessing my application through an open port and a publicly accessible IP address, but the same error occurs on the call to SetExpressCheckout.
Here is the error:
Exception Details: System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
Source Error:
Line 1790: [return: System.Xml.Serialization.XmlElementAttribute("SetExpressCheckoutResponse", Namespace="urn:ebay:api:PayPalAPI")]
Line 1791: public SetExpressCheckoutResponseType SetExpressCheckout([System.Xml.Serialization.XmlElementAttribute(Namespace="urn:ebay:api:PayPalAPI")] SetExpressCheckoutReq SetExpressCheckoutReq) {
Line 1792: object[] results = this.Invoke("SetExpressCheckout", new object[] {
Line 1793: SetExpressCheckoutReq});
Line 1794: return ((SetExpressCheckoutResponseType)(results[0]));
Source File: c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\anan_p2\730602d6\31a8d74e\App_WebReferences.c8vgyrf8.2.cs Line: 1792
I've also tried generating certificates using OpenSSL and uploading them to the Paypal account's encrypted seller option but still no effect.
Thank you very much for reading through my question!
Update: As requested here is the code being used.
String hostingOn = ConfigurationManager.AppSettings["default_site_url"];
reqDetails.ReturnURL = hostingOn + "marketplace_confirm.aspx";
reqDetails.CancelURL = hostingOn + "marketplace.aspx";
reqDetails.NoShipping = "1";
reqDetails.ReqConfirmShipping = "0";
reqDetails.OrderTotal = new BasicAmountType()
{
currencyID = CurrencyCodeType.CAD,
Value = payment_amt.Value,
};
SetExpressCheckoutReq req = new SetExpressCheckoutReq()
{
SetExpressCheckoutRequest = new SetExpressCheckoutRequestType()
{
Version = UtilPayPalAPI.Version,
SetExpressCheckoutRequestDetails = reqDetails
}
};
PayPalAPIAASoapBinding paypal = new PayPalAPIAASoapBinding();
paypal.SetExpressCheckout(req);
I am also using the https://api-aa-3t.paypal.com/2.0/ url for accessing the API
Since early 2016, Paypal started requiring TLS 1.2 protocol for communications in the Sandbox, and will enforce it for the live environment starting June 17. See here for reference.
In most .NET applications TLS 1.2 will come disabled by default, and therefore you'll need to enable it.
You need to add the following line, for example, at the beginning of you Application_Start method:
public class Site : HttpApplication
{
protected void Application_Start()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// other configuration
}
}
You're probably connecting to api.paypal.com or api.sandbox.paypal.com, and not sending along your API certificate. The API certificate is a client SSL certificate used to complete the SSL chain.
If you don't have or are not using an API certificate, you should connect to api-3t.paypal.com or api-3t.sandbox.paypal.com for Live or Sandbox respectively.
I've been working with a PayPal (NVP/Signature) Express Checkout integration and have been hit with this SSL/TLS error.
Nothing I did seemed to get around it but then I found the following code to add above my request. For reference, I'm using MVC3/.NET 4 so Tls1.2 isn't available to me by default (like in .NET 4.5 +). This first three lines of this code gets around that. I hope it helps people!
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
ServicePointManager.DefaultConnectionLimit = 9999;
var url = "https://[paypal-api-url]/nvp";
var uri = new Uri(url);
var request = WebRequest.Create(uri);
var encoding = new UTF8Encoding();
var requestData = encoding.GetBytes(data);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Timeout = (300 * 1000);
request.ContentLength = requestData.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(requestData, 0, requestData.Length);
}
var response = request.GetResponse();
...
Thanks a lot that really helps me.
For reference here is my code for establishing the interface in VB.NET
'Create a service Binding in code
Dim ppEndpointAddress As New System.ServiceModel.EndpointAddress("https://api-3t.sandbox.paypal.com/2.0/")
Dim ppBinding As New System.ServiceModel.BasicHttpBinding(System.ServiceModel.BasicHttpSecurityMode.Transport)
Dim ppIface As New PayPalAPI.PayPalAPIAAInterfaceClient(ppBinding, ppEndpointAddress)
Dim ppPaymentReq As New PayPalAPI.DoDirectPaymentReq()
ppPaymentReq.DoDirectPaymentRequest = ppRequest

Amazon (AWS) - The request must contain the parameter Signature

I'm struggling with the final part of getting my first bit of code working with the AWS - I have got this far, I attached the web reference in VS and this have this
amazon.AWSECommerceService service = new amazon.AWSECommerceService();
// prepare an ItemSearch request
amazon.ItemSearchRequest request = new amazon.ItemSearchRequest();
request.SearchIndex = "DVD";
request.Title = "scream";
request.ResponseGroup = new string[] { "Small" };
amazon.ItemSearch itemSearch = new amazon.ItemSearch();
itemSearch.AssociateTag = "";
itemSearch.Request = new ItemSearchRequest[] { request };
itemSearch.AWSAccessKeyId = ConfigurationManager.AppSettings["AwsAccessKeyId"];
itemSearch.Request = new ItemSearchRequest[] { request };
ItemSearchResponse response = service.ItemSearch(itemSearch);
// write out the results
foreach (var item in response.Items[0].Item)
{
Response.Write(item.ItemAttributes.Title + "<br>");
}
I get the error
The request must contain the parameter Signature.
I know you have to 'sign' requests now, but can't figure out 'where' I would do this or how? any help greatly appreciated?
You have to add to the SOAP request headers including your Amazon access key ID, a timestamp, and the SHA256 hash of the request operation and the timestamp. To accomplish that, you would need access to the SOAP message just before it is going to be sent out. There's a walkthrough and a sample project I put together at http://flyingpies.wordpress.com/2009/08/01/17/.
For the record:
Another reason to get this error is due to keywords with spaces in it.
Example:
'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=xxx&AssociateTag=usernetmax-20&Version=2011-08-01&Operation=ItemSearch&ResponseGroup=Medium,Offers&SearchIndex=All&Keywords=Baby
Stroller&MerchantId=All&Condition=All&Availability=Available&ItemPage=1&Timestamp=2012-05-16T02:17:32Z&Signature=ye5c2jo99cr3%2BPXVkMyXX8vMhTC21UO4XfHpA21%2BUCs%3D'
It should be:
'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=xxx&AssociateTag=usernetmax-20&Version=2011-08-01&Operation=ItemSearch&ResponseGroup=Medium,Offers&SearchIndex=All&Keywords=Baby%20Stroller&MerchantId=All&Condition=All&Availability=Available&ItemPage=1&Timestamp=2012-05-16T02:17:32Z&Signature=ye5c2jo99cr3%2BPXVkMyXX8vMhTC21UO4XfHpA21%2BUCs%3D'
PHP solution:
$Keywords = str_replace(' ', '%20', $Keywords);
or
$Keywords = urlencode($Keywords);

Categories

Resources