Google My Business Requested entity was not found - google-my-business-api

I'm trying to implement an integration between a ERP system and Google My Business to keep store data in sync.
I have a project in the developer console. I have gained access to the GMB API and is approved by Google to use this API.
I'm using a serviceaccount and have followed the instructions from various guides.
But now I'm stuck.
I'm using the google GMB c# library to connect to GMB. I have a valid .12 file for my service account.
string MybusinessServiceScope = "https://www.googleapis.com/auth/plus.business.manage";
String serviceAccountEmail = "myserviceaccount#myapplication-1349.iam.gserviceaccount.com";
var certificate = new X509Certificate2(_serviceP12File, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { MybusinessServiceScope },
}.FromCertificate(certificate));
return new MybusinessService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "myapplication-1349",
});
When I try to List, Patch or Create locations I keep getting the same response:
Requested entity was not found. [404]
Errors [
Message[Requested entity was not found.] Location[ - ] Reason[notFound] Domain[global]
]
Any help is appreciated

I was unable to make this work with a service account. After talking to google support on the matter I change to use the OAuth application flow instead.
This works.
My chat with google: https://www.en.advertisercommunity.com/t5/Google-My-Business-API/Unable-to-PATCH-location-with-v3/td-p/579536#
Hope this can help others

this error occurs when the user doesn't have access to the provided location. (invalid access token or user access has been revoked etc)

Related

Error when querying Microsoft Graph API Shifts: "MS-APP-ACTS-AS header needs to be set for application context requests"

We are trying to query shifts in the Microsoft Graph API using a C# app, now that StaffHub got deprecated , in the past we were getting an Unknown Error which looked like a permissions issue.
In the docs I noticed permissions for Schedule.ReadAll and Schedule.ReadWriteAll so I added them to the application permissions in our App Registration in Azure.
Now when we send the request to https://graph.microsoft.com/beta/teams/{teamid}/schedule we get this error:
Microsoft.Graph.ServiceException: 'Code: Forbidden Message: {"error":{"code":"Forbidden","message":"MS-APP-ACTS-AS header needs to be set for application context requests.","details":[],"innererror":{"code":"MissingUserIdHeaderInAppContext"}}}
The documentation says the Schedule permissions are in private preview, are these required for querying a schedule & shifts, and if so, is it possible to request access to the private preview?
I'm in the same situation. It's possible to request private preview access (we have), but I'm guessing that it's primarily granted to Microsoft partners or at least have a connection at Microsoft.
The workaround for me has been getting access on behalf of a user. It does however require the user to enter username and password in order to get an access token, so it might not be a perfect solution for you. But it works. You need to add (and, I believe, grant admin consent for) delegated permissions for this to work, either Group.Read.All or Group.ReadWrite.All.
Edit:
I've got it working now. We have private preview access, so I'm not sure this will help you unless you do too, but as I understand it will be available eventually. Given your question, I presume you already have an access token.
Add MS-APP-ACT-AS as a header with the user ID of the user you want the Graph client to act as.
If you're using the Graph SDK for .NET Core you can just add a header to the authentication provider:
public IAuthenticationProvider GetAuthenticationProviderForActingAsUser(string userId, string accessToken)
{
return new DelegateAuthenticationProvider(
requestMessage =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
// Get event times in the current time zone.
requestMessage.Headers.Add("Prefer", "outlook.timezone=\"" + TimeZoneInfo.Local.Id + "\"");
requestMessage.Headers.Add("MS-APP-ACTS-AS", userId);
return Task.CompletedTask;
});
}
Then you call the graph service client:
var authenticationProvider = GetAuthenticationProviderForActingAsUser(userId, accessToken);
var graphClient = new GraphServiceClient(authenticationProvider);
You should then be able to fetch the shifts:
var shifts = await graphClient.Teams[teamId].Schedule.Shifts
.Request()
.AddAsync(shift);

Using new microsoft-graph-auth library java sdk gives unauthorized error

Permissions in azure portal I am trying to use microsoft graph auth library preview. Microsoft-graph-auth-sdk-java I am able to initialize the graphClient but unable to get data.I am getting unauthorized 401.
"code": "InvalidAuthenticationToken",
"message": "CompactToken parsing failed with error code: 80049217",
List<String> scopes = new ArrayList<String>();
scopes.add("User.Read.All");
ClientCredentialProvider authProvider = new ClientCredentialProvider(app-Id,
scopes_list,
client-Secret,
tenantId, NationalCloud.Global);
IgraphClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).logger(logger)
.buildClient();
IUserCollectionPage users = graphClient.users()
.buildRequest()
.get();
List<User> usersList = users.getCurrentPage();
for(User user : usersList) {
System.out.println(user.displayName);
}
Permissions picture Link
Permissions and code are fine. The issue must be with the library since it is in snapshot. But I guess they recently made some changes which could have fixed the issue you are facing. Try re-building the jar from the project.
For making app-only calls using client credentials you will need to pass the scope "https://graph.microsoft.com/.default" and then in the app registration portal grant admin consent for User.Read.All.

