Codelab: obsługa administracyjna Google

Zanim zaczniesz

Opis

Obsługa administracyjna klienta z obszarem roboczym Google wymaga kilku wywołań interfejsu API. Poniższy schemat przedstawia ogólne czynności, które należy wykonać, aby zapewnić obsługę klienta.

Czynności, które musisz wykonać, aby udostępnić Google Workspace za pomocą Cloud Channel API

Krok 1. Utwórz obiekty usługi z uwierzytelnionymi danymi logowania

Korzystanie z biblioteki klienta

W tym scenariuszu założono, że używasz jednej z bibliotek klienckich na potrzeby Cloud Channel API.

Do integracji zalecamy użycie biblioteki klienta Google. Te biblioteki zapewniają interfejs dostosowany do języka i języka, oferują lepszą wydajność dzięki zastosowaniu RPC zamiast HTTP oraz ustawiają domyślne wartości pól.

Aby zainstalować bibliotekę:

C#

Jeśli korzystasz z programu Studio Studio w wersji 2017 lub nowszej, otwórz okno menedżera pakietów nuget i wpisz:

Install-Package Google.Cloud.Channel.V1

Jeśli używasz narzędzi interfejsu wiersza poleceń .NET Core do instalowania zależności, uruchom następujące polecenie:

dotnet add package Google.Cloud.Channel.V1

Go

go mod init YOUR_MODULE_NAME
go get -u cloud.google.com/go/channel/apiv1

Java

Jeśli używasz narzędzia Mavena, dodaj do pliku pom.xml następujące elementy. Więcej informacji o BOM znajdziesz w artykule Biblioteki Google Cloud Platform.

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>20.3.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-channel</artifactId>
    <version>2.1.1</version>
  </dependency>

Jeśli korzystasz z gradientu, dodaj do zależności te elementy:

implementation group: 'com.google.cloud', name: 'google-cloud-channel', version: '2.1.1'

Jeśli używasz kodu CS, IntelliJ lub Eklipse, możesz dodać biblioteki klienta do projektu, używając tych wtyczek IDE:

Wtyczki zapewniają dodatkowe funkcje, takie jak zarządzanie kluczami na kontach usług. Szczegółowe informacje znajdziesz w dokumentacji poszczególnych wtyczek.

Node.js

npm install --save @google-cloud/channel

PHP

composer require google/cloud-channel

Python

pip install google-cloud-channel

Ruby

gem install google-cloud-channel

Jeśli nie chcesz używać biblioteki klienta, zalecamy sprawdzenie, czy dostępna jest mniejsza biblioteka klienta do obsługi uwierzytelniania. Nie zalecamy przepisywania warstwy uwierzytelniania od podstaw.

Skonfiguruj dane logowania na potrzeby uwierzytelniania

Cloud Cloud API używa typu uwierzytelniania, który wymaga:

  1. Konto usługi i odpowiadający mu plik klucza JSON.
  2. Superużytkownik domeny sprzedawcy podszywający się pod inne osoby przy użyciu przekazywania dostępu w całej domenie na koncie usługi.

Jeśli brakuje jakichkolwiek wymagań wstępnych, postępuj zgodnie z kodem konfiguracji interfejsu API. Więcej informacji znajdziesz w artykule Konta usługi OAuth 2.0.

W poniższym kodzie wypełnij te zmienne, używając swoich informacji:

  • jsonKeyFile: ścieżka do pliku klucza JSON wygenerowanego podczas tworzenia konta usługi.
  • resellerAdminUser: adres e-mail superadministratora domeny sprzedawcy(najlepiej z konsoli usług testowych).
  • accountId: identyfikator konta, który znajdziesz na stronie Ustawienia w konsoli usług kanału.
  • customerDomain: domena klienta końcowego. Jeśli korzystasz z tego kodu w konsoli usług kanału testowego, upewnij się, że domena jest zgodna z konwencjami nazewnictwa domen.

C#

using Google.Apis.Auth.OAuth2;
using Google.Api.Gax;
using Google.Cloud.Channel.V1;
using Google.Type;
using Newtonsoft.Json;
using System;
using System.Linq;

namespace Codelab {

  class Program {

    /***************** REPLACE WITH YOUR OWN VALUES ********************************/
    private static readonly string jsonKeyFile = "path/to/json_key_file.json";
    private static readonly string resellerAdminUser = "admin@yourresellerdomain.com";
    private static readonly string accountId = "C012345";
    private static readonly string customerDomain = "example.com";
    /*******************************************************************************/

    private static readonly string accountName = "accounts/" + accountId;

    private static CloudChannelServiceClient client;

