Best practices

This section describes some techniques that can help make the Shopping Content API libraries easier to use.

In addition, the samples hosted on GitHub have new functionality that demonstrates the Orders resource. These samples are prefixed with "Orders".

Service account key

While setting up your Google Service Account, you created a key file that you downloaded as a JSON file. Do not lose this file. If you lose it, you cannot download it again.

Some of the Google library APIs use the key file directly, and therefore no modifications are necessary.

However, if you plan to make REST calls to the Orders resource through a web service, you must edit the value of the private_key field in the key file:

  1. Remove all the "\n" characters in the private_key field.
  2. Remove all "=" (equals sign) or "\u003d" (encoded equals sign) values at the end of the private_key field, if present.

The following example highlights the "=" and "\n" to remove:

"private_key": "–––––BEGIN PRIVATE KEY––––– ... \n08875j5642fff...==\n–––––END PRIVATE KEY–––––\n"

.NET

This section provides tips for developers that are implementing the Orders resource in .NET.

Downloads

Download .NET resources from the following locations:

OAuth

Most of the Google documentation and samples show using .NET with an OAuth 2.0 client ID and client key. However, this client ID cannot be added to Merchant Center as an authorized Shopping Action manager and will be unable to download order information.

Instead, a Google Service Account should be used which includes an email address that can be added to Merchant Center and given Buy on Google permissions. In order to use the Google Service account, the JSON file containing the Google Service Accounts credentials needs to be passed by your code to Google for authentication.

The sample code's Authenticator.cs file supports passing the Google Service account JSON file for authentication.

Sandbox vs. production mode

Different endpoints need to be called in order to reach the sandbox and production instances.

To call these different endpoints, you need to import two different libraries using nuget:

You can have both installed simultaneously, as the two have different package hierarchies.

Unfortunately, the only way to toggle between them is to change your import statements.

Python

This section provides tips for developers that are implementing the Orders resource in Python.

Downloads

Download Python resources from the following locations:

OAuth

The Python library requires the service account's private key to contain the line breaks ("\n") that are present in the JSON file. If you are storing the credentials in a separate file, be sure to include the key's line breaks in the new file.

Java

This section provides tips for developers that are implementing the Orders resource in Java.

Downloads

Download Java resources from the following locations:

Tutorial: Compiling and executing GitHub Java examples

This section walks you through compiling and executing the Orders resource Java examples in the GitHub repo:

  1. Pre-requisites
  2. Step 1: Install and configure tools
  3. Step 2: Load Merchant Info and Google oauth2.Credentials
  4. Step 3: Compile and package the project using Maven
  5. Step 4: Execute the OrdersWorkflow CLI

Pre-requisites

The following are required to do this tutorial:

  1. Link the Google Service Account: Follow Get started with the Orders resource to create a Google Service Account (GSA) and link it to your Merchant Center account.
  2. Download key: Credentials are automatically downloaded as a JSON file after you create a GSA.
  3. Install the tools: Install javac, Maven, and git for your platform.
  4. Download the samples: Download the Google samples from the GitHub repo.

    You can download the archive or clone the repository. Note that it is better to clone the repo, so that any changes you make are easily viewed using git diff. For example:

    $ git clone https://github.com/googleads/googleads-shopping-samples.git

    The clone command pulls in all the samples, but you should focus on the Java orders' sample sources for this exercise in the following directory:

    googleads-shopping-samples/java/src/shopping/v2/samples/orders/

Step 1: Install and configure tools

Use the information in this section if you do not already have a Java compiler and Maven installed on your developer box.

Install javac, Maven, and git as per your platform. If you are using a Debian-based Linux distribution, you can use apt‑get.

For Mac OS, you can enter javac or git in the terminal, and Mac OS will suggest where to get them from. You can get Maven from the Apache Maven site.

To see if you have Maven installed already, enter the following command:

$ mvn --version

The default Maven local repository is under your home directory: ${user.home}/.m2/repository. To change this to a different directory, edit the ${MAVEN_HOME}/conf/settings.html file and change <localRepository> to point to a new location.

Step 2: Load Merchant Info and Google oauth2.Credentials

  1. Copy the merchant-info.json file to your home directory. This file is located at the top of the GitHub repo at googleads-shopping-samples/. For example:

    $ mkdir -p  ~/shopping-samples/content
    $ cp ../merchant-info.json ~/shopping-samples/content/
  2. Edit your local copy of the merchant-info.json file:

    1. Replace the value of merchantId with your merchant ID.
    2. Set the email address to an empty string. If the email address is set, then the GSA's JSON key file will not be used.

    The file should look like the following:

    {
      "merchantId": your_merchant_ID,
      "accountSampleUser": "",
      "accountSampleAdWordsCID": 0,
      "emailAddress": ""
    }
  3. Copy the GSA's key file to the location expected by the sample classes. You downloaded this JSON file as part of Get started with the Orders resource.

    For example:

    $ cp your_gsa_file.json ~/shopping-samples/content/service-account.json

