Facebook Java SDK | Marketing API Error #803 - java

I am currently trying to use the Facebook Java SDK to publish ads automatically.
I am just attempting to test my API Authentication using the basic facebook demo code they have provided: https://developers.facebook.com/docs/business-sdk/getting-started/
Here is where I define my APIContext so that I can instantiate my AdAccount:
public static final APIContext context = new APIContext(
"{App Auth Token}",
"{App Secret}"
);
When I execute System.out.println(context.getAppID()); I am returned the ID of the App I have set up within developers.facebook. At this point I think everything is working as intended...?
I then attempt to execute the following code:
AdAccount account = new AdAccount("act_{10405322}", context);
try {
APINodeList<Campaign> campaigns = account.getCampaigns().requestAllFields().execute();
for(Campaign campaign : campaigns) {
System.out.println(campaign.getFieldName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
My application keeps failing with this response:
com.facebook.ads.sdk.APIException$FailedRequestException: {"error":{"message":"(#803) Some of the
aliases you requested do not exist:
act_{10405322}","type":"OAuthException","code":803,"fbtrace_id":"A3uiRKVWUVQyMqZO9GIfWAY"}}
Could someone explain to me why this is the case? act_{10405322} is the ad account I am attempting to reach, so I am not sure why the "alias does not exist"
Thanks!

After rigorous testing, I found two issues that solved my error.
I was using a App Token rather than a Page Access Token
I changed act_{10405322} to act_10405322 and I finally got a successful response.

Related

How to fix AWS 403 error "Check your AWS Secret Access Key and signing method" when calling SES listcontacts

I have been stuck for about the past 6 hours at this point I'm thinking the only reasonable explanations are that this is a AWS SDK bug or the error message is wrong.
I am using SESv2 class from the AWS SDK in a JAVA SpringBoot app and attempting to manage various details of my SES (Simple Email Service) account.
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sesv2.SesV2Client;
import software.amazon.awssdk.services.sesv2.model.*;
I have created an IAM user, created security credentials, set them up using multiple different methods as described here guid to credentials environment I've given full access to SES to this IAM role user. I then wrote some code and I was able to do all of the following,
Create a contact list
Delete a contact list
Create contact
Create a Topic in a contact list
Send an email
However, for some unknown reason when I go to test a function I wrote to get a list of contacts so I can test sending an email to multiple contacts I get the following 403 error message,
The request signature we calculated does not match the signature you
provided. Check your AWS Secret Access Key and signing method. Consult
the service documentation for details.
I've verified the credentials are correct. I have created a new set of credentials and made the old set inactive. No dice, all the functions listed above still work however the listContacts in the SesV2Client class still fails with the same error. As you can see below I even bypassed the env variables and just hardcoded the key and secret to pull out all the stops, still fails. In the function that fails, I've gone over and over the values im passing in they are valid and exist 100% because as I said I can make the other calls in the list above to verify the topics and contact list exists.
private List<Contact> listContactsForSiteUpdatesMailingList() {
try (SesV2Client client = SesV2Client.builder()
.region(Region.US_EAST_1)
.credentialsProvider(StaticCredentialsProvider.create(awsCreds))
.build()){
TopicFilter topicFilter = TopicFilter.builder().topicName(TOPIC_SITE_UPDATES).useDefaultIfPreferenceUnavailable(true).build();
ListContactsFilter listContactsFilter = ListContactsFilter.builder().topicFilter(topicFilter).filteredStatus(SubscriptionStatus.OPT_IN).build();
ListContactsRequest listContactsRequest = ListContactsRequest.builder()
.contactListName(CONTACT_LIST).filter(listContactsFilter).build();
ListContactsResponse listContactsResponse = client.listContacts(listContactsRequest);
return listContactsResponse.contacts();
} catch (Exception ex) {
System.out.println("The email was not sent. Error message: "
+ ex.getMessage());
return null;
}
}
Whats going on here and how can I get to the bottom of this error?
EDIT:
Looking at AWS Console Users>Access Management and then looking at the user a created I can even verify that there was "programmatic access"
An example of accessing a ContactList with no issues
EDIT 2: My SES account is currently sandboxed. I just wanted to mention the question is this possibly happening because of that? Grasping at straws here.
I was able to reproduce your issue. I created a list and added a contact. Both worked. However, when i executed listContacts, I got this error:
This looks like a bug. To address this, open a Github issue on the SDK Java Github here:
https://github.com/aws/aws-sdk-java
This is confirmed as a bug in the AWS SDK. To get around this you can use the async client like so
SesV2AsyncClient client = SesV2AsyncClient.builder()
.region(Region.US_EAST_1)
.build())
TopicFilter topicFilter = TopicFilter.builder().topicName(TOPIC_SITE_UPDATES).useDefaultIfPreferenceUnavailable(true).build();
ListContactsFilter listContactsFilter = ListContactsFilter.builder().topicFilter(topicFilter).filteredStatus(SubscriptionStatus.OPT_IN).build();
ListContactsRequest listContactsRequest = ListContactsRequest.builder()
.contactListName(CONTACT_LIST).filter(listContactsFilter).build();
CompletableFuture<ListContactsResponse> listContactsResponseCompletableFuture = client.listContacts(listContactsRequest);
ListContactsResponse listContactsResponse = listContactsResponseCompletableFuture.get();

GAE HttpResponseException: 401

I am trying to access the DataStore of one app from another GAE project using Remote API.
I am using the following code:
String serverString = "http://example.com";//this should be the target appengine
RemoteApiOptions options;
if (serverString.equals("localhost")) {
options = new RemoteApiOptions().server(serverString, 8080).useDevelopmentServerCredential();
} else {
options = new RemoteApiOptions().server(serverString, 80).useApplicationDefaultCredential();
}
RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
datastore = DatastoreServiceFactory.getDatastoreService();
try {
results = datastore.get(KeyFactory.createKey("some key"));
} catch (EntityNotFoundException e) {
e.printStackTrace();
return null;
}
when I run this locally, i get a nullpointerexception at installer.install(options);.
and when deployed, the error seen from error reporting on the appengine is :HttpResponseException: 401 You must be logged in as an administrator, or access from an approved application.
That being said, I made a small java application with the follwing code:
String serverString = "http://example.com";//same string as the one used in the above code
RemoteApiOptions options;
if (serverString.equals("localhost")) {
options = new RemoteApiOptions().server(serverString, 8080).useDevelopmentServerCredential();
} else {
options = new RemoteApiOptions().server(serverString, 80).useApplicationDefaultCredential();
}
RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
try {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
System.out.println("Key of new entity is " + ds.put(new Entity("Hello Remote API!")));
and this one works!! Hello Remote API entity is added.
The reason it does not work when running on App Engine vs running locally has to do with the credentials that are being picked up. When running locally, it is likely using your own credentials (which has access to both projects); by contrast, when running on App Engine, you are likely picking up the App Engine default service account, which only has access to that App Engine project.
Try fixing this by opening the Cloud IAM section of Cloud Console for the project containing the Cloud Datastore that you wish to access. There, grant the appropriate level of access to the default App Engine service account that is being used by the other project.
If you don't want all App Engine services in the other project to have this kind of access, you might also consider, instead, generating a service account for this cross-project access that you grant the appropriate access to (rather than granting that access to the default App Engine service account). Then, in your code that calls the API, you would explicitly use that service account by calling the useServiceAccountCredential() method of RemoteApiOptions to ensure that the API requests that are issued use the specified service account rather than the default App Engine service account.

Java, Evernote : Revoke access for app on Evernote

I am working on a Java project which has Evernote services integrated into it through an app created on Evernote. Currently, everything is working fine except for access-revocation.
When an user who has already authorized the app, at some point decides not to give this app any access, I would like to also de-authorize the app from the users evernote account.
For this, I am searching for some sample, but came empty handed. One link I found was this, where it was required to call that method with UserStore. I have the access-token, but unfortunately I am only working with NoteStoreClient, rather than UserStore.
Here is the revocation code I have so far.
Person person = this.personService.getCurrentlyAuthenticatedUser();
if (!(person == null)) {
if (person.isEvernoteConsumed()) {
try {
this.evernoteDAO.deleteEvernoteForUser(person.getId());
Evernote evernote = getUsersEvernote(person.getId());
EvernoteAuth evernoteAuth = new EvernoteAuth(EVERNOTE_SERVICE, evernote.getAccessToken());
NoteStoreClient noteStoreClient = new ClientFactory(evernoteAuth).createNoteStoreClient();
}catch (Exception e){
e.printStackTrace();
}
}
}
Nothing fancy in that code, I know. If anyone has any idea of revocation from Evernote, kindly let me know. Thank you.
You're on the right track, that UserStore method will let you revoke your OAuth session. Like you said, you have to use the userstore client instead, you should be able to create it the same way as you did the notestore client:
UserStoreClient userStoreClient =
new ClientFactory(evernoteAuth).createUserStoreClient();
userStoreClient.revokeLongSession(evernoteAuth);

Java: Oauth 2.0 How can I use Google API RefreshTokens to avoid requesting access every time my app launches?

There is a lot of sample code for the google API showing how to Get an authorization token and use it, but I cannot find any sample code that shows you how to use the Oauth 2.0 GoogleAccessProtectedResource.refreshToken() method in the java client to get a new authorization token in in Java. Google search turns up nothing, and I can only find a C# example on Stackoverflow. If you could point me to a bit of sample code in Java showing how this is done that would be great. The platform I am working on in Android. An example of the model of OAuth 2.0 I would like to use is here: http://blog.doityourselfandroid.com/2011/08/06/oauth-2-0-flow-android/
Thanks a lot
Answering my own question here. It turned out to be quite straight forward, by calling GoogleAccessProtectedResource.refreshToken() the accesstoken is refreshed inside the class, it can be read and reused as needed through its getter.
You would have to catch 401(unauthorized) errors. After this do something like this.
accountManager.invalidateAuthToken(accessProtectedResource.getAccessToken());
accessProtectedResource.setAccessToken(null);
After this simply get back the token. This time user will not have to authorize access again.
accountManager.manager.getAuthToken(account, AUTH_TOKEN_TYPE, true,
new AccountManagerCallback<Bundle>() {
#Override
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
if (bundle.containsKey(AccountManager.KEY_INTENT)) {
Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent, REQUEST_AUTHENTICATE);
} else if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) {
accessProtectedResource.setAccessToken(bundle.getString(AccountManager.KEY_AUTHTOKEN));
onAuthToken();
}
} catch (Exception e) {
handleException(e);
}
}
}, null);
Refer the task sample for reference and the corresponding article.

How do I programatically list my LinkedIn contacts?

I have searched the LinkedIn APIs, but I cannot see a way to get the contacts. I know that there are some applications that have this functionality, but I am wondering is this legal or if they use some kind of partner API?
I think that the Connections API probably does what you need.
This is a Web API, so from Java you would need to use an URL.connect() or Apache HttpClient or something like that, using an appropriately formed request URL. Then you'd need to configure an XML parser to parse the XML response body and extract the contact details.
As the page states, your client needs to be authenticated (as you) to access your contacts, and the API won't let you see details that you cannot see using your web browser.
I created a plugin for Play Framework to easily integrated with LinkedIn's OAuth: http://geeks.aretotally.in/projects/play-framework-linkedin-module.
Hopefully it can help. You should def check out Play, very very cool Java framework.
1) First click below link and add your app to developer account
The r_network scope recently changed to be a LinkedIn partner-only permission. You can apply for access to their partnership program here:
https://developer.linkedin.com/partner-programs/apply
2) After successfully creation of your app on developer account make permission of r_network
3) Insert Following code after importing all required linked-in sdk file from this https://developer.linkedin.com/docs/android-sdk
private static final String topCardUrl = "https://api.linkedin.com/v1/people/~:(id,first-name,email-address,last-name,num-connections,headline,picture-url,industry,summary,specialties,positions:(id,title,summary,start-date,end-date,is-current,company:(id,name,type,size,industry,ticker)),educations:(id,school-name,field-of-study,start-date,end-date,degree,activities,notes),associations,interests,num-recommenders,date-of-birth,publications:(id,title,publisher:(name),authors:(id,name),date,url,summary),patents:(id,title,summary,number,status:(id,name),office:(name),inventors:(id,name),date,url),languages:(id,language:(name),proficiency:(level,name)),skills:(id,skill:(name)),certifications:(id,name,authority:(name),number,start-date,end-date),courses:(id,name,number),recommendations-received:(id,recommendation-type,recommendation-text,recommender),honors-awards,three-current-positions,three-past-positions,volunteer)?format=json";
public void getUserData() {
APIHelper apiHelper = APIHelper.getInstance(MainActivity.this);
apiHelper.getRequest(MainActivity.this, topCardUrl, new ApiListener() {
#Override
public void onApiSuccess(ApiResponse result) {
try {
//here you get data in json format
//you have to parse it and bind with adapter for connection list
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onApiError(LIApiError error) {
}
});
}

Categories

Resources