    static void Main(string[] args) {
      // Set up credentials with user impersonation
      ICredential credential = GoogleCredential.FromFile(jsonKeyFile)
                                   .CreateScoped(CloudChannelServiceClient.DefaultScopes)
                                   .CreateWithUser(resellerAdminUser);

      // Create the API client
      client = new CloudChannelServiceClientBuilder {
        TokenAccessMethod = credential.GetAccessTokenForRequestAsync
      }.Build();

Go

package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"

	channel "cloud.google.com/go/channel/apiv1"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	channelpb "google.golang.org/genproto/googleapis/cloud/channel/v1"
	"google.golang.org/genproto/googleapis/type/postaladdress"
	"google.golang.org/protobuf/encoding/protojson"
)

// ############## REPLACE WITH YOUR OWN VALUES ####################
const jsonKeyFile = "path/to/json_key_file.json"
const resellerAdminUser = "admin@yourresellerdomain.com"
const accountID = "C012345"
const customerDomain = "example.com"

// ################################################################

const accountName = "accounts/" + accountID

func main() {
	ctx := context.Background()
	// Set up credentials with user impersonation
	jsonKey, _ := ioutil.ReadFile(jsonKeyFile)
	jwt, _ := google.JWTConfigFromJSON(jsonKey, "https://www.googleapis.com/auth/apps.order")
	jwt.Subject = resellerAdminUser
	tokenSource := jwt.TokenSource(ctx)
	// Create the API client
	client, _ := channel.NewCloudChannelClient(ctx, option.WithTokenSource(tokenSource))

Java

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.cloud.channel.v1.AdminUser;
import com.google.cloud.channel.v1.CheckCloudIdentityAccountsExistRequest;
import com.google.cloud.channel.v1.CheckCloudIdentityAccountsExistResponse;
import com.google.cloud.channel.v1.CloudChannelServiceClient;
import com.google.cloud.channel.v1.CloudChannelServiceSettings;
import com.google.cloud.channel.v1.CloudIdentityInfo;
import com.google.cloud.channel.v1.CommitmentSettings;
import com.google.cloud.channel.v1.CreateCustomerRequest;
import com.google.cloud.channel.v1.CreateEntitlementRequest;
import com.google.cloud.channel.v1.Customer;
import com.google.cloud.channel.v1.Entitlement;
import com.google.cloud.channel.v1.ListOffersRequest;
import com.google.cloud.channel.v1.Offer;
import com.google.cloud.channel.v1.OperationMetadata;
import com.google.cloud.channel.v1.Parameter;
import com.google.cloud.channel.v1.PaymentPlan;
import com.google.cloud.channel.v1.Period;
import com.google.cloud.channel.v1.PeriodType;
import com.google.cloud.channel.v1.ProvisionCloudIdentityRequest;
import com.google.cloud.channel.v1.RenewalSettings;
import com.google.cloud.channel.v1.Value;
import com.google.gson.Gson;
import com.google.type.PostalAddress;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;

// ...

public class Codelab {

  /***************** REPLACE WITH YOUR OWN VALUES ********************************/
  public static final String JSON_KEY_FILE = "path/to/json_key_file.json";
  public static final String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com";
  public static final String ACCOUNT_ID = "C012345";
  public static final String CUSTOMER_DOMAIN = "example.com";
  /*******************************************************************************/

  public static final String ACCOUNT_NAME = "accounts/" + ACCOUNT_ID;

  private static CloudChannelServiceClient client;
  private static final Gson gson = new Gson();

  public static void main(String[] args)
      throws Exception, IOException, ExecutionException, InterruptedException {

    // Set up credentials with user impersonation
    FileInputStream jsonKeyFileStream = new FileInputStream(JSON_KEY_FILE);
    GoogleCredentials  credentials = ServiceAccountCredentials.fromStream(jsonKeyFileStream)
                                        .createScoped("https://www.googleapis.com/auth/apps.order")
                                        .createDelegated(RESELLER_ADMIN_USER);
    // Create the API client
    CloudChannelServiceSettings serviceSettings =
        CloudChannelServiceSettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
            .build();
    client = CloudChannelServiceClient.create(serviceSettings);

Node.js

const {JWT} = require('google-auth-library');
const {grpc} = require('google-gax');
const {CloudChannelServiceClient} = require('@google-cloud/channel');

// ############## REPLACE WITH YOUR OWN VALUES ####################
const jsonKeyFile = 'path/to/json_key_file.json';
const resellerAdminUser = 'admin@yourresellerdomain.com';
const accountId = 'C012345';
const customerDomain = 'example.com';
// ################################################################
const accountName = `accounts/${accountId}`;

// Set up credentials with user impersonation
const authClient = new JWT({
  keyFile: jsonKeyFile,
  scopes: ['https://www.googleapis.com/auth/apps.order'],
  subject: resellerAdminUser,
});
const sslCreds = grpc.credentials.combineChannelCredentials(
  grpc.credentials.createSsl(),
  grpc.credentials.createFromGoogleCredential(authClient)
);
// Create the API client
const client = new CloudChannelServiceClient({sslCreds});

PHP

require 'vendor/autoload.php';

use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Cloud\Channel;

// ############## REPLACE WITH YOUR OWN VALUES ####################
$JSON_KEY_FILE = 'path/to/json_key_file.json';
$RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com';
$ACCOUNT_ID = 'C012345';
$CUSTOMER_DOMAIN = 'example.com';
// ################################################################

$ACCOUNT_NAME = 'accounts/' . $ACCOUNT_ID;

// Set up credentials with user impersonation
$credentials = new ServiceAccountCredentials(
  'https://www.googleapis.com/auth/apps.order', /* $scope */
  $JSON_KEY_FILE, /* $keyFile */
  $RESELLER_ADMIN_USER /* $sub */
);

// Create the API client
$client = new Channel\V1\CloudChannelServiceClient([
  'credentials' => $credentials
]);

Python

from google.cloud import channel
from google.oauth2 import service_account

############## REPLACE WITH YOUR OWN VALUES ####################
JSON_KEY_FILE = "path/to/json_key_file.json"
RESELLER_ADMIN_USER = "admin@yourresellerdomain.com"
ACCOUNT_ID = "C012345"
CUSTOMER_DOMAIN = "example.com"
################################################################

ACCOUNT_NAME = "accounts/" + ACCOUNT_ID

# Set up credentials with user impersonation
credentials = service_account.Credentials.from_service_account_file(
    JSON_KEY_FILE, scopes=["https://www.googleapis.com/auth/apps.order"])
credentials_delegated = credentials.with_subject(RESELLER_ADMIN_USER)

# Create the API client
client = channel.CloudChannelServiceClient(credentials=credentials_delegated)

Ruby

require 'google-cloud-channel'

################## REPLACE WITH YOUR OWN VALUES ################################
JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'
RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'
ACCOUNT_ID = 'C012345'
CUSTOMER_DOMAIN = 'example.com'
################################################################################

ACCOUNT_NAME = "accounts/#{ACCOUNT_ID}"

# Set up credentials with user impersonation
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open(JSON_PRIVATE_KEY_FILE),
  scope: 'https://www.googleapis.com/auth/apps.order'
)
credentials.sub = RESELLER_ADMIN_USER

# Create the API client
CLIENT = Google::Cloud::Channel::cloud_channel_service do |config|
  config.credentials = credentials
end

Krok 2: wybierz ofertę z listy

C#

PagedEnumerable<ListOffersResponse, Offer> offers =
    client.ListOffers(new ListOffersRequest { Parent = accountName });

// For the purpose of this codelab, the code lists all offers and selects
// the first offer for Google Workspace Business Standard on an Annual
// plan. This is needed because offerIds vary from one account to another,
// but this is not a recommended model for your production integration
string sampleOffer = "Google Workspace Business Standard";
PaymentPlan samplePlan = PaymentPlan.Commitment;

Offer selectedOffer = offers.FirstOrDefault(
  o => o.Sku.MarketingInfo.DisplayName == sampleOffer && o.Plan.PaymentPlan == samplePlan);

Console.WriteLine("=== Selected offer");
Console.WriteLine(JsonConvert.SerializeObject(selectedOffer));

Go

var selectedOffer *channelpb.Offer
req := &channelpb.ListOffersRequest{
	Parent: accountName,
}
it := client.ListOffers(ctx, req)

// For the purpose of this codelab, the code lists all offers and selects
// the first offer for Google Workspace Business Standard on an Annual
// plan. This is needed because offerIds vary from one account to another and
// is not a recommended model for your production integration.
for {
	offer, err := it.Next()
	if err == iterator.Done {
		break
	}
	if offer.Sku.MarketingInfo.DisplayName == "Google Workspace Business Standard" &&
		offer.Plan.PaymentPlan == channelpb.PaymentPlan_COMMITMENT {
		selectedOffer = offer
		break
	}
}

fmt.Println("=== Selected offer")
fmt.Println(protojson.Format(selectedOffer))

Java

ListOffersRequest request =
    ListOffersRequest.newBuilder().setParent(ACCOUNT_NAME).build();

// For the purpose of this codelab, the code lists all offers and selects
// the first offer for Google Workspace Business Standard on an Annual
// plan. This is needed because offerIds vary from one account to another,
// but this is not a recommended model for your production integration
String sampleSkuName = "Google Workspace Business Standard";
String samplePlan = "COMMITMENT";

CloudChannelServiceClient.ListOffersPagedResponse response = client.listOffers(request);
Offer selectedOffer = Offer.newBuilder().build();
Iterator<Offer> iterator = response.iterateAll().iterator();
while (iterator.hasNext()) {
  Offer offer = iterator.next();
  String skuName = offer.getSku().getMarketingInfo().getDisplayName();
  String offerPlan = offer.getPlan().getPaymentPlan().name();
  if (skuName.equals(sampleSkuName) && offerPlan.equals(samplePlan)) {
    selectedOffer = offer;
    break;
  }
}

System.out.println("=== Selected offer");
System.out.println(gson.toJson(selectedOffer));

Node.js

const [offers] = await client.listOffers({
  parent: accountName,
});

// For the purpose of this codelab, the code lists all offers and selects
// the first offer for Google Workspace Business Standard on an Annual
// plan. This is needed because offerIds vary from one account to another,
// but this is not a recommended model for your production integration
const selectedOffer = offers.find(o => {
  return (
    o.sku.marketingInfo.displayName ===
      'Google Workspace Business Standard' &&
    o.plan.paymentPlan === 'COMMITMENT'
  );
});

console.log('=== Selected offer');
console.info(selectedOffer);

PHP

$offers = $client->listOffers($ACCOUNT_NAME /* parent */);

// For the purpose of this codelab, the code lists all offers and selects
// the first offer for Google Workspace Business Standard on an Annual
// plan. This is needed because offerIds vary from one account to another,
// but this is not a recommended model for your production integration
$sampleSku = 'Google Workspace Business Standard';
$samplePlan = Channel\V1\PaymentPlan::COMMITMENT;
foreach ($offers as $offer) {
  if ($offer->getSku()->getMarketingInfo()->getDisplayName() == $sampleSku
  && $offer->getPlan()->getPaymentPlan() == $samplePlan) {
    $selectedOffer = $offer;
    break;
  }
}

print '=== Selected offer' . PHP_EOL;
print $selectedOffer->serializeToJsonString() . PHP_EOL;

Python

request = channel.ListOffersRequest(parent=ACCOUNT_NAME)
offers = client.list_offers(request)

# For the purpose of this codelab, the code lists all offers and selects
# the first offer for Google Workspace Business Standard on an Annual
# plan. This is needed because offerIds vary from one account to another,
# but this is not a recommended model for your production integration
sample_offer = "Google Workspace Business Standard"
sample_plan = "PaymentPlan.COMMITMENT"
selected_offer = None
for offer in offers:
  if offer.sku.marketing_info.display_name == sample_offer and \
      str(offer.plan.payment_plan) == sample_plan:
    selected_offer = offer
    break

print("=== Selected offer")
print(selected_offer)

Ruby

# For the purpose of this codelab, the code lists all offers and selects
# the first offer for Google Workspace Business Standard on an Annual
# plan. This is needed because offerIds vary from one account to another,
# but this is not a recommended model for your production integration

request = Google::Cloud::Channel::V1::ListOffersRequest.new({ parent: ACCOUNT_NAME })
offers = CLIENT.list_offers(request)
sample_offer = 'Google Workspace Business Standard'
sample_plan = :COMMITMENT

offer = offers.detect { |offer| offer.sku.marketing_info.display_name == sample_offer
  && offer.plan.payment_plan == sample_plan }
puts("=== Selected offer")
puts(offer.inspect)

Krok 3. Utwórz klienta w Google Workspace

Sprawdź, czy klient ma tożsamość w chmurze

Usługi Google Workspace możesz udostępniać tylko tym klientom, którzy nie mają tożsamości w chmurze lub jeśli sprzedajesz je już teraz.

Jeśli klient ma tożsamość w chmurze, musisz przenieść klienta i jego uprawnienia.

Użyj punktu końcowego accounts.checkCloudIdentityAccountsExist, by sprawdzić, czy możesz udostępnić go jako nowego klienta. Jeśli punkt końcowy zwraca listę istniejących tożsamości w chmurze, musisz przenieść klienta.

C#

// Determine if customer already has a cloud identity
CheckCloudIdentityAccountsExistRequest request =
    new CheckCloudIdentityAccountsExistRequest { Parent = accountName,
                                                 Domain = customerDomain };

CheckCloudIdentityAccountsExistResponse response =
    client.CheckCloudIdentityAccountsExist(request);

if (response.CloudIdentityAccounts.Count > 0) {
  throw new Exception(@"Cloud identity already exists. Customer must be transferred.
  Out of scope for this codelab");
}

Go

// Determine if customer already has a cloud identity
req := &channelpb.CheckCloudIdentityAccountsExistRequest{
	Parent: accountName,
	Domain: customerDomain,
}
res, _ := client.CheckCloudIdentityAccountsExist(ctx, req)
// checkCloudIdentityAccountsExist always returns an array
if len(res.CloudIdentityAccounts) > 0 {
	log.Fatal(`Cloud identity already exists;
		customer must be transferred
		[out-of-scope of this codelab]`)
}

Java

// Determine if customer already has a cloud identity
CheckCloudIdentityAccountsExistRequest request =
    CheckCloudIdentityAccountsExistRequest.newBuilder()
        .setParent(ACCOUNT_NAME)
        .setDomain(CUSTOMER_DOMAIN)
        .build();
CheckCloudIdentityAccountsExistResponse response =
    client.checkCloudIdentityAccountsExist(request);

if (response.getCloudIdentityAccountsCount() > 0) {
  throw new Exception(
      "Cloud identity already exists. "
      + "Customer must be transferred. "
      + "Out of scope for this codelab");
}

Node.js

// Determine if customer already has a cloud identity
const [
  cloudIdentityAccounts,
] = await client.checkCloudIdentityAccountsExist({
  parent: accountName,
  domain: customerDomain,
});

if (cloudIdentityAccounts.length > 0) {
  throw new Error(
    'Cloud identity already exists; ' +
      'customer must be transferred ' +
      '[out-of-scope of this codelab]'
  );
}

PHP

// Determine if customer already has a cloud identity
$response = $client->checkCloudIdentityAccountsExist(
  $ACCOUNT_NAME /* parent */,
  $CUSTOMER_DOMAIN /* domain */
);

if (count($response->getCloudIdentityAccounts()) > 0) {
  throw new Error('Cloud identity already exists; \
    customer must be transferred \
    [out-of-scope of this codelab]'
  );
}

Python

# Determine if customer already has a cloud identity
request = channel.CheckCloudIdentityAccountsExistRequest(
    parent=ACCOUNT_NAME, domain=CUSTOMER_DOMAIN)

response = client.check_cloud_identity_accounts_exist(request)

if response.cloud_identity_accounts:
  raise Exception(
      "Cloud identity already exists. Customer must be transferred." +
      "Out of scope for this codelab")

Ruby

# Determine if customer already has a cloud identity
request = Google::Cloud::Channel::V1::CheckCloudIdentityAccountsExistRequest
.new({ parent: ACCOUNT_NAME, domain: CUSTOMER_DOMAIN })
response = CLIENT.check_cloud_identity_accounts_exist(request)

if response.cloud_identity_accounts.count > 0
  raise 'Cloud identity already exists. Customer must be transferred.'\
    'Out of scope for this codelab'
end

Utwórz klienta usług kanału

Aby móc tworzyć uprawnienia, musisz utworzyć klienta usług kanału dla klienta sprzedaży.

C#

// Create the Customer resource
CreateCustomerRequest request = new CreateCustomerRequest {
  Parent = accountName,
  Customer = new Customer { OrgDisplayName = "Acme Corp",
                            OrgPostalAddress = new PostalAddress {
                                  AddressLines = { "1800 Amphibious Blvd" },
                                  PostalCode = "94045",
                                  RegionCode = "US" },
                            Domain = customerDomain }
};

Customer customer = client.CreateCustomer(request);
Console.WriteLine("=== Created customer with id " + customer.Name);
Console.WriteLine(JsonConvert.SerializeObject(customer));

Go

// Create the Customer resource
req := &channelpb.CreateCustomerRequest{
	Parent: accountName,
	Customer: &channelpb.Customer{
		OrgDisplayName: "Acme Corp",
		OrgPostalAddress: &postaladdress.PostalAddress{
			AddressLines: []string{"1800 Amphibious Blvd"},
			PostalCode:   "94045",
			RegionCode:   "US",
		},
		Domain: customerDomain,
		// Distributors need to pass the following value
		// ChannelPartnerId: channelPartnerLinkId
	},
}
customer, _ := client.CreateCustomer(ctx, req)
fmt.Println("=== Created customer with id " + customer.Name)
fmt.Println(protojson.Format(customer))

Java

// Create the Customer resource
PostalAddress postalAddress =
    PostalAddress.newBuilder()
        .addAddressLines("1800 Amphibious Blvd")
        .setPostalCode("94045")
        .setRegionCode("US")
        .build();

CreateCustomerRequest request =
    CreateCustomerRequest.newBuilder()
        .setParent(ACCOUNT_NAME)
        .setCustomer(
            Customer.newBuilder()
                .setOrgDisplayName("Acme Corp")
                .setOrgPostalAddress(postalAddress)
                .setDomain(CUSTOMER_DOMAIN)
                // Distributors need to pass the following field
                // .setChannelPartnerId(channelPartnerLinkId)
                .build())
        .build();

Customer customer = client.createCustomer(request);

System.out.println("=== Created customer with id " + customer.getName());
System.out.println(gson.toJson(customer));

Node.js

// Create the Customer resource
let [customer] = await client.createCustomer({
  parent: accountName,
  customer: {
    orgDisplayName: 'Acme Corp',
    orgPostalAddress: {
      addressLines: ['1800 Amphibious Blvd'],
      postalCode: '94045',
      regionCode: 'US',
    },
    domain: customerDomain,
    // Distributors need to pass the following field
    // channelPartnerId: channelPartnerLinkId
  },
});
console.log(`=== Created customer with id ${customer.name}`);
console.info(customer);

PHP

// Create the Customer resource
$customer = $client->createCustomer(
  $ACCOUNT_NAME  /* parent */,
  new Channel\V1\Customer([
    'org_display_name' => 'Acme Corp',
    'org_postal_address' => new Google\Type\PostalAddress([
      'address_lines' => ['1800 Amphibious Blvd'],
      'postal_code' => '94045',
      'region_code' => 'US',
    ]),
    'domain' => $CUSTOMER_DOMAIN,
    // Distributors need to pass the following field
    // 'channel_partner_id' => $channelPartnerLinkId
  ])
);

print '=== Created customer with id ' . $customer->getName() . PHP_EOL;
print $customer->serializeToJsonString() . PHP_EOL;

Python

# Create the Customer resource
request = channel.CreateCustomerRequest(
    parent=ACCOUNT_NAME,
    customer={
        "org_display_name": "Acme Corp",
        "domain": CUSTOMER_DOMAIN,
        "org_postal_address": {
            "address_lines": ["1800 Amphibious Blvd"],
            "postal_code": "94045",
            "region_code": "US"
        }
    })
# Distributors need to also pass the following field for the `customer`
# "channel_partner_id": channel_partner_link_id

customer = client.create_customer(request)

print("=== Created customer with id ", customer.name)
print(customer)

Ruby

# Create the Customer resource

request = Google::Cloud::Channel::V1::CreateCustomerRequest.new(
  parent: ACCOUNT_NAME,
  customer: {
    'org_display_name': 'Acme Corp',
    'domain': CUSTOMER_DOMAIN,
    'org_postal_address': {
      'address_lines': ['1800 Amphibious Blvd'],
      'postal_code': '94045',
      'region_code': 'US'
    }
  })

# Distributors need to also pass the following field for the `customer`
# "channel_partner_id": channel_partner_link_id

customer = CLIENT.create_customer(request)

puts("=== Created customer with id " + customer.name)
puts(customer.inspect)

Udostępnianie tożsamości w chmurze

Gdy masz już klienta, musisz dołączyć tożsamość w chmurze z informacjami wymaganymi do obsługi usług Google Workspace.

C#

CloudIdentityInfo cloudIdentityInfo =
    new CloudIdentityInfo { AlternateEmail = "john.doe@gmail.com", LanguageCode = "en-US" };

AdminUser adminUser = new AdminUser { GivenName = "John", FamilyName = "Doe",
                                      Email = "admin@" + customerDomain };

ProvisionCloudIdentityRequest cloudIdentityRequest = new ProvisionCloudIdentityRequest {
  Customer = customer.Name, CloudIdentityInfo = cloudIdentityInfo, User = adminUser
};

// This call returns a long-running operation.
var operation = client.ProvisionCloudIdentity(cloudIdentityRequest);

// Wait for the long-running operation and get the result.
customer = operation.PollUntilCompleted().Result;
Console.WriteLine("=== Provisioned cloud identity");

Go

cireq := &channelpb.ProvisionCloudIdentityRequest{
	Customer: customer.Name,
	CloudIdentityInfo: &channelpb.CloudIdentityInfo{
		AlternateEmail: "john.doe@gmail.com",
		LanguageCode:   "en-US",
	},
	User: &channelpb.AdminUser{
		GivenName:  "John",
		FamilyName: "Doe",
		Email:      "admin@" + customerDomain,
	},
}
// This endpoint returns a long-running operation.
op, _ := client.ProvisionCloudIdentity(ctx, cireq)

// Wait for the long-running operation and get the result.
customer, _ = op.Wait(ctx)
fmt.Println("=== Provisioned cloud identity")

Java

CloudIdentityInfo cloudIdentityInfo =
    CloudIdentityInfo.newBuilder()
        .setAlternateEmail("john.doe@gmail.com")
        .setLanguageCode("en-US")
        .build();

AdminUser adminUser =
    AdminUser.newBuilder()
        .setGivenName("John")
        .setFamilyName("Doe")
        .setEmail("admin@" + CUSTOMER_DOMAIN)
        .build();

ProvisionCloudIdentityRequest cloudIdentityRequest =
    ProvisionCloudIdentityRequest.newBuilder()
        .setCustomer(customer.getName())
        .setCloudIdentityInfo(cloudIdentityInfo)
        .setUser(adminUser)
        .build();

// This call returns a long-running operation.
OperationFuture<Customer, OperationMetadata> operation =
    client.provisionCloudIdentityAsync(cloudIdentityRequest);

// Wait for the long-running operation and get the result.
customer = operation.get();
System.out.println("=== Provisioned cloud identity");

Node.js

// This endpoint returns a long-running operation.
// For other ways to get operation results, see
// https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations
const [operation] = await client.provisionCloudIdentity({
  customer: customer.name,
  cloudIdentityInfo: {
    alternateEmail: 'john.doe@gmail.com',
    languageCode: 'en-US',
  },
  user: {
    givenName: 'John',
    familyName: 'Doe',
    email: `admin@${customerDomain}`,
  },
});

// Wait for the long-running operation and get the result.
[customer] = await operation.promise();
console.log('=== Provisioned cloud identity');

PHP

// This endpoint returns a long-running operation.
$operation = $client->provisionCloudIdentity(
  $customer->getName() /* customer */,
  [
    'cloudIdentityInfo' => new Channel\V1\CloudIdentityInfo([
      'alternate_email' => 'john.doe@gmail.com',
      'language_code' => 'en-US',
    ]),
    'user' => new Channel\V1\AdminUser([
      'given_name' => 'John',
      'family_name' => 'Doe',
      'email' => 'admin@' . $CUSTOMER_DOMAIN,
    ]),
  ]
);

// Wait for the long-running operation and get the result.
$operation->pollUntilComplete();
$customer = $operation->getResult();
print '=== Provisioned cloud identity' . PHP_EOL;

Python

cloud_identity_info = channel.CloudIdentityInfo(
    alternate_email="john.doe@gmail.com", language_code="en-US")

admin_user = channel.AdminUser(
    given_name="John", family_name="Doe", email="admin@" + CUSTOMER_DOMAIN)

cloud_identity_request = channel.ProvisionCloudIdentityRequest(
    customer=customer.name,
    cloud_identity_info=cloud_identity_info,
    user=admin_user)

# This call returns a long-running operation.
operation = client.provision_cloud_identity(cloud_identity_request)

# Wait for the long-running operation and get the result.
customer = operation.result()

print("=== Provisioned cloud identity")

Ruby

cloud_identity_info = Google::Cloud::Channel::V1::CloudIdentityInfo.new(
  alternate_email: 'john.doe@gmail.com', language_code: 'en-US'
)

admin_user = Google::Cloud::Channel::V1::AdminUser.new(
  given_name: 'John', family_name: 'Doe', email: "admin@#{CUSTOMER_DOMAIN}"
)

cloud_identity_request = Google::Cloud::Channel::V1::ProvisionCloudIdentityRequest.new(
  customer: customer.name,
  cloud_identity_info: cloud_identity_info,
  user: admin_user
)

# This call returns a long-running operation.
operation = CLIENT.provision_cloud_identity(cloud_identity_request)

# Wait for the long-running operation and get the result.
CLIENT.operations_client.wait_operation(Google::Longrunning::WaitOperationRequest
  .new({ name: operation.name }))
operation = CLIENT.operations_client.get_operation(Google::Longrunning::GetOperationRequest
  .new({ name: operation.name }))
customer = operation.response
puts("=== Provisioned cloud identity")

To wywołanie spowoduje utworzenie tożsamości w chmurze, w tym pierwszego superadministratora klienta.

Krok 4. Utwórz uprawnienie do obszaru roboczego Google

Po utworzeniu klienta i jego tożsamości w chmurze możesz teraz przyznać uprawnienia do obszaru roboczego Google.

C#

RenewalSettings renewalSettings = new RenewalSettings {
  // Setting renewal settings to auto renew
  EnableRenewal = true,
  PaymentPlan = PaymentPlan.Commitment,
  PaymentCycle = new Period {
    PeriodType = PeriodType.Year,
    Duration = 1
  }
};

CreateEntitlementRequest request = new CreateEntitlementRequest {
  Parent = customer.Name,
  Entitlement = new Entitlement {
      Offer = selectedOffer.Name,
      // Setting 5 seats for this Annual offer
      Parameters = { new Parameter { Name = "num_units",
                                     Value = new Value { Int64Value = 5 } } },
      CommitmentSettings = new CommitmentSettings { RenewalSettings = renewalSettings },
      // A string of up to 80 characters.
      // We recommend using an internal transaction ID or
      // identifier for the customer in this field.
      PurchaseOrderId = "A codelab test"
    }
};

// This call returns a long-running operation.
var operation = client.CreateEntitlement(request);

// Wait for the long-running operation and get the result.
Entitlement entitlement = operation.PollUntilCompleted().Result;
Console.WriteLine("=== Created entitlement");
Console.WriteLine(JsonConvert.SerializeObject(entitlement));

Go

// This endpoint returns a long-running operation.
req := &channelpb.CreateEntitlementRequest{
	Parent: customer.Name,
	Entitlement: &channelpb.Entitlement{
		Offer: selectedOffer.Name,
		// Setting 5 seats for this Annual offer
		Parameters: []*channelpb.Parameter{
			{
				Name: "num_units",
				Value: &channelpb.Value{
					Kind: &channelpb.Value_Int64Value{Int64Value: 5},
				},
			},
		},
		// Setting renewal settings to auto renew
		CommitmentSettings: &channelpb.CommitmentSettings{
			RenewalSettings: &channelpb.RenewalSettings{
				EnableRenewal: true,
				PaymentPlan:   channelpb.PaymentPlan_COMMITMENT,
				PaymentCycle: &channelpb.Period{
					Duration:   1,
					PeriodType: channelpb.PeriodType_YEAR,
				},
			},
		},
		// A string of up to 80 characters.
		// We recommend using an internal transaction ID or
		// identifier for the customer in this field.
		PurchaseOrderId: "A codelab test",
	},
}
// This endpoint returns a long-running operation.
op, _ := client.CreateEntitlement(ctx, req)

// Wait for the long-running operation and get the result.
entitlement, _ := op.Wait(ctx)

fmt.Println("=== Created entitlement")
fmt.Println(protojson.Format(entitlement))

Java

RenewalSettings renewalSettings =
    RenewalSettings.newBuilder()
        // Setting renewal settings to auto renew
        .setEnableRenewal(true)
        .setPaymentPlan(PaymentPlan.COMMITMENT)
        .setPaymentCycle(
            Period.newBuilder().setPeriodType(PeriodType.YEAR).setDuration(1).build())
        .build();

CommitmentSettings commitmentSettings =
    CommitmentSettings.newBuilder().setRenewalSettings(renewalSettings).build();

Entitlement entitlement =
    Entitlement.newBuilder()
        .setOffer(selectedOffer.getName())
        // Setting 5 seats for this Annual offer
        .addParameters(
            Parameter.newBuilder()
                .setName("num_units")
                .setValue(Value.newBuilder().setInt64Value(5).build())
                .build())
        .setCommitmentSettings(commitmentSettings)
        // A string of up to 80 characters.
        // We recommend using an internal transaction ID or
        // identifier for the customer in this field.
        .setPurchaseOrderId("A codelab test")
        .build();

CreateEntitlementRequest request =
    CreateEntitlementRequest.newBuilder()
        .setParent(customer.getName())
        .setEntitlement(entitlement)
        .build();

// This call returns a long-running operation.
OperationFuture<Entitlement, OperationMetadata> operation =
    client.createEntitlementAsync(request);

// Wait for the long-running operation and get the result.
entitlement = operation.get();
System.out.println("=== Created entitlement");
System.out.println(gson.toJson(entitlement));

Node.js

// This call returns a long-running operation.
const [operation] = await client.createEntitlement({
  parent: customer.name,
  entitlement: {
    offer: selectedOffer.name,
    parameters: [
      // Setting 5 seats for this Annual offer
      {
        name: 'num_units',
        value: {
          int64Value: 5,
        },
      },
    ],
    commitmentSettings: {
      // Setting renewal settings to auto renew
      renewalSettings: {
        enableRenewal: true,
        paymentPlan: 'COMMITMENT',
        paymentCycle: {
          duration: 1,
          periodType: 'YEAR',
        },
      },
    },
    // A string of up to 80 characters.
    // We recommend using an internal transaction ID or
    // identifier for the customer in this field.
    purchaseOrderId: 'A codelab test',
  },
});

// Wait for the long-running operation and get the result.
const [entitlement] = await operation.promise();
console.log('=== Created entitlement');
console.info(entitlement);

PHP

// This call returns a long-running operation.
$operation = $client->createEntitlement(
  $customer->getName() /* parent */,
  new Channel\V1\Entitlement([
    'offer' => $selectedOffer->getName(),
    'parameters' => [
      new Channel\V1\Parameter([
        // Setting 5 seats for this Annual offer
        'name' => 'num_units',
        'value' => new Channel\V1\Value([
          'int64_value' => 5,
        ])
      ]),
    ],
    'commitment_settings' => new Channel\V1\CommitmentSettings([
      // Setting renewal settings to auto renew
      'renewal_settings' => new Channel\V1\RenewalSettings([
        'enable_renewal' => true,
        'payment_plan' => Channel\V1\PaymentPlan::COMMITMENT,
        'payment_cycle' => new Channel\V1\Period([
          'duration' => 1,
          'period_type' => Channel\V1\PeriodType::YEAR,
        ]),
      ]),
    ]),
    // A string of up to 80 characters.
    // We recommend using an internal transaction ID or
    // identifier for the customer in this field.
    'purchase_order_id' => 'A codelab test'
  ])
);

// Wait for the long-running operation and get the result.
$operation->pollUntilComplete();
$entitlement = $operation->getResult();
print '=== Created entitlement' . PHP_EOL;
print $entitlement->serializeToJsonString() . PHP_EOL;

Python

request = channel.CreateEntitlementRequest(
    parent=customer.name,
    entitlement={
        "offer": selected_offer.name,
        # Setting 5 seats for this Annual offer
        "parameters": [{
            "name": "num_units",
            "value": {
                "int64_value": 5
            }
        }],
        "commitment_settings": {
            "renewal_settings": {
                # Setting renewal settings to auto renew
                "enable_renewal": True,
                "payment_plan": "COMMITMENT",
                "payment_cycle": {
                    "period_type": "YEAR",
                    "duration": 1
                }
            }
        },
        # A string of up to 80 characters.
        # We recommend an internal transaction ID or
        # identifier for this customer in this field.
        "purchase_order_id": "A codelab test"
    })

# This call returns a long-running operation.
operation = client.create_entitlement(request)

# Wait for the long-running operation and get the result.
entitlement = operation.result()

print("=== Created entitlement")
print(entitlement)

Ruby

request = Google::Cloud::Channel::V1::CreateEntitlementRequest.new(
  parent: customer.name,
  entitlement: {
    offer: selected_offer.name,
    # Setting 5 seats for this Annual offer
    parameters: [{
                   name: 'num_units',
                   value: {
                     int64_value: 5
                   }
                 }],
    commitment_settings: {
      renewal_settings: {
        # Setting renewal settings to auto renew
        enable_renewal: true,
        payment_plan: 'COMMITMENT',
        payment_cycle: {
          period_type: 'YEAR',
          duration: 1
        }
      }
    },
    # A string of up to 80 characters.
    # We recommend an internal transaction ID or
    # identifier for this customer in this field.
    purchase_order_id: 'A codelab test'
  })

# This call returns a long-running operation.
operation = CLIENT.create_entitlement(request)

# Wait for the long-running operation and get the result.
CLIENT.operations_client.wait_operation(Google::Longrunning::WaitOperationRequest
  .new({ name: operation.name }))
operation = CLIENT.operations_client.get_operation(Google::Longrunning::GetOperationRequest
  .new({ name: operation.name }))
entitlement = operation.response

puts("=== Created entitlement")
puts(entitlement)

Opcjonalnie: zintegruj z pakietem Workspace Admin SDK

Jeśli planujesz integrację z pakietem Admin SDK, jego interfejsy API wymagają obszaru roboczego Google customerId. Cloud Cloud API zwraca wartość cloudIdentityId w zasobie Customer.

C#

string customerId = customer.CloudIdentityId;
Console.WriteLine(customerId);

Go

customerID := customer.CloudIdentityId
fmt.Println(customerID)

Java

String adminSDKCustomerId = customer.getCloudIdentityId();
System.out.println(adminSDKCustomerId);

Node.js

const customerId = customer.cloudIdentityId;
console.log(customerId);

PHP

$customerId = $customer->getCloudIdentityId();
print $customerId . PHP_EOL;

Python

customer_id = customer.cloud_identity_id
print(customer_id)

Ruby

customer_id = customer.cloud_identity_id
puts(customer_id)

Jak to wszystko połączyć

Pełny przykładowy kod umożliwiający udostępnienie klientowi uprawnień do obszaru roboczego Google:

C#

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Instructions for this codelab can be found on this page
// https://cloud.google.com/channel/docs/codelabs/workspace/provisioning

using Google.Apis.Auth.OAuth2;
using Google.Api.Gax;
using Google.Cloud.Channel.V1;
using Google.Type;
using Newtonsoft.Json;
using System;
using System.Linq;

namespace Codelab {

  class Program {

    /***************** REPLACE WITH YOUR OWN VALUES ********************************/
    private static readonly string jsonKeyFile = "path/to/json_key_file.json";
    private static readonly string resellerAdminUser = "admin@yourresellerdomain.com";
    private static readonly string accountId = "C012345";
    private static readonly string customerDomain = "example.com";
    /*******************************************************************************/

    private static readonly string accountName = "accounts/" + accountId;

    private static CloudChannelServiceClient client;

    static void Main(string[] args) {
      // Set up credentials with user impersonation
      ICredential credential = GoogleCredential.FromFile(jsonKeyFile)
                                   .CreateScoped(CloudChannelServiceClient.DefaultScopes)
                                   .CreateWithUser(resellerAdminUser);

      // Create the API client
      client = new CloudChannelServiceClientBuilder {
        TokenAccessMethod = credential.GetAccessTokenForRequestAsync
      }.Build();

      Offer selectedOffer = SelectOffer();

      CheckExists();

      Customer customer = CreateCustomer();

      Entitlement entitlement = CreateEntitlement(customer, selectedOffer);

      string customerId = customer.CloudIdentityId;
      Console.WriteLine(customerId);
    }

    static Offer SelectOffer() {
      PagedEnumerable<ListOffersResponse, Offer> offers =
          client.ListOffers(new ListOffersRequest { Parent = accountName });

      // For the purpose of this codelab, the code lists all offers and selects
      // the first offer for Google Workspace Business Standard on an Annual
      // plan. This is needed because offerIds vary from one account to another,
      // but this is not a recommended model for your production integration
      string sampleOffer = "Google Workspace Business Standard";
      PaymentPlan samplePlan = PaymentPlan.Commitment;

      Offer selectedOffer = offers.FirstOrDefault(
        o => o.Sku.MarketingInfo.DisplayName == sampleOffer && o.Plan.PaymentPlan == samplePlan);

      Console.WriteLine("=== Selected offer");
      Console.WriteLine(JsonConvert.SerializeObject(selectedOffer));

      return selectedOffer;
    }

    static void CheckExists() {
      // Determine if customer already has a cloud identity
      CheckCloudIdentityAccountsExistRequest request =
          new CheckCloudIdentityAccountsExistRequest { Parent = accountName,
                                                       Domain = customerDomain };

      CheckCloudIdentityAccountsExistResponse response =
          client.CheckCloudIdentityAccountsExist(request);

      if (response.CloudIdentityAccounts.Count > 0) {
        throw new Exception(@"Cloud identity already exists. Customer must be transferred.
        Out of scope for this codelab");
      }
    }

    static Customer CreateCustomer() {
      // Create the Customer resource
      CreateCustomerRequest request = new CreateCustomerRequest {
        Parent = accountName,
        Customer = new Customer { OrgDisplayName = "Acme Corp",
                                  OrgPostalAddress = new PostalAddress {
                                        AddressLines = { "1800 Amphibious Blvd" },
                                        PostalCode = "94045",
                                        RegionCode = "US" },
                                  Domain = customerDomain }
      };

      Customer customer = client.CreateCustomer(request);
      Console.WriteLine("=== Created customer with id " + customer.Name);
      Console.WriteLine(JsonConvert.SerializeObject(customer));

      CloudIdentityInfo cloudIdentityInfo =
          new CloudIdentityInfo { AlternateEmail = "john.doe@gmail.com", LanguageCode = "en-US" };

      AdminUser adminUser = new AdminUser { GivenName = "John", FamilyName = "Doe",
                                            Email = "admin@" + customerDomain };

      ProvisionCloudIdentityRequest cloudIdentityRequest = new ProvisionCloudIdentityRequest {
        Customer = customer.Name, CloudIdentityInfo = cloudIdentityInfo, User = adminUser
      };

      // This call returns a long-running operation.
      var operation = client.ProvisionCloudIdentity(cloudIdentityRequest);

      // Wait for the long-running operation and get the result.
      customer = operation.PollUntilCompleted().Result;
      Console.WriteLine("=== Provisioned cloud identity");

      return customer;
    }

    static Entitlement CreateEntitlement(Customer customer, Offer selectedOffer) {
      RenewalSettings renewalSettings = new RenewalSettings {
        // Setting renewal settings to auto renew
        EnableRenewal = true,
        PaymentPlan = PaymentPlan.Commitment,
        PaymentCycle = new Period {
          PeriodType = PeriodType.Year,
          Duration = 1
        }
      };

      CreateEntitlementRequest request = new CreateEntitlementRequest {
        Parent = customer.Name,
        Entitlement = new Entitlement {
            Offer = selectedOffer.Name,
            // Setting 5 seats for this Annual offer
            Parameters = { new Parameter { Name = "num_units",
                                           Value = new Value { Int64Value = 5 } } },
            CommitmentSettings = new CommitmentSettings { RenewalSettings = renewalSettings },
            // A string of up to 80 characters.
            // We recommend using an internal transaction ID or
            // identifier for the customer in this field.
            PurchaseOrderId = "A codelab test"
          }
      };

      // This call returns a long-running operation.
      var operation = client.CreateEntitlement(request);

      // Wait for the long-running operation and get the result.
      Entitlement entitlement = operation.PollUntilCompleted().Result;
      Console.WriteLine("=== Created entitlement");
      Console.WriteLine(JsonConvert.SerializeObject(entitlement));

      return entitlement;
    }
  }
}

Go

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Instructions for this codelab can be found on this page
// https://cloud.google.com/channel/docs/codelabs/workspace/provisioning

package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"

	channel "cloud.google.com/go/channel/apiv1"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	channelpb "google.golang.org/genproto/googleapis/cloud/channel/v1"
	"google.golang.org/genproto/googleapis/type/postaladdress"
	"google.golang.org/protobuf/encoding/protojson"
)

// ############## REPLACE WITH YOUR OWN VALUES ####################
const jsonKeyFile = "path/to/json_key_file.json"
const resellerAdminUser = "admin@yourresellerdomain.com"
const accountID = "C012345"
const customerDomain = "example.com"

// ################################################################

const accountName = "accounts/" + accountID

func main() {
	ctx := context.Background()
	// Set up credentials with user impersonation
	jsonKey, _ := ioutil.ReadFile(jsonKeyFile)
	jwt, _ := google.JWTConfigFromJSON(jsonKey, "https://www.googleapis.com/auth/apps.order")
	jwt.Subject = resellerAdminUser
	tokenSource := jwt.TokenSource(ctx)
	// Create the API client
	client, _ := channel.NewCloudChannelClient(ctx, option.WithTokenSource(tokenSource))

	selectedOffer := selectOffer(ctx, client)

	checkExists(ctx, client)

	customer := createCustomer(ctx, client)

	_ /* entitlement */ = createEntitlement(ctx, client, customer, selectedOffer)

	customerID := customer.CloudIdentityId
	fmt.Println(customerID)
}

func selectOffer(ctx context.Context, client *channel.CloudChannelClient) *channelpb.Offer {
	var selectedOffer *channelpb.Offer
	req := &channelpb.ListOffersRequest{
		Parent: accountName,
	}
	it := client.ListOffers(ctx, req)

	// For the purpose of this codelab, the code lists all offers and selects
	// the first offer for Google Workspace Business Standard on an Annual
	// plan. This is needed because offerIds vary from one account to another and
	// is not a recommended model for your production integration.
	for {
		offer, err := it.Next()
		if err == iterator.Done {
			break
		}
		if offer.Sku.MarketingInfo.DisplayName == "Google Workspace Business Standard" &&
			offer.Plan.PaymentPlan == channelpb.PaymentPlan_COMMITMENT {
			selectedOffer = offer
			break
		}
	}

	fmt.Println("=== Selected offer")
	fmt.Println(protojson.Format(selectedOffer))

	return selectedOffer
}

func checkExists(ctx context.Context, client *channel.CloudChannelClient) {
	// Determine if customer already has a cloud identity
	req := &channelpb.CheckCloudIdentityAccountsExistRequest{
		Parent: accountName,
		Domain: customerDomain,
	}
	res, _ := client.CheckCloudIdentityAccountsExist(ctx, req)
	// checkCloudIdentityAccountsExist always returns an array
	if len(res.CloudIdentityAccounts) > 0 {
		log.Fatal(`Cloud identity already exists;
			customer must be transferred
			[out-of-scope of this codelab]`)
	}
}

func createCustomer(ctx context.Context, client *channel.CloudChannelClient) *channelpb.Customer {
	// Create the Customer resource
	req := &channelpb.CreateCustomerRequest{
		Parent: accountName,
		Customer: &channelpb.Customer{
			OrgDisplayName: "Acme Corp",
			OrgPostalAddress: &postaladdress.PostalAddress{
				AddressLines: []string{"1800 Amphibious Blvd"},
				PostalCode:   "94045",
				RegionCode:   "US",
			},
			Domain: customerDomain,
			// Distributors need to pass the following value
			// ChannelPartnerId: channelPartnerLinkId
		},
	}
	customer, _ := client.CreateCustomer(ctx, req)
	fmt.Println("=== Created customer with id " + customer.Name)
	fmt.Println(protojson.Format(customer))

	cireq := &channelpb.ProvisionCloudIdentityRequest{
		Customer: customer.Name,
		CloudIdentityInfo: &channelpb.CloudIdentityInfo{
			AlternateEmail: "john.doe@gmail.com",
			LanguageCode:   "en-US",
		},
		User: &channelpb.AdminUser{
			GivenName:  "John",
			FamilyName: "Doe",
			Email:      "admin@" + customerDomain,
		},
	}
	// This endpoint returns a long-running operation.
	op, _ := client.ProvisionCloudIdentity(ctx, cireq)

	// Wait for the long-running operation and get the result.
	customer, _ = op.Wait(ctx)
	fmt.Println("=== Provisioned cloud identity")

	return customer
}

func createEntitlement(ctx context.Context, client *channel.CloudChannelClient,
	customer *channelpb.Customer, selectedOffer *channelpb.Offer) *channelpb.Entitlement {
	// This endpoint returns a long-running operation.
	req := &channelpb.CreateEntitlementRequest{
		Parent: customer.Name,
		Entitlement: &channelpb.Entitlement{
			Offer: selectedOffer.Name,
			// Setting 5 seats for this Annual offer
			Parameters: []*channelpb.Parameter{
				{
					Name: "num_units",
					Value: &channelpb.Value{
						Kind: &channelpb.Value_Int64Value{Int64Value: 5},
					},
				},
			},
			// Setting renewal settings to auto renew
			CommitmentSettings: &channelpb.CommitmentSettings{
				RenewalSettings: &channelpb.RenewalSettings{
					EnableRenewal: true,
					PaymentPlan:   channelpb.PaymentPlan_COMMITMENT,
					PaymentCycle: &channelpb.Period{
						Duration:   1,
						PeriodType: channelpb.PeriodType_YEAR,
					},
				},
			},
			// A string of up to 80 characters.
			// We recommend using an internal transaction ID or
			// identifier for the customer in this field.
			PurchaseOrderId: "A codelab test",
		},
	}
	// This endpoint returns a long-running operation.
	op, _ := client.CreateEntitlement(ctx, req)

	// Wait for the long-running operation and get the result.
	entitlement, _ := op.Wait(ctx)

	fmt.Println("=== Created entitlement")
	fmt.Println(protojson.Format(entitlement))

	return entitlement
}

Java

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Instructions for this codelab can be found on this page
// https://cloud.google.com/channel/docs/codelabs/workspace/provisioning

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.cloud.channel.v1.AdminUser;
import com.google.cloud.channel.v1.CheckCloudIdentityAccountsExistRequest;
import com.google.cloud.channel.v1.CheckCloudIdentityAccountsExistResponse;
import com.google.cloud.channel.v1.CloudChannelServiceClient;
import com.google.cloud.channel.v1.CloudChannelServiceSettings;
import com.google.cloud.channel.v1.CloudIdentityInfo;
import com.google.cloud.channel.v1.CommitmentSettings;
import com.google.cloud.channel.v1.CreateCustomerRequest;
import com.google.cloud.channel.v1.CreateEntitlementRequest;
import com.google.cloud.channel.v1.Customer;
import com.google.cloud.channel.v1.Entitlement;
import com.google.cloud.channel.v1.ListOffersRequest;
import com.google.cloud.channel.v1.Offer;
import com.google.cloud.channel.v1.OperationMetadata;
import com.google.cloud.channel.v1.Parameter;
import com.google.cloud.channel.v1.PaymentPlan;
import com.google.cloud.channel.v1.Period;
import com.google.cloud.channel.v1.PeriodType;
import com.google.cloud.channel.v1.ProvisionCloudIdentityRequest;
import com.google.cloud.channel.v1.RenewalSettings;
import com.google.cloud.channel.v1.Value;
import com.google.gson.Gson;
import com.google.type.PostalAddress;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;

/**
* This is a basic example of provisioning a Google Workspace customer.
*/

public class Codelab {

  /***************** REPLACE WITH YOUR OWN VALUES ********************************/
  public static final String JSON_KEY_FILE = "path/to/json_key_file.json";
  public static final String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com";
  public static final String ACCOUNT_ID = "C012345";
  public static final String CUSTOMER_DOMAIN = "example.com";
  /*******************************************************************************/

  public static final String ACCOUNT_NAME = "accounts/" + ACCOUNT_ID;

  private static CloudChannelServiceClient client;
  private static final Gson gson = new Gson();

  public static void main(String[] args)
      throws Exception, IOException, ExecutionException, InterruptedException {

    // Set up credentials with user impersonation
    FileInputStream jsonKeyFileStream = new FileInputStream(JSON_KEY_FILE);
    GoogleCredentials  credentials = ServiceAccountCredentials.fromStream(jsonKeyFileStream)
                                        .createScoped("https://www.googleapis.com/auth/apps.order")
                                        .createDelegated(RESELLER_ADMIN_USER);
    // Create the API client
    CloudChannelServiceSettings serviceSettings =
        CloudChannelServiceSettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
            .build();
    client = CloudChannelServiceClient.create(serviceSettings);

    Offer selectedOffer = selectOffer();

    checkExists();

    Customer customer = createCustomer();

    Entitlement entitlement = createEntitlement(customer, selectedOffer);

    String adminSDKCustomerId = customer.getCloudIdentityId();
    System.out.println(adminSDKCustomerId);
  }

  private static Offer selectOffer() {
    ListOffersRequest request =
        ListOffersRequest.newBuilder().setParent(ACCOUNT_NAME).build();

    // For the purpose of this codelab, the code lists all offers and selects
    // the first offer for Google Workspace Business Standard on an Annual
    // plan. This is needed because offerIds vary from one account to another,
    // but this is not a recommended model for your production integration
    String sampleSkuName = "Google Workspace Business Standard";
    String samplePlan = "COMMITMENT";

    CloudChannelServiceClient.ListOffersPagedResponse response = client.listOffers(request);
    Offer selectedOffer = Offer.newBuilder().build();
    Iterator<Offer> iterator = response.iterateAll().iterator();
    while (iterator.hasNext()) {
      Offer offer = iterator.next();
      String skuName = offer.getSku().getMarketingInfo().getDisplayName();
      String offerPlan = offer.getPlan().getPaymentPlan().name();
      if (skuName.equals(sampleSkuName) && offerPlan.equals(samplePlan)) {
        selectedOffer = offer;
        break;
      }
    }

    System.out.println("=== Selected offer");
    System.out.println(gson.toJson(selectedOffer));

    return selectedOffer;
  }

  private static void checkExists() throws Exception {
    // Determine if customer already has a cloud identity
    CheckCloudIdentityAccountsExistRequest request =
        CheckCloudIdentityAccountsExistRequest.newBuilder()
            .setParent(ACCOUNT_NAME)
            .setDomain(CUSTOMER_DOMAIN)
            .build();
    CheckCloudIdentityAccountsExistResponse response =
        client.checkCloudIdentityAccountsExist(request);

    if (response.getCloudIdentityAccountsCount() > 0) {
      throw new Exception(
          "Cloud identity already exists. "
          + "Customer must be transferred. "
          + "Out of scope for this codelab");
    }
  }

  private static Customer createCustomer() throws InterruptedException, ExecutionException {
    // Create the Customer resource
    PostalAddress postalAddress =
        PostalAddress.newBuilder()
            .addAddressLines("1800 Amphibious Blvd")
            .setPostalCode("94045")
            .setRegionCode("US")
            .build();

    CreateCustomerRequest request =
        CreateCustomerRequest.newBuilder()
            .setParent(ACCOUNT_NAME)
            .setCustomer(
                Customer.newBuilder()
                    .setOrgDisplayName("Acme Corp")
                    .setOrgPostalAddress(postalAddress)
                    .setDomain(CUSTOMER_DOMAIN)
                    // Distributors need to pass the following field
                    // .setChannelPartnerId(channelPartnerLinkId)
                    .build())
            .build();

    Customer customer = client.createCustomer(request);

    System.out.println("=== Created customer with id " + customer.getName());
    System.out.println(gson.toJson(customer));

    CloudIdentityInfo cloudIdentityInfo =
        CloudIdentityInfo.newBuilder()
            .setAlternateEmail("john.doe@gmail.com")
            .setLanguageCode("en-US")
            .build();

    AdminUser adminUser =
        AdminUser.newBuilder()
            .setGivenName("John")
            .setFamilyName("Doe")
            .setEmail("admin@" + CUSTOMER_DOMAIN)
            .build();

    ProvisionCloudIdentityRequest cloudIdentityRequest =
        ProvisionCloudIdentityRequest.newBuilder()
            .setCustomer(customer.getName())
            .setCloudIdentityInfo(cloudIdentityInfo)
            .setUser(adminUser)
            .build();

    // This call returns a long-running operation.
    OperationFuture<Customer, OperationMetadata> operation =
        client.provisionCloudIdentityAsync(cloudIdentityRequest);

    // Wait for the long-running operation and get the result.
    customer = operation.get();
    System.out.println("=== Provisioned cloud identity");

    return customer;
  }

  private static Entitlement createEntitlement(Customer customer, Offer selectedOffer)
      throws InterruptedException, ExecutionException {
    RenewalSettings renewalSettings =
        RenewalSettings.newBuilder()
            // Setting renewal settings to auto renew
            .setEnableRenewal(true)
            .setPaymentPlan(PaymentPlan.COMMITMENT)
            .setPaymentCycle(
                Period.newBuilder().setPeriodType(PeriodType.YEAR).setDuration(1).build())
            .build();

    CommitmentSettings commitmentSettings =
        CommitmentSettings.newBuilder().setRenewalSettings(renewalSettings).build();

    Entitlement entitlement =
        Entitlement.newBuilder()
            .setOffer(selectedOffer.getName())
            // Setting 5 seats for this Annual offer
            .addParameters(
                Parameter.newBuilder()
                    .setName("num_units")
                    .setValue(Value.newBuilder().setInt64Value(5).build())
                    .build())
            .setCommitmentSettings(commitmentSettings)
            // A string of up to 80 characters.
            // We recommend using an internal transaction ID or
            // identifier for the customer in this field.
            .setPurchaseOrderId("A codelab test")
            .build();

    CreateEntitlementRequest request =
        CreateEntitlementRequest.newBuilder()
            .setParent(customer.getName())
            .setEntitlement(entitlement)
            .build();

    // This call returns a long-running operation.
    OperationFuture<Entitlement, OperationMetadata> operation =
        client.createEntitlementAsync(request);

    // Wait for the long-running operation and get the result.
    entitlement = operation.get();
    System.out.println("=== Created entitlement");
    System.out.println(gson.toJson(entitlement));

    return entitlement;
  }
}

Node.js

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Instructions for this codelab can be found on this page
// https://cloud.google.com/channel/docs/codelabs/workspace/provisioning

const {JWT} = require('google-auth-library');
const {grpc} = require('google-gax');
const {CloudChannelServiceClient} = require('@google-cloud/channel');

// ############## REPLACE WITH YOUR OWN VALUES ####################
const jsonKeyFile = 'path/to/json_key_file.json';
const resellerAdminUser = 'admin@yourresellerdomain.com';
const accountId = 'C012345';
const customerDomain = 'example.com';
// ################################################################
const accountName = `accounts/${accountId}`;

// Set up credentials with user impersonation
const authClient = new JWT({
  keyFile: jsonKeyFile,
  scopes: ['https://www.googleapis.com/auth/apps.order'],
  subject: resellerAdminUser,
});
const sslCreds = grpc.credentials.combineChannelCredentials(
  grpc.credentials.createSsl(),
  grpc.credentials.createFromGoogleCredential(authClient)
);
// Create the API client
const client = new CloudChannelServiceClient({sslCreds});

async function main() {
  const selectedOffer = await selectOffer();

  await checkExists();

  const customer = await createCustomer();

  const entitlement = await createEntitlement(customer, selectedOffer);

  const customerId = customer.cloudIdentityId;
  console.log(customerId);
}

async function selectOffer() {
  const [offers] = await client.listOffers({
    parent: accountName,
  });

  // For the purpose of this codelab, the code lists all offers and selects
  // the first offer for Google Workspace Business Standard on an Annual
  // plan. This is needed because offerIds vary from one account to another,
  // but this is not a recommended model for your production integration
  const selectedOffer = offers.find(o => {
    return (
      o.sku.marketingInfo.displayName ===
        'Google Workspace Business Standard' &&
      o.plan.paymentPlan === 'COMMITMENT'
    );
  });

  console.log('=== Selected offer');
  console.info(selectedOffer);

  return selectedOffer;
}

async function checkExists() {
  // Determine if customer already has a cloud identity
  const [
    cloudIdentityAccounts,
  ] = await client.checkCloudIdentityAccountsExist({
    parent: accountName,
    domain: customerDomain,
  });

  if (cloudIdentityAccounts.length > 0) {
    throw new Error(
      'Cloud identity already exists; ' +
        'customer must be transferred ' +
        '[out-of-scope of this codelab]'
    );
  }
}

async function createCustomer() {
  // Create the Customer resource
  let [customer] = await client.createCustomer({
    parent: accountName,
    customer: {
      orgDisplayName: 'Acme Corp',
      orgPostalAddress: {
        addressLines: ['1800 Amphibious Blvd'],
        postalCode: '94045',
        regionCode: 'US',
      },
      domain: customerDomain,
      // Distributors need to pass the following field
      // channelPartnerId: channelPartnerLinkId
    },
  });
  console.log(`=== Created customer with id ${customer.name}`);
  console.info(customer);

  // This endpoint returns a long-running operation.
  // For other ways to get operation results, see
  // https://github.com/googleapis/gax-nodejs/blob/master/client-libraries.md#long-running-operations
  const [operation] = await client.provisionCloudIdentity({
    customer: customer.name,
    cloudIdentityInfo: {
      alternateEmail: 'john.doe@gmail.com',
      languageCode: 'en-US',
    },
    user: {
      givenName: 'John',
      familyName: 'Doe',
      email: `admin@${customerDomain}`,
    },
  });

  // Wait for the long-running operation and get the result.
  [customer] = await operation.promise();
  console.log('=== Provisioned cloud identity');

  return customer;
}

async function createEntitlement(customer, selectedOffer) {
  // This call returns a long-running operation.
  const [operation] = await client.createEntitlement({
    parent: customer.name,
    entitlement: {
      offer: selectedOffer.name,
      parameters: [
        // Setting 5 seats for this Annual offer
        {
          name: 'num_units',
          value: {
            int64Value: 5,
          },
        },
      ],
      commitmentSettings: {
        // Setting renewal settings to auto renew
        renewalSettings: {
          enableRenewal: true,
          paymentPlan: 'COMMITMENT',
          paymentCycle: {
            duration: 1,
            periodType: 'YEAR',
          },
        },
      },
      // A string of up to 80 characters.
      // We recommend using an internal transaction ID or
      // identifier for the customer in this field.
      purchaseOrderId: 'A codelab test',
    },
  });

  // Wait for the long-running operation and get the result.
  const [entitlement] = await operation.promise();
  console.log('=== Created entitlement');
  console.info(entitlement);

  return entitlement;
}

main().catch(err => {
  console.error(err.message);
  process.exitCode = 1;
});
process.on('unhandledRejection', err => {
  console.error(err.message);
  process.exitCode = 1;
});

PHP

<?php
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Instructions for this codelab can be found on this page
// https://cloud.google.com/channel/docs/codelabs/workspace/provisioning

require 'vendor/autoload.php';

use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Cloud\Channel;

// ############## REPLACE WITH YOUR OWN VALUES ####################
$JSON_KEY_FILE = 'path/to/json_key_file.json';
$RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com';
$ACCOUNT_ID = 'C012345';
$CUSTOMER_DOMAIN = 'example.com';
// ################################################################

$ACCOUNT_NAME = 'accounts/' . $ACCOUNT_ID;

// Set up credentials with user impersonation
$credentials = new ServiceAccountCredentials(
  'https://www.googleapis.com/auth/apps.order', /* $scope */
  $JSON_KEY_FILE, /* $keyFile */
  $RESELLER_ADMIN_USER /* $sub */
);

// Create the API client
$client = new Channel\V1\CloudChannelServiceClient([
  'credentials' => $credentials
]);

$selectedOffer = selectOffer();

checkExists();

$customer = createCustomer();

$entitlement = createEntitlement($customer, $selectedOffer);

$customerId = $customer->getCloudIdentityId();
print $customerId . PHP_EOL;

function selectOffer() {
  global $client, $ACCOUNT_NAME;

  $offers = $client->listOffers($ACCOUNT_NAME /* parent */);

  // For the purpose of this codelab, the code lists all offers and selects
  // the first offer for Google Workspace Business Standard on an Annual
  // plan. This is needed because offerIds vary from one account to another,
  // but this is not a recommended model for your production integration
  $sampleSku = 'Google Workspace Business Standard';
  $samplePlan = Channel\V1\PaymentPlan::COMMITMENT;
  foreach ($offers as $offer) {
    if ($offer->getSku()->getMarketingInfo()->getDisplayName() == $sampleSku
    && $offer->getPlan()->getPaymentPlan() == $samplePlan) {
      $selectedOffer = $offer;
      break;
    }
  }

  print '=== Selected offer' . PHP_EOL;
  print $selectedOffer->serializeToJsonString() . PHP_EOL;

  return $selectedOffer;
}

function checkExists () {
  global $client, $ACCOUNT_NAME, $CUSTOMER_DOMAIN;

  // Determine if customer already has a cloud identity
  $response = $client->checkCloudIdentityAccountsExist(
    $ACCOUNT_NAME /* parent */,
    $CUSTOMER_DOMAIN /* domain */
  );

  if (count($response->getCloudIdentityAccounts()) > 0) {
    throw new Error('Cloud identity already exists; \
      customer must be transferred \
      [out-of-scope of this codelab]'
    );
  }
}

function createCustomer() {
  global $client, $ACCOUNT_NAME, $CUSTOMER_DOMAIN;

  // Create the Customer resource
  $customer = $client->createCustomer(
    $ACCOUNT_NAME  /* parent */,
    new Channel\V1\Customer([
      'org_display_name' => 'Acme Corp',
      'org_postal_address' => new Google\Type\PostalAddress([
        'address_lines' => ['1800 Amphibious Blvd'],
        'postal_code' => '94045',
        'region_code' => 'US',
      ]),
      'domain' => $CUSTOMER_DOMAIN,
      // Distributors need to pass the following field
      // 'channel_partner_id' => $channelPartnerLinkId
    ])
  );

  print '=== Created customer with id ' . $customer->getName() . PHP_EOL;
  print $customer->serializeToJsonString() . PHP_EOL;

  // This endpoint returns a long-running operation.
  $operation = $client->provisionCloudIdentity(
    $customer->getName() /* customer */,
    [
      'cloudIdentityInfo' => new Channel\V1\CloudIdentityInfo([
        'alternate_email' => 'john.doe@gmail.com',
        'language_code' => 'en-US',
      ]),
      'user' => new Channel\V1\AdminUser([
        'given_name' => 'John',
        'family_name' => 'Doe',
        'email' => 'admin@' . $CUSTOMER_DOMAIN,
      ]),
    ]
  );

  // Wait for the long-running operation and get the result.
  $operation->pollUntilComplete();
  $customer = $operation->getResult();
  print '=== Provisioned cloud identity' . PHP_EOL;

  return $customer;
}

function createEntitlement($customer, $selectedOffer) {
  global $client;

  // This call returns a long-running operation.
  $operation = $client->createEntitlement(
    $customer->getName() /* parent */,
    new Channel\V1\Entitlement([
      'offer' => $selectedOffer->getName(),
      'parameters' => [
        new Channel\V1\Parameter([
          // Setting 5 seats for this Annual offer
          'name' => 'num_units',
          'value' => new Channel\V1\Value([
            'int64_value' => 5,
          ])
        ]),
      ],
      'commitment_settings' => new Channel\V1\CommitmentSettings([
        // Setting renewal settings to auto renew
        'renewal_settings' => new Channel\V1\RenewalSettings([
          'enable_renewal' => true,
          'payment_plan' => Channel\V1\PaymentPlan::COMMITMENT,
          'payment_cycle' => new Channel\V1\Period([
            'duration' => 1,
            'period_type' => Channel\V1\PeriodType::YEAR,
          ]),
        ]),
      ]),
      // A string of up to 80 characters.
      // We recommend using an internal transaction ID or
      // identifier for the customer in this field.
      'purchase_order_id' => 'A codelab test'
    ])
  );

  // Wait for the long-running operation and get the result.
  $operation->pollUntilComplete();
  $entitlement = $operation->getResult();
  print '=== Created entitlement' . PHP_EOL;
  print $entitlement->serializeToJsonString() . PHP_EOL;

  return $entitlement;
}

Python

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Google Workspace Provisioning codelab.

Instructions for this codelab can be found on this page:
https://cloud.google.com/channel/docs/codelabs/workspace/provisioning
"""

from google.cloud import channel
from google.oauth2 import service_account

############## REPLACE WITH YOUR OWN VALUES ####################
JSON_KEY_FILE = "path/to/json_key_file.json"
RESELLER_ADMIN_USER = "admin@yourresellerdomain.com"
ACCOUNT_ID = "C012345"
CUSTOMER_DOMAIN = "example.com"
################################################################

ACCOUNT_NAME = "accounts/" + ACCOUNT_ID

# Set up credentials with user impersonation
credentials = service_account.Credentials.from_service_account_file(
    JSON_KEY_FILE, scopes=["https://www.googleapis.com/auth/apps.order"])
credentials_delegated = credentials.with_subject(RESELLER_ADMIN_USER)

# Create the API client
client = channel.CloudChannelServiceClient(credentials=credentials_delegated)

def main():
  offer = select_offer()

  check_exists()

  customer = create_customer()

  _ = create_entitlement(customer, offer)

  customer_id = customer.cloud_identity_id
  print(customer_id)

def select_offer():
  """Selects a Workspace offer.

  Returns:
    A Channel API Offer for Workspace
  """
  request = channel.ListOffersRequest(parent=ACCOUNT_NAME)
  offers = client.list_offers(request)

  # For the purpose of this codelab, the code lists all offers and selects
  # the first offer for Google Workspace Business Standard on an Annual
  # plan. This is needed because offerIds vary from one account to another,
  # but this is not a recommended model for your production integration
  sample_offer = "Google Workspace Business Standard"
  sample_plan = "PaymentPlan.COMMITMENT"
  selected_offer = None
  for offer in offers:
    if offer.sku.marketing_info.display_name == sample_offer and \
        str(offer.plan.payment_plan) == sample_plan:
      selected_offer = offer
      break

  print("=== Selected offer")
  print(selected_offer)

  return selected_offer

def check_exists():
  """Determine if customer already has a cloud identity.

  Raises:
    Exception: if the domain is already in use
  """
  # Determine if customer already has a cloud identity
  request = channel.CheckCloudIdentityAccountsExistRequest(
      parent=ACCOUNT_NAME, domain=CUSTOMER_DOMAIN)

  response = client.check_cloud_identity_accounts_exist(request)

  if response.cloud_identity_accounts:
    raise Exception(
        "Cloud identity already exists. Customer must be transferred." +
        "Out of scope for this codelab")

def create_customer():
  """Create the Customer resource, with a cloud identity.

  Returns:
    The created Channel API Customer
  """
  # Create the Customer resource
  request = channel.CreateCustomerRequest(
      parent=ACCOUNT_NAME,
      customer={
          "org_display_name": "Acme Corp",
          "domain": CUSTOMER_DOMAIN,
          "org_postal_address": {
              "address_lines": ["1800 Amphibious Blvd"],
              "postal_code": "94045",
              "region_code": "US"
          }
      })
  # Distributors need to also pass the following field for the `customer`
  # "channel_partner_id": channel_partner_link_id

  customer = client.create_customer(request)

  print("=== Created customer with id ", customer.name)
  print(customer)

  cloud_identity_info = channel.CloudIdentityInfo(
      alternate_email="john.doe@gmail.com", language_code="en-US")

  admin_user = channel.AdminUser(
      given_name="John", family_name="Doe", email="admin@" + CUSTOMER_DOMAIN)

  cloud_identity_request = channel.ProvisionCloudIdentityRequest(
      customer=customer.name,
      cloud_identity_info=cloud_identity_info,
      user=admin_user)

  # This call returns a long-running operation.
  operation = client.provision_cloud_identity(cloud_identity_request)

  # Wait for the long-running operation and get the result.
  customer = operation.result()

  print("=== Provisioned cloud identity")

  return customer

def create_entitlement(customer, selected_offer):
  """Create the Entitlement.

  Args:
    customer: a Customer resource
    selected_offer: an Offer

  Returns:
    The created Channel API Entitlement
  """
  request = channel.CreateEntitlementRequest(
      parent=customer.name,
      entitlement={
          "offer": selected_offer.name,
          # Setting 5 seats for this Annual offer
          "parameters": [{
              "name": "num_units",
              "value": {
                  "int64_value": 5
              }
          }],
          "commitment_settings": {
              "renewal_settings": {
                  # Setting renewal settings to auto renew
                  "enable_renewal": True,
                  "payment_plan": "COMMITMENT",
                  "payment_cycle": {
                      "period_type": "YEAR",
                      "duration": 1
                  }
              }
          },
          # A string of up to 80 characters.
          # We recommend an internal transaction ID or
          # identifier for this customer in this field.
          "purchase_order_id": "A codelab test"
      })

  # This call returns a long-running operation.
  operation = client.create_entitlement(request)

  # Wait for the long-running operation and get the result.
  entitlement = operation.result()

  print("=== Created entitlement")
  print(entitlement)

  return entitlement

if __name__ == "__main__":
  main()

Ruby

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# Instructions for this codelab can be found on this page
# https://cloud.google.com/channel/docs/codelabs/workspace/provisioning

require 'google-cloud-channel'

################## REPLACE WITH YOUR OWN VALUES ################################
JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'
RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'
ACCOUNT_ID = 'C012345'
CUSTOMER_DOMAIN = 'example.com'
################################################################################

ACCOUNT_NAME = "accounts/#{ACCOUNT_ID}"

# Set up credentials with user impersonation
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open(JSON_PRIVATE_KEY_FILE),
  scope: 'https://www.googleapis.com/auth/apps.order'
)
credentials.sub = RESELLER_ADMIN_USER

# Create the API client
CLIENT = Google::Cloud::Channel::cloud_channel_service do |config|
  config.credentials = credentials
end

def main
  offer = select_offer
  check_exists
  customer = create_customer
  create_entitlement(customer, offer)
  customer_id = customer.cloud_identity_id
  puts(customer_id)
end

def select_offer
  # For the purpose of this codelab, the code lists all offers and selects
  # the first offer for Google Workspace Business Standard on an Annual
  # plan. This is needed because offerIds vary from one account to another,
  # but this is not a recommended model for your production integration

  request = Google::Cloud::Channel::V1::ListOffersRequest.new({ parent: ACCOUNT_NAME })
  offers = CLIENT.list_offers(request)
  sample_offer = 'Google Workspace Business Standard'
  sample_plan = :COMMITMENT

  offer = offers.detect { |offer| offer.sku.marketing_info.display_name == sample_offer
    && offer.plan.payment_plan == sample_plan }
  puts("=== Selected offer")
  puts(offer.inspect)
  offer
end

def check_exists
  # Determine if customer already has a cloud identity
  request = Google::Cloud::Channel::V1::CheckCloudIdentityAccountsExistRequest
  .new({ parent: ACCOUNT_NAME, domain: CUSTOMER_DOMAIN })
  response = CLIENT.check_cloud_identity_accounts_exist(request)

  if response.cloud_identity_accounts.count > 0
    raise 'Cloud identity already exists. Customer must be transferred.'\
      'Out of scope for this codelab'
  end
end

def create_customer
  # Create the Customer resource

  request = Google::Cloud::Channel::V1::CreateCustomerRequest.new(
    parent: ACCOUNT_NAME,
    customer: {
      'org_display_name': 'Acme Corp',
      'domain': CUSTOMER_DOMAIN,
      'org_postal_address': {
        'address_lines': ['1800 Amphibious Blvd'],
        'postal_code': '94045',
        'region_code': 'US'
      }
    })

  # Distributors need to also pass the following field for the `customer`
  # "channel_partner_id": channel_partner_link_id

  customer = CLIENT.create_customer(request)

  puts("=== Created customer with id " + customer.name)
  puts(customer.inspect)

  cloud_identity_info = Google::Cloud::Channel::V1::CloudIdentityInfo.new(
    alternate_email: 'john.doe@gmail.com', language_code: 'en-US'
  )

  admin_user = Google::Cloud::Channel::V1::AdminUser.new(
    given_name: 'John', family_name: 'Doe', email: "admin@#{CUSTOMER_DOMAIN}"
  )

  cloud_identity_request = Google::Cloud::Channel::V1::ProvisionCloudIdentityRequest.new(
    customer: customer.name,
    cloud_identity_info: cloud_identity_info,
    user: admin_user
  )

  # This call returns a long-running operation.
  operation = CLIENT.provision_cloud_identity(cloud_identity_request)

  # Wait for the long-running operation and get the result.
  CLIENT.operations_client.wait_operation(Google::Longrunning::WaitOperationRequest
    .new({ name: operation.name }))
  operation = CLIENT.operations_client.get_operation(Google::Longrunning::GetOperationRequest
    .new({ name: operation.name }))
  customer = operation.response
  puts("=== Provisioned cloud identity")

  customer
end

def create_entitlement(customer, selected_offer)
  request = Google::Cloud::Channel::V1::CreateEntitlementRequest.new(
    parent: customer.name,
    entitlement: {
      offer: selected_offer.name,
      # Setting 5 seats for this Annual offer
      parameters: [{
                     name: 'num_units',
                     value: {
                       int64_value: 5
                     }
                   }],
      commitment_settings: {
        renewal_settings: {
          # Setting renewal settings to auto renew
          enable_renewal: true,
          payment_plan: 'COMMITMENT',
          payment_cycle: {
            period_type: 'YEAR',
            duration: 1
          }
        }
      },
      # A string of up to 80 characters.
      # We recommend an internal transaction ID or
      # identifier for this customer in this field.
      purchase_order_id: 'A codelab test'
    })

  # This call returns a long-running operation.
  operation = CLIENT.create_entitlement(request)

  # Wait for the long-running operation and get the result.
  CLIENT.operations_client.wait_operation(Google::Longrunning::WaitOperationRequest
    .new({ name: operation.name }))
  operation = CLIENT.operations_client.get_operation(Google::Longrunning::GetOperationRequest
    .new({ name: operation.name }))
  entitlement = operation.response

  puts("=== Created entitlement")
  puts(entitlement)

  entitlement
end

main