Integrating your app's backend

This section describes the steps to integrate your app's backend with Google Cloud Marketplace. With this integration, you can manage users' accounts and entitlements, which indicate that users have bought your product from Google Cloud Marketplace. If you chose a usage-based pricing model, you also integrate your backend to report usage to Google.

For an example of integrating a basic app with Google Cloud Marketplace and a walkthrough of the sample code, see the codelab to integrate a managed service.

For the sample code used in the codelab, see the GitHub repository.

Before you begin

  • Set up access to the Cloud Commerce Partner Procurement API, as described in Integrating your app: setting up.
  • If you chose a usage-based pricing scheme, verify that your Partner Engineer has created a service that you can report usage against. This service displays in the Service domain field of the Billing Integration section of Producer Portal.

Creating a service account

To integrate your product with Google Cloud, you must create a service account in the project that you are using for your product. Your app uses this service account to interact with the Google Cloud Marketplace Partner APIs and get information about users' purchases.

We recommend that you use Producer Portal to create and link your service accounts.

If you are using Partner Portal, your Partner Engineer grants the Pub/Sub Subscriber role to this service account. For detailed steps to create a service account, see Creating and managing service accounts.

Using Producer Portal to integrate your app's backend

To access all of the information you need to integrate your app's backend with Google Cloud Marketplace from one location, such as your service accounts and plan level identifiers, you can use the BILLING INTEGRATION section of Producer Portal.

The direct link to Producer Portal is:

https://console.cloud.google.com/producer-portal?project=YOUR_PROJECT_ID

To access the BILLING INTEGRATION section:

  1. In the list of products, click the name of your product.

  2. On the Overview page of your product, go to the Technical Integration section and click on BILLING INTEGRATION.

Creating and linking service accounts in Producer Portal

You can use the BILLING INTEGRATION section of Producer Portal to create and link the service accounts that you use to interact with the Partner APIs and to get information about users' purchases.

The direct link to Producer Portal is:

https://console.cloud.google.com/producer-portal?project=YOUR_PROJECT_ID

In the following steps, you can use existing service accounts, or create new service accounts. If you create a new service account, specify the service account's name in the Service account name field and the service account's ID in the Service account ID field, and then click CREATE AND LINK.

To link your service accounts:

  1. In the list of products, click the name of your product.

  2. On the Overview page of your product, go to the Technical Integration section and click on BILLING INTEGRATION.

  3. To integrate with the Partner Procurement API, under Link a service account to call Procurement API, click ADD SERVICE ACCOUNT. You can enter an existing service account into the field, or create a new service account.

  4. To integrate with Pub/Sub, under Link a service account to subscribe to Pub/Sub topic, click ADD SERVICE ACCOUNT. You can enter an existing service account into the field, or create a new service account.

  5. To integrate with the Service Control API, under Add roles/servicemanagement.serviceController to a service account, click ADD SERVICE ACCOUNT. You can enter an existing service account into the field, or create a new service account.

User account tasks

At a high level, your app must handle the following scenario:

  1. A user makes a request or change in Google Cloud Marketplace, such as signing up for your product.

  2. Google Cloud Marketplace sends your app a notification through Pub/Sub, containing information about the request in the eventType field. For example, if a user changes their entitlement, the eventType is ENTITLEMENT_PLAN_CHANGED.

    See the full list of possible eventTypes.

  3. To approve the request, your app sends an HTTP POST request to the Partner Procurement API.

The following sections describe the types of requests that users can make, and what your app must do to handle the requests.

For the API calls described in this section, use this endpoint:

https://cloudcommerceprocurement.googleapis.com/

Creating an account for a new user

When a user first purchases your product, Google Cloud Marketplace creates an account resource that tracks the user's relationship with you. When the account resource is created, you get notified through the Pub/Sub topic that was created for you. The Pub/Sub message is in the following format:

{
  "eventId": "...",
  "providerId": "YOUR_PARTNER_ID",
  "account": {
    "id": "USER_ACCOUNT_ID",
    "updateTime": "..."
  }
}

where USER_ACCOUNT_ID is the account ID created by Google Cloud Marketplace and YOUR_PARTNER_ID is an ID assigned to you when your Partner Engineer enables access to the Partner Procurement API.