Error 400: invalid_scope "https://www.googleapis.com/auth/chat.bot"

The documentation for the new google hangouts chat says that you need to authorize the scope https://www.googleapis.com/auth/chat.bot to do pretty much anything.
Here's the error:
While generating an authentication URL using their OAuth2 client I get the message that the scope is invalid. I don't have that problem if I use https://www.googleapis.com/auth/chat or some other scope like the one for google plus.
When I try to google things on in the API Explorer no combination of the URL or parts of the URL work either.
Here is my code to fetch the URL, seems to work just fine for everything else:
var {google} = require('googleapis');
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2(
"clientid-idididid.apps.googleusercontent.com",
"_secretsuff",
"http://localhost:3000/auth/google/callback"
);
var scopes = [
"https://www.googleapis.com/auth/chat", //Works
"https://www.googleapis.com/auth/chat.bot" // Does not work
];
var url = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes,
});
console.log(url);
In case others are running across this problem I think I've figured this out. Google doesn't seem need this auth scope enabled by a domain user because it's already authorised on the domain when your testing your bot. The "authorisation" of these scopes are dictated by users in a domain adding/removing bots from spaces.
I'll go into a bit of detail if you're confused.
When you create a bot in the console for an organisation https://console.cloud.google.com/apis/api/chat.googleapis.com/ your bot is added to the domain and can be added to spaces by users. If then go over to to the credentials and create a service account you can use that json file credentials to access the API as your bot. The code below gets a list of the people in a space.
var { google } = require('googleapis');
var chat = google.chat("v1");
var key = require('./google_service-account-credentials.json');
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
['https://www.googleapis.com/auth/chat.bot'], // an array of auth scopes
null
);
jwtClient.authorize(function (err, tokens) {
chat.spaces.members.list({
auth: jwtClient,
parent: "spaces/AAAAD4xtKcE"
}, function (err, resp) {
console.log(resp.data);
});
});
If you try to get a list of members on other spaces (and other domains) the bot will fail with the exact same error message:
"Bot is not a member of the space."
I assume if you list your bot on the marketplace and it gets added to different domains and spaces google's API makes sure that your bot can do what it's trying to do on a space by space basis. It would be annoying have to setup some authentication flow after a bot has already been added for it to do its job. This is also probably why the current REST api doesn't let you list spaces under domains, it's not the paradigm this API works under.
It may have to do with one of the following:
The scope is created for service accounts. Make sure you are accessing the REST API with a service account.
Make sure that the bot is added to the room or space and has access to what you want it do.
Make sure the Service account is part of the bot project that you are using for the bot.

Error when trying to get Purchases from Android Publisher Service in a .Net Web API

I have a web Api, which needs to validate purchases from Play Store. According to what I read in the google api documentation, I need to have a service account, and use its credentials to be authenticated, to be able to do what i want.
I have the following code:
String serviceAccountEmail = "MYSERVICEACCOUNTEMAIL#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"C:\privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { "https://www.googleapis.com/auth/androidpublisher" }
}.FromCertificate(certificate));
// Create the service.
var service = new AndroidPublisherService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential
});
var data = service.Purchases.Get("MYPACKAGE", "MYPRODUCT",
"MYTOKEN")
.Execute();
It throws the following exception
Google.Apis.Requests.RequestError
Invalid Value [400]
Errors [
Message[Invalid Value] Location[ - ] Reason[invalid] Domain[global]
]
I have NO IDEA of what can be causing it. I searched a lot, but I didn't find something really helpful. Any kind help will be really appreciated.
I know this question is "a little" old, but I still want to try to answer for clarification.
var data = service.Purchases.Get("MYPACKAGE", "MYPRODUCT",
"MYTOKEN")
.Execute();
My guess would be that this part is not entirely right. The Purchases class does not have a Get method. Before that you have to specify either (in your case):
service.Purchases.Products.Get(...) -> for consumable products
service.Purchases.Subscriptions.Get(...) -> for subscriptions
This answer assumes you are using V2. Hope it helps anyone who is stuck.

OAuth 2.0 with Google Analytics API v3

