Google Translate API: Requests from this client application <empty> are blocked - java

I've been getting error 403 - Requests from this Android client application are blocked using paid Google Cloud Platform Translation API. Works great when restrictions are set to none.
There are a few threads around reporting similar issue, but none answered.
I've seen in some examples, there's a version which had .setApplicationName(), I think that might help, but I can't find which version would that be.
Code used is:`
private void translate(String textToTranslate, String targetLanguage, TranslateCallback callback) {
try {
TranslateOptions options = TranslateOptions.newBuilder()
.setApiKey( < api_key >)
.build();
Translate trService = options.getService();
Translation translation = trService.translate(textToTranslate,TranslateOption.targetLanguage(targetLanguage));
callback.onSuccess(translation.getTranslatedText());
}
catch(Exception e) {
callback.onFailure();
}
}`
from: https://medium.com/#amsanjeev/adding-translate-api-to-android-apps-788c5bca5521

Finally I found a way.
When setting up your API key restriction for android app, you specified the package name and SHA-1 certificate fingerprint. So when you send an request to Google, you must add these information in the header of each request.
connection.setRequestProperty("X-Android-Package", "com.example.awesomeapp");
String sign = "5D:5A:12:D3:......".toLowerCase(); //Your SHA1 key in lower cased.
connection.setRequestProperty("X-Android-Cert", sig);
A detailed answer can be found here.

Related

Bad request (invalid value) when trying to retrieve in-app purchase info using the Java Google Play Developer API v3 with a valid purchase token

When using the Java Google Play Developer API (version 3), and requesting purchase information for a valid purchase token, I get the below exception. The API call returns a 400 Bad Request response with the following message.
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid Value",
"reason" : "invalid"
} ],
"message" : "Invalid Value"
}
Unfortunately there is no further information. I do not know what value is invalid.
First, we have contacted Google support about this. Unfortunately we have been going back and forth with Google support for almost 2 months and they still haven't even indicated they correctly understand what our problem is. Every time they reply, they give us suggestions that have literally nothing to do with the Google Play Developer API, even after thoroughly explaining the problem multiple times. This is the most frustrating support experience I've had in 20 years. Google support is clearly not going to be of any help here.
Second, we have successfully linked our Google Play account and our back-end. All necessary configuration is complete and working. On our back-end we are getting notifications from Google Play whenever an Android in-app purchase is made, and these notifications include a purchase token. This took some substantial effort, but I am confident this is now all correct, our service account is configured correctly, and all permissions and such are good.
I am able to successfully call the API that returns a list of available in-app-purchase products. I get a full and correct listing of the products we have configured in Google Play for users to purchase in our app. In order to make this call, we must provide credentials, and I assume the server is validating these credentials when we make this call. Since I can successfully make this call, I am assuming the "Invalid Value" is not related to our credentials. We are using a Google-generated JSON file created for a specific service account (not using a p12 file).
I have searched StackOverflow, and the rest of the internet looking for information on this issue. I have found many pages indicating the same or similar problem, but using an older version of the Google Play Developer API, which apparently did things differently. The solutions offered do not seem to apply to the v3 API. I have been searching for many weeks and trying various solutions I've come across all with no success.
I have written a test app that I run on my local PC which works when I am requesting a listing of in-app products, but does not work when requesting the purchase details for a given purchase token. I have tried with many different purchase tokens. I read that the test tokens are not actually valid for use with this particular API, so I actually released to production a build of our app that I am able to make a real, actual purchase with. I have done this, been charged by Google, and our back-end has received real and valid purchase tokens from these purchases.
private static void testGooglePlayDevAPI_Purchase() throws Throwable {
final String productIdSku = "[the_product_sku]";
final String purchaseToken = "[a_valid_purchase_token]";
final String packageName = "[our_app_id]";
final File GOOGLE_PLAY_DEV_API_CREDENTIALS =
new File("path_to_file/google-api-credentials.json");
final FileInputStream credentials =
new FileInputStream(GOOGLE_PLAY_DEV_API_CREDENTIALS);
final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
final HttpTransport TRANSPORT =
GoogleNetHttpTransport.newTrustedTransport();
String scope = AndroidPublisherScopes.ANDROIDPUBLISHER;
GoogleCredential credential = GoogleCredential
.fromStream(credentials, TRANSPORT, JSON_FACTORY)
.createScoped(Arrays.asList(scope));
AndroidPublisher publisher = new AndroidPublisher
.Builder(TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(packageName)
.build();
try {
AndroidPublisher.Purchases purchases = publisher.purchases();
AndroidPublisher.Purchases.Products products = purchases.products();
AndroidPublisher.Purchases.Products.Get get =
products.get(packageName, productIdSku, purchaseToken);
ProductPurchase product = get.execute();
System.out.println(String.format(
"Product purchase data found [developerPayload=%s]",
product.getDeveloperPayload()));
} catch (Throwable t) {
System.out.println(ExceptionSupport.getExceptionDetails(t));
}
}
I expect the above code to give me a response with valid product purchase data (a valid ProductPurchase instance that I can interrogate and process). Instead, all I ever get here is a 400 Bad Request response indicating that SOME VALUE (I don't know which) is invalid. The actual response is:
com.google.api.client.googleapis.json.GoogleJsonResponseException:
400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid Value",
"reason" : "invalid"
} ],
"message" : "Invalid Value"
}
UPDATE:
I've provided my own answer to this question below.
I'll provide my own answer here because we finally found a work-around. It turns out that something in the Java Google Play Developer API (v3) client library is not working correctly. I don't know what it is, but the documentation for that client library is terrible and Google provides NO examples of using it. However, it turns out that we can successfully use the HTTPS/JSON/OAuth2 API directly without going through the Java client. We have implemented our server-side solution using this approach and caching the OAuth2 tokens in memcache until they expire.
I double-checked and we were emailing back-and-forth with Google support for 2 months!!! They were of no assistance at all. I find this to be remarkable (in a bad way).