Simultaneously, the user is directed to your sign-up page, where they create an account in your system. For information on creating the sign-up page, see Integrating your app's frontend.

After the user has successfully signed up, your app must call the Partner Procurement API and indicate that the account has been approved. Accounts are created in the ACCOUNT_ACTIVE state, but they have a PENDING entry in the approvals field called signup, which indicates that the user has not yet signed up. To approve the account after the user has signed up, use the following HTTP POST request:

POST v1/providers/YOUR_PARTNER_ID/accounts/USER_ACCOUNT_ID:approve {'approvalName': 'signup'}

To check the status of a linked account, use the following HTTP GET request:

GET v1/providers/YOUR_PARTNER_ID/accounts/USER_ACCOUNT_ID

The response is in the following format:

{
  "name": "providers/YOUR_PARTNER_ID/accounts/USER_ACCOUNT_ID",
  "provider": "acme-services",
  "state": "ACCOUNT_ACTIVE",
  "approvals": [{
    "name": "signup",
    "state": "APPROVED",
    "updateTime": "...",
  }],
  "updateTime": "...",
  "createTime": "..."
}

For a list of possible account states, see the providers.accounts API reference.

Managing entitlements

When customers choose a pricing plan for your software, Google creates an entitlement, which indicates that the customer has bought your product from Google Cloud Marketplace. This section reviews how to create and manage entitlements for your customers using the Partner Procurement API.

For more details on managing entitlements, see the reference documentation.

Approving or rejecting an entitlement

When a customer chooses a pricing plan, Google Cloud Marketplace creates an entitlement and sends the following Pub/Sub message to your app:

{
  "eventId": "...",
  "eventType": "ENTITLEMENT_CREATION_REQUESTED",
  "providerId": "YOUR_PARTNER_ID",
  "entitlement": {
    "id": "ENTITLEMENT_ID",
    "updateTime": "...",
  },
}

where ENTITLEMENT_ID is an ID created by Google Cloud Marketplace.

In your system, update the user's account to reflect that they have purchased a plan. Then, to approve the entitlement, make an HTTP POST request to the Partner Procurement API, and send the ENTITLEMENT_ID that you are approving:

POST v1/providers/YOUR_PARTNER_ID/entitlements/ENTITLEMENT_ID:approve

To reject an entitlement, instead use the reject method in your HTTP POST request:

POST v1/providers/YOUR_PARTNER_ID/entitlements/ENTITLEMENT_ID:reject

Changing an entitlement plan

Depending on how you set up your pricing plans, your customers might be able to change their plan. If a customer selects a new pricing plan, you receive a Pub/Sub message, in the following format:

{
  "eventId": "...",
  "eventType": "ENTITLEMENT_PLAN_CHANGE_REQUESTED",
  "providerId": "YOUR_PARTNER_ID",
  "entitlement": {
    "id": "ENTITLEMENT_ID",
    "newPlan": "ultimate",   // New plan
    "updateTime": "...",
  },
}

To approve the plan change, make the following HTTP POST request to the Partner Procurement API:

POST v1/providers/YOUR_PARTNER_ID/entitlements/ENTITLEMENT_ID:approvePlanChange

The request body must have the plan that is being approved:

{
  "pendingPlanName": PLAN_NAME
}

After the change is approved, you receive another Pub/Sub message when the change takes effect. In the message, the eventType field changes to ENTITLEMENT_PLAN_CHANGED. To check the status of a plan, make the following HTTP GET request to the Partner Procurement API.

GET v1/providers/YOUR_PARTNER_ID/entitlements/ENTITLEMENT_ID

The response is similar to the following, with the state field indicating whether the new plan is active, or whether the plan change is still pending:

{
  "name": "providers/YOUR_PARTNER_ID/entitlements/ENTITLEMENT_ID",
  "provider": "YOUR_PARTNER_ID",
  "account": "USER_ACCOUNT_ID",
  "product": "example-server",
  "plan": "pro",
  "state": "ENTITLEMENT_PENDING_PLAN_CHANGE",
  "newPendingPlan": "ultimate",
  ...
}

Sending a status message to users

If the time between a user choosing a pricing plan and your backend approving an entitlement is a few hours or longer, we recommend that you provide a status message to users. In this message, indicate the progress of the approval, and if available, when you expect the approval to be complete.

