Google Books API - keep getting error code "403" reason: "ipRefererBlocked" - android

I am using this as my request url:
`String isbnUrl = "https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn + "&key=" + myAPIKEY;`
Can anyone tell me why I keep getting this response:
{
"error":{
"errors":[
{
"domain":"usageLimits",
"reason":"ipRefererBlocked",
"message":"There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed.",
"extendedHelp":"https://console.developers.google.com"
}
],
"code":403,
"message":"There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed."
}
}
I have gone through the process of getting an API for my Android app using the debug keystore and release keystore and can't seem to get it to work I have tried adding my key as a header as suggested as an answer here: Google Books API 403 Access Not Configured.
I thought this was the answer but then realized by accident that it was the same as not supplying a key at all. I came to this realization after entering the wrong String as the key and it still worked.
In the developer console I am seeing that it receives the request from my API under usage response code section: Client errors (4xx).
I would really appreciate any help if anyone has figured out how to get this API to work the way Google wants by including the key.

Problem is when setting up your API key restriction for android app, you specified the package name and SHA-1 certificate fingerprint. Therefore your API key will only accept request from your app with package name and SHA-1 certificate fingerprint specified.
So when you send an request to Google, you MUST add these information in the header of each request with following keys:
Key: "X-Android-Package", value: your app package name
Key: "X-Android-Cert", value: SHA-1 certificate of your apk
FIRST, get your app SHA signature (you will need Guava library):
/**
* Gets the SHA1 signature, hex encoded for inclusion with Google Cloud Platform API requests
*
* #param packageName Identifies the APK whose signature should be extracted.
* #return a lowercase, hex-encoded
*/
public static String getSignature(#NonNull PackageManager pm, #NonNull String packageName) {
try {
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
if (packageInfo == null
|| packageInfo.signatures == null
|| packageInfo.signatures.length == 0
|| packageInfo.signatures[0] == null) {
return null;
}
return signatureDigest(packageInfo.signatures[0]);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
private static String signatureDigest(Signature sig) {
byte[] signature = sig.toByteArray();
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] digest = md.digest(signature);
return BaseEncoding.base16().lowerCase().encode(digest);
} catch (NoSuchAlgorithmException e) {
return null;
}
}
Then, add package name and SHA certificate signature to request header:
java.net.URL url = new URL(REQUEST_URL);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try {
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestProperty("Accept", "application/json");
// add package name to request header
String packageName = mActivity.getPackageName();
connection.setRequestProperty("X-Android-Package", packageName);
// add SHA certificate to request header
String sig = getSignature(mActivity.getPackageManager(), packageName);
connection.setRequestProperty("X-Android-Cert", sig);
connection.setRequestMethod("POST");
// ADD YOUR REQUEST BODY HERE
// ....................
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.disconnect();
}
You can see full answer here.
Enjoy coding :D

Related

Youtube API Key

When I try to use YouTube API for Search, I get this error:
There was a service error: 403 : The request did not specify any
Android package name or signing-certificate fingerprint. Please ensure
that the client is sending them or use the API Console to update your
key restrictions.
In the MainActivity I have this code:
youtube = new YouTube.Builder(new NetHttpTransport(), JSON_FACTORY, new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest httpRequest) throws IOException {
}
}).setYouTubeRequestInitializer(new YouTubeRequestInitializer(apiKey)).setApplicationName("Some Name").build();
In the cloud console I have an ApiKey for Android, with the package name set and the SHA-1 number obtained with keytool command.
At last I found a solution for this problem :)
After creating API_KEY in Google Developer Console and restrict it with "Package name" and "SHA-1 certificate fingerprint", You have to provide these data in every youtube api request. Below the steps:
1- get Package Name:
String packageName = context.getPackageName();
2- get SHA-1:
private String getSHA1(String packageName){
try {
Signature[] signatures = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures;
for (Signature signature: signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA-1");
md.update(signature.toByteArray());
return BaseEncoding.base16().encode(md.digest());
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
3- Prepare youtube api http header:
youTube = new YouTube.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) throws IOException {
String packageName = context.getPackageName();
String SHA1 = getSHA1(packageName);
request.getHeaders().set("X-Android-Package", packageName);
request.getHeaders().set("X-Android-Cert",SHA1);
}
}).setApplicationName(appName).build();
4- Build your youtube api query as you like:
For example to search for video:
YouTube.Search.List query;
query = youTube.search().list("id, snippet");
query.setKey(YOUR_API_KEY);
query.setType("video");
query.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)");
query.setQ(search keywords);
SearchListResponse response = query.execute();
List<SearchResult> results = response.getItems();
then process returned search results.
After lot of trial and error, the thing which finally worked for me was changing API KEY restriction to None instead of Android from API Manager console and just save.
After doing the above step I am able to make search API call from my Android device using my API KEY.
Try to double check if you follow properly the setup when creating OAuth Credentials. And make sure you enable the YouTube Data API in your Developer Console.
Here the steps that you need to do.
In the Package name field, enter your Android app's package
name
In a terminal, run the Keytool
utility to
get the SHA1 fingerprint for your digitally signed .apk file's public
certificate.
keytool -exportcert -alias androiddebugkey -keystore path-to-debug-or-production-keystore -list -v
Paste the SHA1 fingerprint into the form where requested.
I also found here in this SO question answered by a Googler that a user has to go through OAuth2. Because Service accounts are not supported in Data API v3.

