Question

I am developing a piece of code which can create and download reports using Google DFA Reporting API's.

I am able to do the same using Client Id and Client Secret, which is generated using Install-App (native Application) account, but with this type of account, it always open a browser for first time and then only it authenticates the future request.

On further reading, I came across the service account. I then created a new Service Account and downloaded p12 key. I am now able to build credential object with the help of p12 and Email account (*******ccms@developer.gserviceaccount.com). I can confirm this as I am seeing access token in a credential object after calling credentials.refreshToken().

I then create an object of DFA Reporting using the above credential and trying to fetch profiles list, but I am getting the below error:

java.lang.IllegalArgumentException: No profiles found
    at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:92)
    at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:49)
    at com.google.api.services.samples.dfareporting.cmdline.GetAllUserProfiles.list(GetAllUserProfiles.java:52)
    at com.google.api.services.samples.dfareporting.cmdline.DfaReportingSample.main(DfaReportingSample.java:171)

Please see my code below and let me know where I am going wrong:

private static Credential authorize() throws Exception {
    // load client secrets

    List<String> SCOPES = ImmutableList
            .of("https://www.googleapis.com/auth/dfareporting");
    String SERVICE_ACCOUNT_EMAIL = "*************************@developer.gserviceaccount.com";

    String Path = DfaReportingSample.class.getResource(
            "/TestDFA-5d985ff38b34.p12").getPath();
    java.io.File file = new java.io.File(Path);

    HttpTransport httpTransport = new NetHttpTransport();
    JacksonFactory jsonFactory = new JacksonFactory();

    Credential credentials =  new GoogleCredential.Builder()
            .setTransport(httpTransport)
            .setJsonFactory(jsonFactory)
            .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
            .setServiceAccountScopes(SCOPES)
            .setServiceAccountPrivateKeyFromP12File(file).build();

    credentials.refreshToken();

    return credentials;
}

private static Dfareporting initializeDfareporting() throws Exception {
    Credential credential = authorize();

    // Create DFA Reporting client.
    return new Dfareporting(httpTransport, JSON_FACTORY, credential);
}


public static void main(String[] args) {

    try {
        httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        Dfareporting reporting = initializeDfareporting();

        UserProfiles up = reporting.userProfiles();
        List l = up.list();
        UserProfileList profiles = l.execute();
        // {"etag":"\"bM2H6qONz9kIDiByk_eTdC6Ehcc/vyGp6PvFo4RvsFtPoIWeCReyIC8\"","items":[],"kind":"dfareporting#userProfileList"}
        Preconditions.checkArgument(
            profiles.getItems() != null && !profiles.getItems().isEmpty(), "No profiles found");
        for (UserProfile userProfile : profiles.getItems()) {
          System.out.printf("User profile with ID \"%s\" and name \"%s\" was found.%n",
              userProfile.getProfileId(), userProfile.getUserName());
        }
....................................

PS: I am able to fetch all the profiles, if I use access token which is generated using client id and client secret provided by native application (installed apps) account.

Thanks, Hussain Bohra

Was it helpful?

Solution

After trying a lot with service account (& p12 key), we couldn't make it work with the Google DFA Reporting. Hence we are now using the following class for authentication:

com.google.api.ads.common.lib.auth.OfflineCredentials

input = new FileInputStream(Utils.getProperty(Constants.HOME_PATH)
        + Utils.getProperty(Constants.CLIENT_SECRETS_DIRECTORY)
        + Constants.PATH_SEPARATOR + userPropertyFile);
userProperty.load(input);

credential = new OfflineCredentials.Builder()
        .forApi(OfflineCredentials.Api.DFA)
        .withHttpTransport(
                GoogleNetHttpTransport.newTrustedTransport())
        .withClientSecrets(userProperty.getProperty("client_id"),
                userProperty.getProperty("client_secret"))
        .withRefreshToken(userProperty.getProperty("refresh_token"))
        .build().generateCredential();

The refresh token used in the above code is generated manually (one time process) for every account. Using this object of credential, we are now able to perform all the following activities in a DFA reporting: - List Profiles - Validate and Create Report - Download Report Data.

Code to get refresh token (involves a manual step of clicking Accept in a browser)

java.io.File DATA_STORE_DIR = new java.io.File(
        "d:/dfa-reporting/.store/dfareporting_sample");
FileDataStoreFactory dataStoreFactory;
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);

GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
        JSON_FACTORY,
        new InputStreamReader(DfaReportingSample.class
                .getResourceAsStream("/client_secret_galtieri.json")));
// set up authorization code flow
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
        httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
        .setDataStoreFactory(dataStoreFactory).build();
// authorize
String refreshToken = new AuthorizationCodeInstalledApp(flow,
        new PromptReceiver()).authorize("hbohra").getRefreshToken();

Thanks, Hussain Bohra

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top