To provide a status message, make the following HTTP POST request to the Procurement API:

POST v1/providers/your-partner-id/entitlements/entitlement_id:updateUserMessage

In the request body, provide the text of the message, similar to the following example:

{
  "message": "Approval expected in 2 days"
}

Canceling entitlements

If a user decides to cancel their entitlement, you receive a Pub/Sub notification. Similar to changing a plan, the actual cancellation might take effect at the end of the current billing cycle.

The notification is in the following format:

{
  "eventId": "...",
  // If the entitlement is canceled at the end of the month,
  // eventType is ENTITLEMENT_PENDING_CANCELLATION
  "eventType": "ENTITLEMENT_CANCELLED",
  "providerId": "YOUR_PARTNER_ID",
  "entitlement": {
    "id": "ENTITLEMENT_ID",
    "cancellationDate": "...",
    "updateTime": "..."
  },
}

Deleting an entitlement

If a user makes a direct request, or if they leave the Google platform, their entitlements are canceled and deleted, and their account is deleted. To protect the user's privacy, you must delete their data from your servers when you are notified.

When the entitlements are canceled and the account is deleted, you receive notifications similar to the following:

{
  "eventId": "...",
  "eventType": "ENTITLEMENT_DELETED",
  "providerId": "YOUR_PARTNER_ID",
  "entitlement": {
    "id": "ENTITLEMENT_ID",
    "updateTime": "...",
  },
}
{
  "eventId": "...",
  "eventType": "ACCOUNT_DELETED",
  "providerId": "YOUR_PARTNER_ID",
  "account": {
    "id": "USER_ACCOUNT_ID",
    "updateTime": "...",
  },
}

List of event types for account tasks

The following is a list of the eventTypes that your app might receive in Pub/Sub messages:

eventTypeDescription
ACCOUNT_CREATION_REQUESTEDDeprecated
ACCOUNT_ACTIVEIndicates that the customer's account has been created.
ACCOUNT_DELETEDIndicates that the customer's account was deleted from Google Cloud systems.
ENTITLEMENT_CREATION_REQUESTEDIndicates that a customer selected one of your pricing plans. This also triggers a new ENTITLEMENT_CREATION_REQUESTED event every 24 hours until you take action on the customer's request.
ENTITLEMENT_ACTIVEIndicates that a customer's chosen plan is now active.
ENTITLEMENT_PLAN_CHANGE_REQUESTEDIndicates that a customer chose a new plan. This also triggers a new ENTITLEMENT_PLAN_CHANGE_REQUESTED event every 24 hours until you take action on the customer's selection.
ENTITLEMENT_PLAN_CHANGEDIndicates that a customer's plan change is approved and the changes have taken effect.
ENTITLEMENT_PLAN_CHANGE_CANCELLEDIndicates that a customer's plan change was canceled, either because it wasn't approved, or because they switched back to their old plan.
ENTITLEMENT_PENDING_CANCELLATIONIndicates that a customer canceled their plan, and the cancellation is pending until the end of the billing cycle.
ENTITLEMENT_CANCELLATION_REVERTEDIndicates that a customer's pending cancellation was reverted. Note that cancellations cannot be reverted after they are final.
ENTITLEMENT_CANCELLEDIndicates that a customer's plan was canceled.
ENTITLEMENT_CANCELLINGIndicates that a customer's plan is in the process of being canceled.
ENTITLEMENT_RENEWEDIndicates that a customer's entitlement was renewed for another term. You don't need to take any action to complete the renewal.
ENTITLEMENT_OFFER_ENDEDIndicates that a customer's private offer has ended. If the customer's entitlement was canceled, a separate ENTITLEMENT_CANCELLED event is triggered. If the customer's entitlement is still active, their plan reverts to non-discounted pricing.
ENTITLEMENT_DELETEDIndicates that information about a customer's plan was deleted from Google Cloud Marketplace.

(For usage-based pricing) Reporting usage to Google

If you choose usage-based pricing for your product, you must report your app's usage to the Service Control API.

For an introduction to Service Control, see the Getting Started Guide.

If you have access to Producer Portal, we recommend that you use Producer Portal to create a service account in Producer Portal for use with Service Control.

