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:
- Remove all the "\n" characters in the
private_key
field. - 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:
- Shopping Content API for .NET library
- Shopping Content API for .NET documentation
- GitHub Code Samples
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
:
- Sandbox (dev/testing): Google.Apis.ShoppingContent.v2sandbox
- Production: Google.Apis.ShoppingContent.v2
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:
- Shopping Content API for Python library
- Shopping Content API for Python documentation
- GitHub Code Samples
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:
- Shopping Content API for Java library
- Shopping Content API for Java documentation
- GitHub Code Samples (see tutorial)
Tutorial: Compiling and executing GitHub Java examples
This section walks you through compiling and executing the Orders resource Java examples in the GitHub repo:
- Pre-requisites
- Step 1: Install and configure tools
- Step 2: Load Merchant Info and Google oauth2.Credentials
- Step 3: Compile and package the project using Maven
- Step 4: Execute the OrdersWorkflow CLI
Pre-requisites
The following are required to do this tutorial:
- 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.
- Download key: Credentials are automatically downloaded as a JSON file after you create a GSA.
- Install the tools: Install javac, Maven, and git for your platform.
- 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
- 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/
- Edit your local copy of the merchant-info.json file:
- Replace the value of
merchantId
with your merchant ID. - 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": "" }
- Replace the value of
- 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):
- Comment out the section that lists unacknowledged orders. The following example shows the
section to comment out:
- Limit the number of results from the
list
method by specifying a recent value for theplacedDateStart
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(); }
- 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:
- Configure your Google Console project to get your GSA's JSON key file, as described in Get started with the Orders resource.
- Extract the
client_email
andsecret_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.
- 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.
- 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.
- Extract the value of the access token from the response. You can now use this token for up to 60 minutes in your requests.
- 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.