Multi OAuth Authentication in Vertx

I have the following code:
Class<OAuthHandler> _tempClass = (Class<OAuthHandler>) Class.forName(providerClass);
Constructor<OAuthHandler> oAuthHandlerConstructor = _tempClass.getDeclaredConstructor(Vertx.class);
OAuthHandler oAuthHandler = oAuthHandlerConstructor.newInstance(vertx);
OAuth2Auth oAuth2Auth = oAuthHandler.getoAuth2Auth();
/* AccessToken accessToken = */ oAuth2Auth.getToken(oAuthHandler.getTokenConfig(code), accessTokenResponse -> {
if (accessTokenResponse.failed()) {
System.out.println("Failed to obtain token");
} else {
AccessToken accessToken = accessTokenResponse.result();
// Return the token? Somehow.
}
});
The oAuthHandler is a provider specific implementation providing some config etc based on the provider name, and simply wraps around the methods provided by the vertx-auth-oauth2 library.
I would like to use the access token after it returns, but not inside the getToken Lambda, so I can get any information about the user I need.
Ive seen some things about Vert.x Futures, but unsure if I can even use them here, any suggestions or examples to solutions would be much appreciated!
Vert.x OAuth2 support is not vendor specific. According to the documentation http://vertx.io/docs/vertx-web/java/#_oauth2authhandler_handler you will see that the same code can handle the following providers:
Google
Twitter
Github
LinkedIn
Facebook
Keycloak
and as soon as 3.4 is released some small fixes will make it also compatible with:
Azure AD
Also the handler is generic so if you have your own provider you can also use it.
Now regarding the second part of the question how to use the the token directly, then you probably do not want the OAuth2Handler since it hides all this from you and you want to interact with OAuth2 client directly:
http://vertx.io/docs/vertx-auth-oauth2/java/#_getting_started
From the documentation above there is an getting started code example that allows you to interact with the get token without using reflection. This is way better since you will not be hurt if internal api's change.

Using Https Protocol for downloading data from Flickr