If you don't have access to Producer Portal, your Partner Engineer creates a service that corresponds to your solution, and gives your service account access to report usage against that service.

When an entitlement is created, you must call the Partner Procurement API to retrieve a usageReportingId, using the following HTTP GET request:

GET v1/providers/YOUR_PARTNER_ID/entitlements/ENTITLEMENT_ID

The response contains information about the entitlement, in the following format:

{
  "name": "providers/YOUR_PARTNER_ID/entitlements/ENTITLEMENT_ID",
  "provider": "YOUR_PARTNER_ID",
  "account": "USER_ACCOUNT_ID",
  "product": "example-messaging-service",
  "plan": "pro",
  "usageReportingId": "USAGE_REPORTING_ID",
  "state": "ENTITLEMENT_ACTIVATION_REQUESTED",
  "updateTime": "...",
  "createTime": "..."
}

To report usage, you must first make a services.check API call, to check the service's configuration. In the response, if the checkErrors[] object is empty, make a services.report API call to send the usage report.

The usage report is a Service Control API Operation. The following is an example of a usage report for example-messaging-service that sends information about the storage being used by the customer:

POST https://servicecontrol.googleapis.com/v1/services/example-messaging-service.gcpmarketplace.example.com:report
{
  "operations": [{
    "operationId": "1234-example-operation-id-4567",
    "operationName": "Hourly Usage Report",
    "consumerId": "USAGE_REPORTING_ID",
    "startTime": "2019-02-06T12:00:00Z",
    "endTime": "2019-02-06T13:00:00Z",
    "metricValueSets": [{
      "metricName": "example-messaging-service/UsageInGiB",
      "metricValues": [{ "int64Value": "150" }]
    }],
    "userLabels": {
      "cloudmarketplace.googleapis.com/resource_name": "order_history_cache",
      "cloudmarketplace.googleapis.com/container_name": "storefront_prod",
      "environment": "prod",
      "region": "us-west2"
    }
  }]
}

where:

  • operationId is a unique string that your service instance generates. You should use the same operationId for your check and report operations.

  • consumerId is the same as the usageReportingId from the entitlement.

  • startTime and endTime represent the start and end times of the total interval for the report Operation. In most cases, the startTime of a report Operation should have the same value as the endTime of the previous report Operation.

    If a customer's service is disabled before the startTime of a report Operation, the services.check API call sends an error in the checkErrors[] object, and the customer is not charged for the corresponding interval.

  • MetricValueSet contains one or intermediate time intervals and corresponding updated metric values. You define your service's metrics when you choose and submit your pricing model.

    If you have access to Producer Portal, you view and reference the identifiers for your metrics in the Technical integration section of Producer Portal.

  • userLabels are user-created labels, defined as key-value strings that follow specific syntax requirements. These labels are forwarded to Cloud Billing cost management tools for attribution. For recommended labeling conventions, see Best practices for usage labeling.

If the services.check API returns one or more of the following errors, we recommend that you stop providing your service to the customer until the error is resolved:

  • SERVICE_NOT_ACTIVATED
  • BILLING_DISABLED
  • PROJECT_DELETED

Best practices for usage labeling

For a given entitlement, all usage is attributed to a single usageReportingId. However in some scenarios one usageReportingId may be shared broadly within a customer's organization. In order to support fine-grain cost attribution, we recommend that all services attach userLabels to usage reports. Labels will be forwarded to Cloud Billing cost management tools, including cost reports and billing exports.

If your service natively supports a concept of resource labels, we recommend that you forward those labels in your usage reports. Please note that labels will need to conform to the syntax requirements.

Additionally, Google Cloud Marketplace uses the following label conventions. You can use these labels to identify additional context for usage within your native service platform. We recommend that you include these labels in your usage reports by default.

Label KeyLabel ValueDescription>
cloudmarketplace.googleapis.com/resource_name USER_SUPPLIED The name of the resource associated with a usage metric. For example, if the metric is reporting database storage amounts, the value of this label would be the name of database.
cloudmarketplace.googleapis.com/container_name USER_SUPPLIED The name of a resource container. For example, if a database resource is parented by a cluster container, the value of this label would be the name of the cluster.