I used to be able to query the Google Analytics API with my account's login & password.
Google is now using OAuth for authentication which is great...
The only issue is that I only need ONE access token.
I don't wanna allow other users to fetch THEIR analytics data.
I just wanna be able to fetch MY data.
Is there a way I can generate an access token only for my app or my analytics account?
I know such solutions exists... For instance, Twitter provides what they call a "single-user oauth" for apps that don't require a specific user to sign in.
One again, all I'm trying to accomplish here is to fetch MY OWN analytics data via the API.
Is there a way to properly do that?
I'm adding a PHP answer - you may be able to adjust or convert it to garb / ruby code.
You should be able to use Analytics with service accounts now. You will indeed have to use a private key instead of an access token.
Create an app in the API Console
Basically, you go to the Google API Console and create an App.
Enable Google Analytics in the services tab.
In the API Access tab, create a new OAuth ID (Create another client ID... button), select service account and download your private key (Generate new key... link). You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email address (#developer.gserviceaccount.com) and add a new user with this email address to your Google Analytics profile. If you do not do this, you'll get some nice errors
Code
Download the latest Google PHP Client off SVN (from the command line svn checkout http://google-api-php-client.googlecode.com/svn/trunk/ google-api-php-client-read-only).
You can now access the Analytics API in code:
require_once 'Google_Client.php';
require_once 'contrib/Google_AnalyticsService.php';
$keyfile = 'dsdfdss0sdfsdsdfsdf44923dfs9023-privatekey.p12';
// Initialise the Google Client object
$client = new Google_Client();
$client->setApplicationName('Your product name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'11122233344#developer.gserviceaccount.com',
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('11122233344.apps.googleusercontent.com');
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
// We have finished setting up the connection,
// now get some data and output the number of visits this week.
// Your analytics profile id. (Admin -> Profile Settings -> Profile ID)
$analytics_id = 'ga:1234';
$lastWeek = date('Y-m-d', strtotime('-1 week'));
$today = date('Y-m-d');
try {
$results = $analytics->data_ga->get($analytics_id,
$lastWeek,
$today,'ga:visits');
echo '<b>Number of visits this week:</b> ';
echo $results['totalsForAllResults']['ga:visits'];
} catch(Exception $e) {
echo 'There was an error : - ' . $e->getMessage();
}
Terry Seidler answered this nicely for php. I want to add a java code example.
Api console setup
Start by doing the required steps in the google api console as Terry explained:
Basically, you go to the Google API Console and create an App. Enable
Google Analytics in the services tab. In the API Access tab, create a
new OAuth ID (Create another client ID... button), select service
account and download your private key (Generate new key... link).
You'll have to upload the key to your web server later.
On the API Access page, in the Service account section, copy the email
address (#developer.gserviceaccount.com) and add a new user with this
email address to your Google Analytics profile. If you do not do this,
you'll get some nice errors
Get the necessary libraries
Download the google analytics java client from:
https://developers.google.com/api-client-library/java/apis/analytics/v3
Or add the following maven dependencies:
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-analytics</artifactId>
<version>v3-rev94-1.18.0-rc</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson</artifactId>
<version>1.18.0-rc</version>
</dependency>
Now for the code:
public class HellowAnalyticsV3Api {
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public void analyticsExample() {
// This is the .p12 file you got from the google api console by clicking generate new key
File analyticsKeyFile = new File(<p12FilePath>);
// This is the service account email address that you can find in the api console
String apiEmail = <something#developer.gserviceaccount.com>;
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(apiEmail)
.setServiceAccountScopes(Arrays.asList(AnalyticsScopes.ANALYTICS_READONLY))
.setServiceAccountPrivateKeyFromP12File(analyticsPrivateKeyFile).build();
Analytics analyticsService = new Analytics.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(<your application name>)
.build();
String startDate = "2014-01-03";
String endDate = "2014-03-03";
String mertrics = "ga:sessions,ga:timeOnPage";
// Use the analytics object build a query
Get get = analyticsService.data().ga().get(tableId, startDate, endDate, mertrics);
get.setDimensions("ga:city");
get.setFilters("ga:country==Canada");
get.setSort("-ga:sessions");
// Run the query
GaData data = get.execute();
// Do something with the data
if (data.getRows() != null) {
for (List<String> row : data.getRows()) {
System.out.println(row);
}
}
}
You can use a refresh token. Store the refresh token in a db or secure config file, then use it to show the stats.
Google API Offline Access Using OAuth 2.0 Refresh Token will give you an idea of how to capture then store your refresh token.
See also Using OAuth 2.0 for Web Server Applications - Offline Access
Hello I found a solution, it works for me
you have to change this one
immediate: true
to
immediate: false
and it looks like
function checkAuth() {
gapi.auth.authorize({
client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
}
Google has the 'Service Account' (Calls Google APIs on behalf of your application instead of an end-user), but the way it works is a bit different as it won't use access tokens but a private key instead.
You can find more details at https://developers.google.com/accounts/docs/OAuth2ServiceAccount

Resources