Since June 2014, all API keys just work via HTTPS only.Flickr deprecate non-SSL access to the API. There is another Post, but It's for 6 years ago which is before this event.
I know how to download data from Flickr, and I know it should work, but the problem is the library doesn't support Https.
I am trying to count the number of Images that have been shared by a user. I used getPeopleInterface().getPublicPhotos(userId,100,1) method.
but the problem is, it returns back Error 403 for URL!
I checked the Url in browser, and the Error is "SSL is required."
So I changed http to https in the URL and it worked. I do not know how I can change it in my code.
public class GetUsersPhotos {
public static void main(String[] args) throws Exception{
String key = "";
String secret = "";
String userId = "78069284#N00";
Transport t = new REST();
Flickr f = new Flickr(key, secret, t);
PhotoList list = f.getPeopleInterface().getPublicPhotos(userId,100,1);
System.out.println(list);
}
}
I solved my problem. The Flickrapi 1.2,doesn't support Https Protocol. What I did I downloaded Flickr4Java.jar which I checked and support Https, and then add the latest log4j jar file. then, it works.

Google Drive API Authentication - how to do it and how to implement it?

I'm trying to get the title of a document using the file ID. Here's the code:
private static void printFile(Drive service, String fileId) {
try {
File file = service.files().get(fileId).execute();
System.out.println("Title: " + file.getTitle());
} catch (IOException e) {
System.out.println("An error occured: " + e);
}
}
}
However, when I run it I receive a 403 forbidden error that states, "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
I assume that I have to authenticate, but seeing as I'm completely new to Google Drive API and also java, I'm confused as to how to do this (forgive me). I found this webpage: https://developers.google.com/drive/web/auth/web-server which explains how to authenticate but I'm still confused. The page lists multiple classes that do thing such as exchange the authorization code for an access token and use OAuth 2.0 credentials.
My question is do I need to use all of these classes to authenticate? And how do I implement them into my code?
Here is a brief explanation at the http level.
Any Google Drive REST API call requires an http Authorization: Bearer xxxxxx to be set. If there is no such header, you'll get the 403 you're experiencing
The xxxxx is an access token. There are a myriad ways to get one of these depending on the user experience you want to implement and whether you're trying to access the user's Drive files or the application's. Read the Google docs and experiment with the OAuth Playground.
The Google Java library attempts to abstract all of the above. Whether it does a good job or not is for you to decide. Personally I've had more success calling the REST API directly.

How to migrate OAuth1 token/secret pairs to OAuth2 access tokens for the Dropbox API?

If a user has already authorized our app for OAuth 1 (so we have a valid token/secret pair for this user), is it possible to get a valid OAuth 2.0 access token without the user having to explicitly re-authorize our app again? I know that some APIs support this (e.g. Soundcloud and I think also Google), but I haven't found anything related to OAuth token migration in the Dropbox API documentation.
Context: We have an application in Java that accesses the Dropbox API with OAuth 1.0a using the Scribe OAuth library and want to migrate to the official Dropbox Java API that only supports OAuth 2 (and we don't want to have all our users having to re-authorize us).
Just for people stumbling upon this, the API for this is now there: https://www.dropbox.com/developers/core/docs#oa2-from-oa1
From their Java SDK, I used their Upgrader class like so
DbxOAuth1Upgrader upgrader;
DbxOAuth1AccessToken oAuth1AccessToken;
try {
DbxRequestConfig requestConfig = new DbxRequestConfig("Your App", Locale.getDefault().toString());
DbxAppInfo appInfo = new DbxAppInfo(DROPBOX_APP_KEY, DROPBOX_APP_SECRET);
upgrader = new DbxOAuth1Upgrader(requestConfig, appInfo);
oAuth1AccessToken = new DbxOAuth1AccessToken(oauth1AccessKey, oauth1AccessSecret);
String newToken = upgrader.createOAuth2AccessToken(oAuth1AccessToken);
upgrader.disableOAuth1AccessToken(oAuth1AccessToken);
return newToken;
} catch (Exception e) {
//deal with it
}
It's snipped for relevance but if you're doing this in Android, make sure you do it inside an AsyncTask otherwise it throws an exception for performing work on the main thread.
See also the answer on the Dropbox forum: https://forums.dropbox.com/topic.php?id=107766. For now, there's no automated way today to do this migration.

Categories