Firebase 401 unauthorized error FCM

I'm trying to test out Firebase Cloud messaging APIs as all functionality is not available from console (notably customization of notifications when app is in background). But for some reasons, I cannot get it to work, and it always shows up 401 error. I investigated the reasons for this, and tried it after regenerating new server key, but the error remains constant. Surprisingly, when I generated a new server key, it is not reflected in Firebase console and it shows server key as empty. Also, I tried adding my IP address to the server whitelist IPs but still no luck. I've attached a screenshot of a request that I did with Postman (I substitue the server key in place of serverKey.
I'm stuck on this for a few hours and would really appreciate some help.
I don't know if someone uses the [Web API Key] as the [YOUR_SERVER_KEY] for POSTMAN test and keep getting '401 Error'. [Web API Key] is not [YOUR_SERVER_KEY].
You should go to your Firebase console and check this:
to get the correct Server key.
Hope it help.
I noticed from your screenshot that you were using "key: serverKey". Could you try using "key=serverKey" instead?
Also you don't need to have "POST fcm.googleapus.com/fcm/send"; this is not proper json and would explain the error you are seeing. The URL of the request is already defined elsewhere so remove it from the payload.
I faced the same problem.
the problem was that I was using the legacy server key. when I used the new version of the server key the problem solved.
in your firebase console goto settings -> cloud messaging
then use the new server key. it is longer than the old version key.
go to https://console.firebase.google.com/u/0/project/[project-name]/settings/cloudmessaging/
you can use Server Key or Legacy server key
I too am facing the Same problem... I am using curl in php for posting and it works only if I have php files stored on my LocalHost server. When I try to use access the files via a free hosting online, then it say Unautorized 401.
So I would suggest if you can, use the Localhost.
I have the same problem at Server Side Code(C#).
You basically used wrong Server Key (or API Key) for service side code.
Follow below Link over stackoverflow posted by me (Helpful to find Server Key (or API Key) )
FCM (Firebase Cloud Messaging) Push Notification with Asp.Net
401 with FCM through HTTPv1 (Error and Solution for Bearer)
If you are using FCM via HTTP v1, then you will have to make two sucessive POST requests:
1/ In the first call, you make a POST request to 'https://accounts.google.com/o/oauth2/token' (or using API packages) using your firebase service account key at
'https://console.firebase.google.com/u/0/project/{{firebaseProjectName}}/settings/serviceaccounts/adminsdk'
to get the access token.
2/ Then you have to make another POST request to 'https://fcm.googleapis.com/v1/projects/{{firebaseProjectName}}/messages:send'. If you have followed the steps for the migration from legacy HTTP to HTTP v1 (very clear documentation) on firebase website, you have to make some small changes at the content of the post request and also using 'Bearer ${accessToken.data}' for the Authorization.
In my case I was not properly awaiting for the accessToken in the first function (forgot the 'await' keyword in front of the function making the post request and AndroidStudio did not notice either that there was something wrong).
Make sure that you await the result of the first post request as it is a Future.
If you don't, Bearer will be null when you make the second POST request because you did not await for it.
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.Size;
public class PushNotificationSubmit {
public static void main(String[] args) {
new PushNotificationSubmit().send("sample message title", "sample message body");
}
final String serverKey = "AAAA_*******";
final String fcmUrl = "https://fcm.googleapis.com/fcm/send";
/**
* note from google: The value should be an array of registration tokens to which to send the multicast message. The array must contain at least 1 and at most 1000 registration tokens.
* send to specific users
*
* #param messageTitle
* #param messageBody
* #param tokenList
*/
#Size.List({#Size(min = 1), #Size(max = 999)})
public void send(String messageTitle, String messageBody, List<String> tokenList) {
try {
String payloadJson = createMessageAsJson(messageTitle, messageBody, tokenList);
doSend(payloadJson);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* send to all users that registered in my topic
*
* #param messageTitle
* #param messageBody
*/
public void send(String messageTitle, String messageBody) {
try {
String payloadJson = createMessageAsJson(messageTitle, messageBody, null);
doSend(payloadJson);
} catch (Exception e) {
e.printStackTrace();
}
}
private String createMessageAsJson(String messageTitle, String messageBody, List<String> tokenList) {
JSONObject payloadObj = new JSONObject();
try {
JSONObject notifyObj = new JSONObject();
notifyObj.put("title", messageTitle);
notifyObj.put("body", messageBody);
payloadObj.put("notification", notifyObj);
if (tokenList != null) {
if (tokenList != null && tokenList.size() > 0) {
JSONArray regId = new JSONArray();
for (int i = 0; i < tokenList.size(); i++) {
regId.put(tokenList.get(i));
}
payloadObj.put("registration_ids", regId);
}
} else {
payloadObj.put("to", "/topics/all");
}
return payloadObj.toString();
} catch (Exception e) {
// TODO: add logger
e.printStackTrace();
throw e;
}
}
private void doSend(String payloadJson) throws Exception {
HttpClient httpclient = HttpClientBuilder.create().build();
try {
HttpPost httpPost = new HttpPost(fcmUrl);
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Authorization", "key=" + serverKey);
httpPost.setEntity(new StringEntity(payloadJson, "UTF-8"));
HttpResponse response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
System.out.println("push notification status: " + response.getStatusLine());
EntityUtils.consume(entity);
} finally {
httpclient.getConnectionManager().shutdown();
}
}
}
In C# HttpClient response
For wrong server key it will happen, Invalid Key, Unauthorize, 401
I was facing the same problem, i solved it by using the following steps
1- In the server from where you are sending push, Use the browser key only, you can get it from Firebase console or google api console as I have highlighted in the below images:-
Google api console
Firebase console, click on the project-->settings
Note : The Firebase console web api key and google console browser key are the same you can use either of them
2- If you follow the first step only you will get the Unauthorized error, to resolve this you need to authorize your browser key in google console by adding your server IP address from where you will send the push. Click on the edit pencil icon on the right side of your browser key in google api console, above first image
After adding your Ip address click save
Make sure that your device token is not empty on which you are sending the push, I hope your push will be sent successfully now.

Android expiry time of In-app subscription item in android

I am trying to get expiry time or status of subscription to ensure if user is paying regularly for my item or not . When i query using
Purchase monthlySubscription = inv.getPurchase("itemName");
or
ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
It returns following data
{
"packageName":"com.abcPackage",
"productId":"auto1week",
"purchaseTime":1453369299644,
"purchaseState":0,
"developerPayload":"PAY_LOAD",
"purchaseToken":"TOKEN",
"autoRenewing":true
}
The problem is , purchaseTime remains same after several weeks which is supposed to be change after every purchase.
I tried google Play developers API
https://developers.google.com/android-publisher/#subscriptions
but i am having a hard time implementing it on my android device .
I will be grateful if someone can guide me step by step process to get this data on android device.
https://developers.google.com/android-publisher/api-ref/purchases/subscriptions
Any help in this regard will be highly appreciated.
Not sure if this will help, but here is my server side code (in java) that connects to the developer API and returns the expiration of the subscription.
I created a Service Account in the Google Developer Console, and followed the somewhat obtuse instructions to create a key file in src/resources/keys.json. APPLICATION_NAME is the package name of my app, and PRODUCT_ID is the subscription ID from the Google PLAY developer console.
Sorry it's not really 'step by step' as you asked for, but I also am doing verification on the server side instead of on the client. I suppose on the client you could do some sort of soft-verification by checking purchaseState == 0 (1=cancelled, 2=refunded), and autoRenewing==true. You may get stuck there if they cancel though, since you are still supposed to provide service through the duration of the subscription.
public static Long doSomeWork(String token){
log.debug("Google Validation: Doing some work:" + token);
try{
// Creating new Trusted Transport
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
// Getting Auth Creds
Credential cred = getAuthCredential();
// Building Android Publisher API call
AndroidPublisher ap = new AndroidPublisher.Builder(httpTransport, JSON_FACTORY, cred)
.setApplicationName(APPLICATION_NAME).build();
// Get Subscription
AndroidPublisher.Purchases.Subscriptions.Get get = ap.purchases().subscriptions().get(
APPLICATION_NAME,
PRODUCT_ID,
token);
SubscriptionPurchase subscription = get.execute();
log.debug(subscription.toPrettyString());
log.debug("DONE (not null)");
return subscription.getExpiryTimeMillis();
} catch(IOException ex) {
ex.printStackTrace();
} catch (GeneralSecurityException ex2) {
ex2.printStackTrace();
}
log.debug("DONE (failure) (0)");
return 0L;
}
private static Credential getAuthCredential(){
log.debug("getAuthCredential");
try{
//Read the credentials from the keys file. This file is obtained from the
// Google Developer Console (not the Play Developer Console
InputStream is = GoogleReceiptValidation.class.getClassLoader().getResourceAsStream("keys.json");
String str = IOUtils.toString(is);
is.close();
JSONObject obj = new JSONObject(str);
InputStream stream = new ByteArrayInputStream(obj.toString().getBytes());
//This is apparently "beta functionality".
GoogleCredential creds = GoogleCredential.fromStream(stream);
creds = creds.createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
return creds;
} catch (IOException ex){
ex.printStackTrace();
} catch (JSONException ex2){
ex2.printStackTrace();
}
log.debug("No Creds found - returning null");
return null;
}

Restrict access to my API Endpoint to Android App

I want to restrict my API endpoints access only to my android app, but without google_account/password.
I've the choice of those methods : https://developers.google.com/accounts/docs/OAuth2
For test, I succeeded to authenticate my android app to my API with this method: https://cloud.google.com/appengine/docs/python/endpoints/consume_android
==> This method allow you to authenticate your app with combo:
Login/password (Google account)
SHA1 and package name of your android APP
So if someone get my code (Decompiling apk) and modify my android code, they can't access to my API because SHA1 fingerprint of my app will change. (I tested it, and it works =) )
This method works fine, but I don't want Google login/password for authentication..
So I tried this method: https://developers.google.com/accounts/docs/OAuth2ServiceAccount
I successfully authenticate my android app, BUT, if my android code is modified by someone else(So the SHA1 changed), my android app can still connect to my API !! So if someone get my package and decompile it, he'll changed freely code and successfully access to my API..
Here is my API Code:
#ApiMethod( name = "ListCampagnes", httpMethod = ApiMethod.HttpMethod.GET, path="list", clientIds = {CONSTANTES.ANDROID_CLIENT_ID, CONSTANTES.WEB_CLIENT_ID, CONSTANTES.SERVICE_CLIENT_ID, com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID}, audiences = {CONSTANTES.ANDROID_AUDIENCE})
public Collection<Campagne> getCampagnes(#Named("NumPortable")String NumPortable, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
return CampagneCRUD.getInstance().findCampagne(NumPortable);
}
Here is my android code:
GoogleCredential credentialToAppengine;
try {
String p12Password = "notasecret";
KeyStore keystore = KeyStore.getInstance("PKCS12");
InputStream keyFileStream = getAssets().open("59ce5a08e110.p12");
keystore.load(keyFileStream, p12Password.toCharArray());
PrivateKey key = (PrivateKey)keystore.getKey("privatekey", p12Password.toCharArray());
credentialToAppengine = new GoogleCredential.Builder().setTransport(AndroidHttp.newCompatibleTransport()).setJsonFactory(new JacksonFactory()).setServiceAccountId("301991144702-3v9ikfp4lsmokee1utkucj35847eddvg#developer.gserviceaccount.com").setServiceAccountPrivateKey(key).setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email")).build();
} catch (GeneralSecurityException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
Do I try an other method for authenticate my android App ? Or did I missing something in my API code ?
Thanks a looot in advance,
Authenticate Android End point without Google User Account is just impossible ! I tried every ways but still doesn't works !
So here is my way to resolv this problem, without any user interaction (Maybe not the right but that works, and you've got strong authentication (SHA1 + Google Account)):
HERE IS MY ANDROID CODE
Get and Build Valid Credential
//Get all accounts from my Android Phone
String validGoogleAccount = null;
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
//Just store mail if countain gmail.com
if (account.name.toString().contains("gmail.com")&&account.type.toString().contains("com.google")){
validGoogleAccount=account.name.toString();
}
}
}
//Build Credential with valid google account
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this,"server:client_id:301991144702-5qkqclsogd0b4fnkhrja7hppshrvp4kh.apps.googleusercontent.com");
credential.setSelectedAccountName(validGoogleAccount);
Use this credential for secure calls
Campagneendpoint.Builder endpointBuilder = new Campagneendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), credential);
HERE IS MY API BACKEND CODE:
API Annotation
#Api(
scopes=CONSTANTES.EMAIL_SCOPE,
clientIds = {CONSTANTES.ANDROID_CLIENT_ID,
CONSTANTES.WEB_CLIENT_ID,
com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {CONSTANTES.ANDROID_AUDIENCE},
name = "campagneendpoint",
version = "v1"
)
Method code:
public Collection<Campagne> getCampagnes(#Named("NumPortable")String NumPortable, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
return CampagneCRUD.getInstance().findCampagne(NumPortable);
}
For the moment, it only works on Android (I don't know how we gonna do on IOS..)..
Hope It will help you !

Signature verification, Android in app billing failing after previously working

Background:
We have an Android app that is currently on sale via Google Play. For the app to function the user must purchase a "token" via In-App Billing. The "token" is a consumable item, eg used once and finished with. To verify the token, we send the purchase data to a server which uses standard Java RSA security code to verify the information returned from the Play Store is valid. (Code below).
We did extensive testing prior to releasing the app, and even once the app is on the store, we did some more testing. The data being returned from Google passed verification every time. Then about the start of December the signature verification started failing. We haven't changed the code or the app in the store, and the verification code on the server has remained static.
I've debugged the code, and ran the receipt data and signature data being returned from the Play Store and it indeed now fails verification. I'm at a loss to explain what has changed, or why the verification started failing, when it was working fine.
Question:
Has anyone come across this before, where signature verification failed in an app that hasn't changed? Any tips on where to start looking to try and work out where the issues may be coming from?
Further Information
The only thing that I can think of changing, is Google released the in-app billing API v3, but that shouldn't effect V2, which is what we use.
To aide development, we use the net.robotmedia.billing library to handle the IAB.
Below is the server verification code for data returned from Play Store
where encodePublicKey => our public key from Play Store
signedData => base64 encoded receiptData as return from Play Store purchase
signature => signature as returned from Play Store
public class Security {
public final static Logger logger = Logger.getLogger(Security.class.getName());
private static final String KEY_FACTORY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* Generates a PublicKey instance from a string containing the
* Base64-encoded public key.
*
* #param encodedPublicKey
* Base64-encoded public key
* #throws IllegalArgumentException
* if encodedPublicKey is invalid
*/
public static PublicKey generatePublicKey(String encodedPublicKey) {
try {
byte[] decodedKey = Base64.decode(encodedPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
catch (InvalidKeySpecException e) {
logger.error("Invalid key specification.", e);
throw new IllegalArgumentException(e);
}
catch (Base64DecoderException e) {
logger.error("Base64 decoding failed.", e);
throw new IllegalArgumentException(e);
}
}
/**
* Verifies that the signature from the server matches the computed
* signature on the data. Returns true if the data is correctly signed.
*
* #param publicKey
* public key associated with the developer account
* #param signedData
* signed data from server
* #param signature
* server signature
* #return true if the data and signature match
*/
public static boolean verify(PublicKey publicKey, String signedData, String signature) {
Signature sig;
try {
sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
byte[] decodedSig = Base64.decode(signature);
if (!sig.verify(decodedSig)) {
logger.error("Signature verification failed.");
return false;
}
return true;
}
catch (NoSuchAlgorithmException e) {
logger.error("NoSuchAlgorithmException.");
}
catch (InvalidKeyException e) {
logger.error("Invalid key specification.");
}
catch (SignatureException e) {
logger.error("Signature exception.");
}
catch (Base64DecoderException e) {
logger.error("Base64 decoding failed.");
}
return false;
}
}
for me maybe file encoding was the problem,
after changing eclipse workspace, it used mac file format again.
changing it to UTF-8 and copy&paste the key again into the project,
everything works fine now :/
wasted hours :/
Just an update. I never got to the bottom of why it stopped failing verification. We think it could be an issue with the Google Play servers and our Public Key.
Anyway the solution, as far as it is, is to implement the In-App Billing v3 Api (which is magnitudes nicer than the old version BTW) and it starting working again.
So, not really a definitive answer, but a fix as it were.

Categories

Resources