Step 3: Compile and package the project using Maven

Compile the project using Maven; for example:

$ cd googleads-shopping-samples/java
$ mvn compile
$ mvn package

This will also download the Google APIs, as defined in the project's dependencies.

If there are any errors during the dependency downloads, try again; some Maven repositories may time out or have other errors.

To clean up the compiled sources, use mvn clean.

When compiled successfully, Maven creates a JAR file in the top-level project directory; for example:

googleads-shopping-samples/java/target/OrdersWorkflow-v2-rev77-1.21.0.jar

Step 4: Execute the OrdersWorkflow CLI

Execute the OrdersWorkflow CLI; for example:

$ cd googleads-shopping-samples/java
$ mvn exec:java -Dexec.mainClass="shopping.v2.samples.orders.OrdersWorkflow"

If the execution of the OrdersWorkflow CLI fails on "Listing unacknowledged orders for merchant", edit the source file (java/src/main/java/shopping/content/v2.1/samples/orders/OrdersWorkflow.java):

  1. Comment out the section that lists unacknowledged orders. The following example shows the section to comment out:

  2. Limit the number of results from the list method by specifying a recent value for the placedDateStart parameter.

    You can use the following diff to patch the OrdersWorkflow.java file:

    --- a/java/src/shopping/v2/samples/orders/OrdersWorkflow.java
    +++ b/java/src/shopping/v2/samples/orders/OrdersWorkflow.java
    @@ -17,6 +17,9 @@ import java.io.IOException;
     import java.util.Random;
     import shopping.v2.samples.BaseSample;
    
    +import java.util.Date;
    +import java.text.SimpleDateFormat;
    +import java.util.Calendar;
     /**
      * Sample that runs through an entire test order workflow. We run this sample on the sandbox
      * API endpoint, so that we have access to test order creation and don't accidentally mutate real
    @@ -44,9 +47,14 @@ public class OrdersWorkflow extends BaseSample {
         System.out.println();
    
         // List the unacknowledged orders.
    +    String orderDateStart = getOrderDateStart(); // default: Limit the list call to Yesterday's orders
    +                                                 // modify this function to increase/decrease the limit.
    +
         System.out.printf("Listing unacknowledged orders for merchant %d:%n", config.getMerchantId());
         ShoppingContent.Orders.List listCall = sandbox.orders().list(config.getMerchantId())
    -        .setAcknowledged(false);
    +        .setAcknowledged(false)
    +       .setPlacedDateStart(orderDateStart)
    +       ;
         do {
           OrdersListResponse page = listCall.execute();
           for (Order product : page.getResources()) {
    @@ -233,6 +241,14 @@ public class OrdersWorkflow extends BaseSample {
         return ret;
       }
    
    +  private String getOrderDateStart() {
    +    Calendar cal = Calendar.getInstance();
    +    cal.add(Calendar.DATE, -1); // Yesterday. Change this to -7 for a weeks worth of data.
    +    String ret  = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
    +    System.out.printf("Listing placed orders from date: \"%s\"... \n", ret);
    +    return ret;
    +  }
    +
       public static void main(String[] args) throws IOException {
         new OrdersWorkflow().execute();
       }
  3. After you have saved your changes to the OrdersWorkflow.java file, recompile and execute the CLI:

    $ cd googleads-shopping-samples/java
      $ mvn compile
      $ mvn package
      $ mvn exec:java -Dexec.mainClass="shopping.v2.samples.orders.OrdersWorkflow"

The following example shows the output of a successful execution:

[INFO] ------------------------------------------------------------------------
[INFO] [exec:java {execution: default-cli}]
Loaded the Application Default Credentials.
Creating test order... done.
Order "TEST-3907-38-6950" created.

Acknowledging order "TEST-3907-38-6950"... done with status "executed".

Updating merchant order ID to "test order -663546118768520962"... done with status "executed".

Retrieving order "TEST-3907-38-6950"... done.

Order "TEST-3907-38-6950":
- Status: inProgress
...
--

   1 of item "S3LIDLO54ICZEYE"

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 40 seconds
[INFO] Finished at: Tue Jan 03 19:13:32 EST 2017
[INFO] Final Memory: 21M/181M
[INFO] ------------------------------------------------------------------------

Getting an access token

To access Google's APIs with a RESTful service request, your application must identify itself to Google with an OAuth 2.0 access token.

You get an access token by sending a JSON Web Token (JWT) to Google's authentication service, which returns an access token that is good for up to 60 minutes. You must periodically call the authentication service and exchange your JWT for a valid access token.

After you get an access token, you pass it in your RESTful service requests to the Orders resource.

To get and use an access token:

  1. Configure your Google Console project to get your GSA's JSON key file, as described in Get started with the Orders resource.
  2. Extract the client_email and secret_key values from the key file. You will use these values to create a JSON Web Token (JWT).

    Remove the newlines, equals signs, and other parts of the string, as described in Service account key.

  3. Create a JWT. You will pass the JWT as part of your OAuth call to get the access token in the next step.

    A JWT is made up of the following parts:

    {header}.{claim_set}.{signed_signature}

    All parts of the JWT are base-64 URL encoded.

    The header defines the algorithm and token type. Set it to the following:

    {
      "alg":"RS256",
      "typ":"JWT"
    }

    The claim_set contains details about the authentication request. Use the following format when defining your claim set:

    {
      "iss":"SERVICE_ACCT_CLIENT_EMAIL_ADDRESS",
      "scope":"https://www.googleapis.com/auth/content",
      "aud":"https://accounts.google.com/o/oauth2/token",
      "exp":NOW_+1HR_TIME_IN_SEC_FROM_01-01-1970,
      "iat":NOW_TIME_IN_SEC_FROM_01-01-1970
    }

    Where:

    • iss: The service account email address that you created as part of Get started with the Orders resource. This is the email address that ends with "@developer.gserviceaccount.com".
    • scope: Specifies which APIs are being authorized. For the Orders resource, use "https://www.googleapis.com/auth/content". You can authorize multiple APIs by separating them with spaces.
    • exp: The JWT's expiration time, in seconds, from Jan 1, 1970. The maximum lifetime for a JWT is 1 hour from NOW.
    • iat: The current time, in seconds, from Jan 1, 1970.

    The signed_signature is an RSA-encrypted value of your private key (the value of secret_key from Step 2). To sign your key, use SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) on a UTF-8 representation of the input. The output of the signing process will be a byte array.

    Note that Google's authorization only supports the SHA-256 hashing algorithm to encrypt your signature (which is indicated by the value of "RSA256" for alg in the header).

    The combined header, claim set, and signature might appear like the following:

    ewogICJhbGciOiJSUzI1NiIsCiAgInR5cCI6IkpXVCIKfS4KewogICJpc3MiOiJleGF
    tcGxlQGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwKICAic2NvcGUiOiJodHRwczovL3d3dy5nb29nbGV
    hcGlzLmNvbS9hdXRoL2NvbnRlbnQiLAogICJhdWQiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9vYXV
    0aDIvdG9rZW4iLAogICJleHAiOjE1MDg4NTc3OTYsCiAgImlhdCI6MTUwODg2MTM5Ngp9LgpaR1poYTJ4cVpIVTR
    PVFExTkd3dWFXbzFPVEJ6WkhWblptRnBielE1TUhWVFZFVmtabXN1YkdwRVJreExSRFF5VTFORVJrZExURXBUCkN
    tbHFOVGt3YzJSMVoyWmhhVzgwT1RCMVUxUkZaR1pyUldSbWF5NXNha1JHVEV0RU5ESlRVMFJHUjB0TVNsTlRSREl
    5TXpNd05FUmgKTUFwa1ptRnJiR3BrZFRnNU5EVTBiQzVwYWpVNU1ITmtkV2RtWVdsdk5Ea3dkVk5VUldSbWF5NXN
    ha1JHVEZOR09UQTBNZz09

    You will use this value as the JWT_encoded_message in the next step.

  4. Make an OAuth call to https://accounts.google.com/o/oauth2/v2/auth to request an access token. Include the JWT as the value of assertion in the body of the request, as the following example shows:

    POST https://accounts.google.com/o/oauth2/v2/auth
    Content-type: application/x-www-form-urlencoded
    Payload (Body):
      "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer"
      "assertion": "JWT_encoded_message"
    

    You can get the latest version of the OAuth endpoint and other details from the Discovery Document.

  5. Extract the value of the access token from the response. You can now use this token for up to 60 minutes in your requests.

  6. Send a RESTful request to the Orders resource with the access token. You do this by appending the token as the access_token query string parameter, as the following example shows:

    orders_api_endpoint?access_token=auth_token

    For example:

    https://www.googleapis.com/content/v2.1sandbox/42/testordertemplates/template1?access_token=dkljsdf3jdfsk42

    Note that the access token is good for 60 minutes. After that time, you will need to issue a new OAuth call to get a new access token (repeat steps 3 through 5). In step 3, be sure to update the current time and expiration time in the claim set, which will change the JWT that you send.

Google's OAuth 2.0 implementation conforms to the OpenID Connect specification, and is OpenID Certified. For additional details and examples, see OpenID Connect.