本教學課程將說明如何使用經銷商 API 為客戶佈建服務。
為客戶提供適當的服務需要完成多個相互依賴的步驟,這些步驟橫跨 Google Workspace 平台中的多個 API。
上圖顯示在各個步驟中用於佈建客戶的 API:
- 使用 Site Verification API 放置網域驗證權杖。
- 使用 Reseller API 建立客戶。
- 使用 Directory API 建立第一位使用者,並將該使用者設為管理員。
- 使用 Reseller API 建立訂閱。
- 使用網站驗證 API 驗證網域。
必要條件
- Google 經銷商網域執行個體。
- 已全面履行 Google Workspace 合作夥伴協議。
- Google 帳戶。
- 在 Partner Sales Console 中接受《服務條款》。
- 下載不同語言的用戶端程式庫。
設定環境
如要完成本教學課程,請設定環境。
啟用 API
使用 Google API 前,您必須先在 Google Cloud 專案中啟用這些 API。您可以在單一 Google Cloud 專案中啟用一或多個 API。在 Google Cloud 控制台中啟用 Reseller API、Site Verification API 和 Admin SDK API。
建立服務帳戶
服務帳戶是一種特殊的帳戶,由應用程式 (而非使用者) 所使用。您可以使用服務帳戶,透過機器人帳戶存取資料或執行動作,也可以代表 Google Workspace 或 Cloud Identity 使用者存取資料。詳情請參閱「瞭解服務帳戶」一文。Google Cloud 控制台
- 在 Google Cloud 控制台中,依序前往「Menu」(選單) >「IAM & Admin」(IAM 與管理) >「Service Accounts」(服務帳戶)。
- 按一下「建立服務帳戶」。
- 填寫服務帳戶詳細資料,然後按一下「建立並繼續」。
- 選用:將角色指派給服務帳戶,授予 Google Cloud 專案資源的存取權。詳情請參閱「授予、變更及撤銷資源的存取權」。
- 按一下「繼續」。
- 選用:輸入可管理這個服務帳戶並執行相關動作的使用者或群組。詳情請參閱「管理服務帳戶模擬功能」。
- 按一下「完成」,請記下服務帳戶的電子郵件地址。
gcloud CLI
- 建立服務帳戶:
gcloud iam service-accounts create
SERVICE_ACCOUNT_NAME
\ --display-name="SERVICE_ACCOUNT_NAME
" - 選用:將角色指派給服務帳戶,授予 Google Cloud 專案資源的存取權。詳情請參閱「授予、變更及撤銷資源的存取權」。
為服務帳戶建立憑證
您必須以公開/私密金鑰組的形式取得憑證。程式碼會使用這些憑證,在應用程式中授權服務帳戶的動作。- 在 Google Cloud 控制台中,依序前往「Menu」(選單) >「IAM & Admin」(IAM 與管理) >「Service Accounts」(服務帳戶)。
- 選取服務帳戶。
- 依序點選「金鑰」>「新增金鑰」>「建立新的金鑰」。
- 選取「JSON」,然後按一下「建立」。
系統會產生新的公開/私密金鑰組,並下載至您的電腦中做為新檔案。將下載的 JSON 檔案儲存為工作目錄中的
credentials.json
。這個檔案是這組金鑰的唯一副本。如要瞭解如何安全儲存金鑰,請參閱「管理服務帳戶金鑰」。 - 按一下「關閉」。
為服務帳戶設定全網域委派
如要代表 Google Workspace 機構中的使用者呼叫 API,您的服務帳戶必須由超級管理員帳戶在 Google Workspace 管理控制台中授予網域層級委派權限。詳情請參閱「將網域層級權限委派給服務帳戶」。- 在 Google Cloud 控制台中,依序前往「Menu」(選單) >「IAM & Admin」(IAM 與管理) >「Service Accounts」(服務帳戶)。
- 選取服務帳戶。
- 按一下 [顯示進階設定]。
- 在「全網域委派」下方,找出服務帳戶的「用戶端 ID」。按一下「複製」圖示 ,將用戶端 ID 值複製到剪貼簿。
如果您有相關 Google Workspace 帳戶的超級管理員存取權,請按一下「查看 Google Workspace 管理控制台」,然後使用超級管理員使用者帳戶登入,並繼續按照這些步驟操作。
如果您沒有相關 Google Workspace 帳戶的超級管理員存取權,請與該帳戶的超級管理員聯絡,並傳送服務帳戶的客戶端 ID 和 OAuth 範圍清單給對方,讓對方在管理控制台中完成下列步驟。
- 在 Google 管理控制台中,依序點選「選單」圖示 >「安全性」 >「存取權與資料控管」 >「API 控制項」。
- 按一下「管理全網域委派設定」。
- 點選「新增」。
- 在「用戶端 ID」欄位中,貼上先前複製的用戶端 ID。
- 在「OAuth 範圍」欄位中,輸入應用程式所需範圍的清單,並以半形逗號分隔。這與您在設定 OAuth 同意畫面時定義的範圍相同。
- 按一下「授權」。
使用已驗證的憑證建立服務物件
如要開始使用任何 Google API,您必須先在應用程式中設定驗證和憑證。Google 用戶端程式庫會代您處理這項作業。所有程式庫都有建立憑證物件時使用的模式,您可以授予所有 API 的存取權,並將這些權限傳遞至各項服務。應用程式通常應具備一組憑證,並且只使用一個雲端專案來處理所有 Google API 互動。
請使用建立服務帳戶時產生的 JSON 金鑰檔案。
Python
import sys from apiclient.discovery import build from apiclient.http import HttpError from oauth2client.service_account import ServiceAccountCredentials ############## REPLACE WITH YOUR OWN VALUES #################### JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json' RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com' CUSTOMER_DOMAIN = 'example.com' CUSTOMER_SITE = 'https://www.example.com' ################################################################ # Full List of scopes: # https://developers.google.com/identity/protocols/googlescopes OAUTH2_SCOPES = [ 'https://reseller.googleapis.com/auth/apps.order', 'https://reseller.googleapis.com/auth/siteverification', 'https://reseller.googleapis.com/auth/admin.directory.user', ] credentials = ServiceAccountCredentials.from_json_keyfile_name( JSON_PRIVATE_KEY_FILE, OAUTH2_SCOPES).create_delegated(RESELLER_ADMIN_USER) reseller_service = build( serviceName='reseller', version='v1', credentials=credentials) directory_service = build( serviceName='admin', version='directory_v1', credentials=credentials) verification_service = build( serviceName='siteVerification', version='v1', credentials=credentials)
Java
// OAuth2 and HTTP import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.HttpResponseException; import com.google.api.client.json.jackson2.JacksonFactory; // Directory API import com.google.api.services.admin.directory.Directory; import com.google.api.services.admin.directory.DirectoryScopes; import com.google.api.services.admin.directory.model.User; import com.google.api.services.admin.directory.model.UserMakeAdmin; import com.google.api.services.admin.directory.model.UserName; // Reseller API import com.google.api.services.reseller.Reseller; import com.google.api.services.reseller.ResellerScopes; import com.google.api.services.reseller.model.Address; import com.google.api.services.reseller.model.Customer; import com.google.api.services.reseller.model.RenewalSettings; import com.google.api.services.reseller.model.Seats; import com.google.api.services.reseller.model.Subscription; // Site Verification API import com.google.api.services.siteVerification.SiteVerification; import com.google.api.services.siteVerification.SiteVerificationScopes; import com.google.api.services.siteVerification.model.SiteVerificationWebResourceGettokenRequest; import com.google.api.services.siteVerification.model.SiteVerificationWebResourceGettokenResponse; import com.google.api.services.siteVerification.model.SiteVerificationWebResourceResource; // Java library imports import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.List; /** * This is a basic example of provisioning a Google Workspace customer. */ public class CodelabExample { // Full List of scopes: // https://developers.google.com/identity/protocols/googlescopes private static final List<String> OAUTH2_SCOPES = Arrays.asList( ResellerScopes.APPS_ORDER, SiteVerificationScopes.SITEVERIFICATION, DirectoryScopes.ADMIN_DIRECTORY_USER ); /***************** REPLACE WITH YOUR OWN VALUES ********************************/ public static final String JSON_PRIVATE_KEY_FILE = "path/to/json_key_file.json"; public static final String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com"; public static final String CUSTOMER_DOMAIN = "example.com"; public static final String CUSTOMER_SITE = "https://www.example.com/"; /*******************************************************************************/ public static void main(String[] args) throws IOException, GeneralSecurityException, FileNotFoundException { // Instantiate services with authenticated credentials GoogleCredential jsonCredentials = GoogleCredential .fromStream(new FileInputStream(JSON_PRIVATE_KEY_FILE)); GoogleCredential credentials = new GoogleCredential.Builder() .setTransport(GoogleNetHttpTransport.newTrustedTransport()) .setJsonFactory(JacksonFactory.getDefaultInstance()) .setServiceAccountScopes(OAUTH2_SCOPES) .setServiceAccountUser(RESELLER_ADMIN_USER) .setServiceAccountPrivateKey(jsonCredentials.getServiceAccountPrivateKey()) .setServiceAccountId(jsonCredentials.getServiceAccountId()) .build(); Reseller resellerService = new Reseller.Builder( credentials.getTransport(), credentials.getJsonFactory(), credentials).setApplicationName("Google Workspace Creator").build(); Directory directoryService = new Directory.Builder( credentials.getTransport(), credentials.getJsonFactory(), credentials).setApplicationName("Google Workspace Creator").build(); SiteVerification verificationService = new SiteVerification.Builder( credentials.getTransport(), credentials.getJsonFactory(), credentials).setApplicationName("Google Workspace Creator").build();
C#
// OAuth2 and HTTP using Google.Apis.Auth.OAuth2; using Google.Apis.Services; // Reseller API using Google.Apis.Reseller.v1; using Google.Apis.Reseller.v1.Data; // Directory API using Google.Apis.Admin.Directory.directory_v1; using User = Google.Apis.Admin.Directory.directory_v1.Data.User; using UserName = Google.Apis.Admin.Directory.directory_v1.Data.UserName; using UserMakeAdmin = Google.Apis.Admin.Directory.directory_v1.Data.UserMakeAdmin; //Site Verification API using Google.Apis.SiteVerification.v1; using Google.Apis.SiteVerification.v1.Data; // System imports using System; using System.IO; class CodelabExample { // Full List of scopes: // https://developers.google.com/identity/protocols/googlescopes static string[] OAUTH2_SCOPES = { ResellerService.Scope.AppsOrder, DirectoryService.Scope.AdminDirectoryUser, SiteVerificationService.Scope.Siteverification }; /***************** REPLACE WITH YOUR OWN VALUES ********************************/ public static String JSON_PRIVATE_KEY_FILE = "path/to/json_key_file.json"; public static String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com"; public static String CUSTOMER_DOMAIN = "example.com"; public static String CUSTOMER_SITE = "https://www.example.com/"; /*******************************************************************************/ static void Main(string[] args) { GoogleCredential credential; using (var stream = new FileStream(JSON_PRIVATE_KEY_FILE, FileMode.Open, FileAccess.Read)) { credential = GoogleCredential .FromStream(stream) .CreateScoped(OAUTH2_SCOPES) .CreateWithUser(RESELLER_ADMIN_USER); } var resellerService = new ResellerService(new BaseClientService.Initializer() { HttpClientInitializer = credential, }); var directoryService = new DirectoryService(new BaseClientService.Initializer() { HttpClientInitializer = credential, }); var verificationService = new SiteVerificationService(new BaseClientService.Initializer() { HttpClientInitializer = credential, });
PHP
// https://developers.google.com/api-client-library/php/ require_once 'vendor/autoload.php'; // Full List of scopes: // https://developers.google.com/identity/protocols/googlescopes $OAUTH2_SCOPES = [ Google_Service_Reseller::APPS_ORDER, Google_Service_SiteVerification::SITEVERIFICATION, Google_Service_Directory::ADMIN_DIRECTORY_USER, ]; ######### REPLACE WITH YOUR OWN VALUES ############### $JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'; $RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'; $CUSTOMER_DOMAIN = 'example.com'; $CUSTOMER_SITE = 'https://www.example.com/'; ###################################################### $client = new Google_Client(); $client->setAuthConfig($JSON_PRIVATE_KEY_FILE); $client->setSubject($RESELLER_ADMIN_USER); $client->setScopes($OAUTH2_SCOPES); $resellerService = new Google_Service_Reseller($client); $directoryService = new Google_Service_Directory($client); $verificationService = new Google_Service_SiteVerification($client);
Ruby
require 'googleauth' require 'google/apis/reseller_v1' require 'google/apis/site_verification_v1' require 'google/apis/admin_directory_v1' # Full List of scopes: # https://developers.google.com/identity/protocols/googlescopes OAUTH2_SCOPES = [ 'https://reseller.googleapis.com/auth/apps.order', 'https://reseller.googleapis.com/auth/admin.directory.user', 'https://reseller.googleapis.com/auth/siteverification', ] ####### REPLACE WITH YOUR OWN VALUES ############### JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json' RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com' CUSTOMER_DOMAIN = 'example.com' CUSTOMER_SITE = 'https://www.example.com/' #################################################### credentials = Google::Auth::ServiceAccountCredentials.make_creds( json_key_io: File.open(JSON_PRIVATE_KEY_FILE), scope: OAUTH2_SCOPES) credentials.sub = RESELLER_ADMIN_USER Google::Apis::RequestOptions.default.authorization = credentials reseller_service = Google::Apis::ResellerV1::ResellerService.new directory_service = Google::Apis::AdminDirectoryV1::DirectoryService.new verification_service = Google::Apis::SiteVerificationV1::SiteVerificationService.new
Node.js
// NOTE: This script needs googleapis 28.0.0 or later as it uses promises const {google} = require('googleapis'); // ############## REPLACE WITH YOUR OWN VALUES #################### const JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'; const RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'; const CUSTOMER_DOMAIN = 'example.com'; const CUSTOMER_SITE = 'https://www.example.com/'; // ################################################################ // Full List of scopes: https://developers.google.com/identity/protocols/googlescopes const OAUTH2_SCOPES = [ 'https://reseller.googleapis.com/auth/apps.order', 'https://reseller.googleapis.com/auth/siteverification', 'https://reseller.googleapis.com/auth/admin.directory.user', ]; const authJWT = new google.auth.JWT({ keyFile: JSON_PRIVATE_KEY_FILE, scopes: OAUTH2_SCOPES, subject: RESELLER_ADMIN_USER, }); const resellerService = google.reseller({version: 'v1', auth: authJWT}); const directoryService = google.admin({version: 'directory_v1', auth: authJWT}); const verificationService = google.siteVerification({version: 'v1', auth: authJWT});
開始網域驗證程序
這個步驟為選用步驟,但如果您能夠驗證客戶的網域,建議您進行驗證。您在教學課程結束時驗證網域,這個步驟就會完成。
如果您未驗證客戶的網域,則客戶會受到下列限制:
- 他們只能存取管理控制台,並在該處按照手動網域驗證程序完成驗證。
- 可能會在建立後 21 天遭到停權。
如要擷取網站驗證權杖,請按照下列步驟操作:
如要擷取網站驗證權杖,請使用 網站驗證 API。您無法驗證網域是否先前已通過驗證,但可以多次驗證網站,不會有任何問題。視您是要驗證
INET_DOMAIN
還是SITE
類型而定,verificationMethod
參數會有所不同。請選擇下列其中一項:針對
INET_DOMAIN
類型,請使用下列其中一個verificationMethod
參數:DNS_TXT
DNS_CNAME
以下權杖擷取範例使用
INET_DOMAIN
類型:Python
# Retrieve the site verification token and place it according to: # https://developers.google.com/site-verification/v1/getting_started#tokens response = verification_service.webResource().getToken( body={ 'site': { 'type': 'INET_DOMAIN', 'identifier': CUSTOMER_DOMAIN }, 'verificationMethod': 'DNS_TXT' }).execute() print(response)
Java
// Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens SiteVerificationWebResourceGettokenRequest.Site getTokenSite = new SiteVerificationWebResourceGettokenRequest.Site() .setType("INET_DOMAIN") .setIdentifier(CUSTOMER_DOMAIN); SiteVerificationWebResourceGettokenRequest request = new SiteVerificationWebResourceGettokenRequest() .setVerificationMethod("DNS_TXT") .setSite(getTokenSite); SiteVerificationWebResourceGettokenResponse getTokenResponse = verificationService.webResource().getToken(request).execute(); System.out.println("Site Verification Token: " + getTokenResponse.getToken());
C#
// Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens SiteVerificationWebResourceGettokenRequest.SiteData getTokenSite = new SiteVerificationWebResourceGettokenRequest.SiteData() { Type = "INET_DOMAIN", Identifier = CUSTOMER_DOMAIN }; SiteVerificationWebResourceGettokenRequest request = new SiteVerificationWebResourceGettokenRequest() { VerificationMethod = "DNS_TXT", Site = getTokenSite }; SiteVerificationWebResourceGettokenResponse getTokenResponse = verificationService.WebResource.GetToken(request).Execute(); Console.WriteLine("Site Verification Token: {0}", getTokenResponse.Token);
PHP
// Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens $body = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest([ 'verificationMethod' => 'DNS_TXT', 'site' => [ 'type' => 'INET_DOMAIN', 'identifier' => $CUSTOMER_DOMAIN ] ]); $response = $verificationService->webResource->getToken($body); print_r ($response);
Ruby
# Retrieve the site verification token and place it according to: # https://developers.google.com/site-verification/v1/getting_started#tokens request = Google::Apis::SiteVerificationV1::GetWebResourceTokenRequest.new( site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN }, verification_method: 'DNS_TXT' ) response = verification_service.get_web_resource_token(request) puts response.inspect
Node.js
/** * Retrieve the site verification token and place it according to: * https://developers.google.com/site-verification/v1/getting_started#tokens */ const getTokenPromise = verificationService.webResource.getToken({ requestBody: { site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN, }, verificationMethod: 'DNS_TXT', } }).then(({data}) => { console.log(data); return data; });
針對
SITE
類型,請使用下列其中一個verificationMethod
參數:FILE
META
以下權杖擷取範例使用
SITE
類型搭配FILE
驗證方法。使用SITE
驗證類型時,您必須在 ID 前方加上http://
或https://
。Python
# Retrieve the site verification token and place it according to: # https://developers.google.com/site-verification/v1/getting_started#tokens response = verification_service.webResource().getToken( body={ 'site': { 'type': 'SITE', 'identifier': CUSTOMER_SITE }, 'verificationMethod': 'FILE' }).execute() print(response)
Java
// Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens SiteVerificationWebResourceGettokenRequest.Site getTokenSite = new SiteVerificationWebResourceGettokenRequest.Site() .setType("SITE") .setIdentifier(CUSTOMER_SITE); SiteVerificationWebResourceGettokenRequest request = new SiteVerificationWebResourceGettokenRequest() .setVerificationMethod("FILE") .setSite(getTokenSite); SiteVerificationWebResourceGettokenResponse getTokenResponse = verificationService.webResource().getToken(request).execute(); System.out.println("Site Verification Token: " + getTokenResponse.getToken());
C#
// Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens SiteVerificationWebResourceGettokenRequest.SiteData getTokenSite = new SiteVerificationWebResourceGettokenRequest.SiteData() { Type = "SITE", Identifier = CUSTOMER_SITE }; SiteVerificationWebResourceGettokenRequest request = new SiteVerificationWebResourceGettokenRequest() { VerificationMethod = "FILE", Site = getTokenSite }; SiteVerificationWebResourceGettokenResponse getTokenResponse = verificationService.WebResource.GetToken(request).Execute(); Console.WriteLine("Site Verification Token: {0}", getTokenResponse.Token);
PHP
// Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens $body = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest([ 'verificationMethod' => 'FILE', 'site' => [ 'type' => 'SITE', 'identifier' => $CUSTOMER_DOMAIN ] ]); $response = $verificationService->webResource->getToken($body); print_r($response);
Ruby
# Retrieve the site verification token and place it according to: # https://developers.google.com/site-verification/v1/getting_started#tokens request = Google::Apis::SiteVerificationV1::GetWebResourceTokenRequest.new( site: { type: 'SITE', identifier: CUSTOMER_SITE }, verification_method: 'FILE' ) response = verification_service.get_web_resource_token(request) puts response.inspect
Node.js
/** * Retrieve the site verification token and place it according to: * https://developers.google.com/site-verification/v1/getting_started#tokens */ const getTokenPromise = verificationService.webResource.getToken({ requestBody: { site: { type: 'SITE', identifier: CUSTOMER_SITE, }, verificationMethod: 'FILE', } }).then(({data}) => { console.log(data); return data; });
使用 Reseller API 建立客戶
使用 Customers.Get 方法,判斷客戶是否已在 Google Workspace 中:
Python
# Determine if customer domain already has Google Workspace try: response = reseller_service.customers().get( customerId=CUSTOMER_DOMAIN).execute() print('Customer already exists if call succeeds') sys.exit() except HttpError as error: if int(error.resp['status']) == 404: print('Domain available for Google Workspace creation') else: raise
Java
// Determine if customer domain already has Google Workspace try { resellerService.customers().get(CUSTOMER_DOMAIN).execute(); System.out.println("Customer already exists if call succeeds"); System.exit(0); } catch (HttpResponseException e) { if (e.getStatusCode() == 404) { System.out.println("Domain available for Google Workspace creation"); } else { throw e; } }
C#
// Determine if customer domain already has Google Workspace try { resellerService.Customers.Get(CUSTOMER_DOMAIN).Execute(); Console.WriteLine("Customer already exists if call succeeds"); Environment.Exit(0); } catch (Google.GoogleApiException e) { if (e.Error.Code == 404) { Console.WriteLine("Domain available for Google Workspace creation"); } else throw e; }
PHP
// Determine if customer domain already has Google Workspace try { $response = $resellerService->customers->get($CUSTOMER_DOMAIN); exit('Customer already exists if call succeeds'); } catch(Google_Service_Exception $e) { if ($e->getErrors()[0]['reason'] == 'notFound'){ print ("Domain available for Google Workspace creation\n"); } else { throw $e; } }
Ruby
# Determine if customer domain already has Google Workspace begin reseller_service.get_customer(CUSTOMER_DOMAIN) abort('Customer already exists if call succeeds') rescue Google::Apis::ClientError => ex if ex.status_code == 404 puts 'Domain available for Google Workspace creation' else raise ex end end
Node.js
// Determine if customer domain already has Google Workspace const getCustomerPromise = resellerService.customers.get({ customerId: CUSTOMER_DOMAIN }).then(() => { throw new Error('Customer already exists'); }, resErr => { if (resErr.code === 404) { console.log('Domain available for Google Workspace creation'); } else { throw resErr; } });
視回應而定,執行下列操作:
如果客戶不存在,
customers.get
方法會傳回HTTP 404
錯誤代碼。請繼續進行下一個步驟,在 Google Workspace 中建立客戶記錄。如果
customers.get
方法傳回時沒有錯誤,請檢查回應本文是否有alternateEmail
屬性,藉此判斷客戶是否為您的客戶。如果缺少alternateEmail
屬性,您必須轉移客戶及其訂閱項目。
在 Google Workspace 中建立客戶記錄。您必須先建立客戶記錄,才能根據下列指南為該客戶建立訂閱項目:
alternateEmail
不得與customerDomain
位於同一個網域。postalAddress.countryCode
必須是兩個字元的 ISO 國家/地區代碼。
以下範例說明如何建立客戶記錄:
Python
# Create customer resource response = reseller_service.customers().insert( body={ 'customerDomain': CUSTOMER_DOMAIN, 'alternateEmail': 'marty.mcfly@gmail.com', 'postalAddress': { 'contactName': 'Marty McFly', 'organizationName': 'Acme Corp', 'postalCode': '10009', 'countryCode': 'US', } }).execute() print(response)
Java
// Create customer resource Address address = new Address() .setContactName("Marty McFly") .setOrganizationName("Acme Corp") .setCountryCode("US") .setPostalCode("10009"); Customer customer = new Customer() .setCustomerDomain(CUSTOMER_DOMAIN) .setAlternateEmail("marty.mcfly@gmail.com") .setPostalAddress(address); Customer customerResponse = resellerService.customers() .insert(customer).execute(); System.out.println("Created Customer:\n" + customerResponse);
C#
// Create customer resource Address address = new Address() { ContactName = "Marty McFly", OrganizationName = "Acme Corp", CountryCode = "US", PostalCode = "10009" }; Customer customer = new Customer() { CustomerDomain = CUSTOMER_DOMAIN, AlternateEmail = "marty.mcfly@gmail.com", PostalAddress = address }; Customer customerResponse = resellerService.Customers.Insert(customer).Execute(); Console.WriteLine("Created Customer:\n{0}", customerResponse);
PHP
// Create customer resource $customer = new Google_Service_Reseller_Customer([ 'customerDomain' => $CUSTOMER_DOMAIN, 'alternateEmail' => 'marty.mcfly@gmail.com', 'postalAddress' => [ 'contactName' => 'Marty McFly', 'organizationName' => 'Acme Corp', 'countryCode' => 'US', 'postalCode' => '10009' ] ]); $response = $resellerService->customers->insert($customer); print_r ($response);
Ruby
# Create customer resource customer = Google::Apis::ResellerV1::Customer.new( customer_domain: CUSTOMER_DOMAIN, alternate_email: 'marty.mcfly@gmail.com', postal_address: { contact_name: 'Marty McFly', organization_name: 'Acme Corp', country_code: 'US', postal_code: '10009'}) response = reseller_service.insert_customer(customer) puts response.inspect
Node.js
// Create customer resource const insertCustomerPromise = resellerService.customers.insert({ requestBody: { customerDomain: CUSTOMER_DOMAIN, alternateEmail: 'marty.mcfly@gmail.com', postalAddress: { contactName: 'Marty McFly', organizationName: 'Acme Corp', postalCode: '10009', countryCode: 'US', } } }).then(({data}) => { console.log(data); return data; });
使用 Admin SDK API 建立第一個管理員使用者
為客戶佈建服務後,您必須建立第一個使用者,並立即將該使用者升級為網域超級管理員,讓客戶存取新服務並接受所有適用的服務條款。
建立第一個使用者並設定密碼。密碼必須足夠複雜,且至少包含八個字元。詳情請參閱
user
資源。Python
# Create first admin user response = directory_service.users().insert( body={ 'primaryEmail': 'marty.mcfly@' + CUSTOMER_DOMAIN, 'name': { 'givenName': 'Marty', 'familyName': 'McFly', }, 'password': 'Timecircuit88' }).execute() print(response)
Java
// Create first admin user String userEmail = "marty.mcfly@" + CUSTOMER_DOMAIN; UserName name = new UserName(); name.setGivenName("Marty"); name.setFamilyName("McFly"); User user = new User(); user.setPrimaryEmail(userEmail); user.setPassword("TimeCircuit88"); user.setName(name); User userResponse = directoryService.users().insert(user).execute(); System.out.println("Created User:\n" + userResponse);
C#
// Create first admin user String userEmail = "marty.mcfly@" + CUSTOMER_DOMAIN; UserName name = new UserName() { GivenName = "Marty", FamilyName = "McFly" }; User user = new User() { PrimaryEmail = userEmail, Password = "TimeCircuit88", Name = name }; User userResponse = directoryService.Users.Insert(user).Execute(); Console.WriteLine("Created User:\n{0}", userResponse);
PHP
// Create first admin user $user = new Google_Service_Directory_User([ 'primaryEmail' => 'marty.mcfly@' . $CUSTOMER_DOMAIN, 'password' => 'Timecircuit88', 'name' => [ 'givenName' => 'Marty', 'familyName' => 'McFly', 'fullName' => 'Marty McFly' ] ]); $response = $directoryService->users->insert($user); print_r ($response);
Ruby
# Create first admin user user = Google::Apis::AdminDirectoryV1::User.new( name: { given_name: 'Marty', family_name: 'McFly', full_name: 'Marty McFly' }, password: 'Timecircuit88', primary_email: 'marty.mcfly@' + CUSTOMER_DOMAIN, ) response = directory_service.insert_user(user) puts response.inspect
Node.js
// Create first admin user const insertUserPromise = directoryService.users.insert({ requestBody: { primaryEmail: `marty.mcfly@${CUSTOMER_DOMAIN}`, name: { givenName: 'Marty', familyName: 'McFly', }, password: 'Timecircuit88', } }).then(({data}) => { console.log(data); return data; });
如果建立使用者的呼叫傳回
HTTP 409
,表示使用者名稱可能已存在於消費者 Google 帳戶中。將使用者升級為超級管理員角色:
Python
# Promote user to admin status response = directory_service.users().makeAdmin( userKey='marty.mcfly@' + CUSTOMER_DOMAIN, body={ 'status': True }).execute()
Java
// Promote user to admin status UserMakeAdmin admin = new UserMakeAdmin(); admin.setStatus(true); directoryService.users().makeAdmin(userEmail, admin).execute(); System.out.println("User promoted to Admin");
C#
// Promote user to admin status UserMakeAdmin admin = new UserMakeAdmin() { Status = true }; directoryService.Users.MakeAdmin(admin, userEmail).Execute(); Console.WriteLine("User promoted to Admin");
PHP
// Promote user to admin status $makeAdmin = new Google_Service_Directory_UserMakeAdmin([ 'status' => true ]); $directoryService->users->makeAdmin( 'marty.mcfly@' . $CUSTOMER_DOMAIN, $makeAdmin );
Ruby
# Promote user to admin status admin_status = Google::Apis::AdminDirectoryV1::UserMakeAdmin.new( status: true ) response = directory_service.make_user_admin('marty.mcfly@' + CUSTOMER_DOMAIN, admin_status)
Node.js
// Promote user to admin status const makeAdminPromise = directoryService.users.makeAdmin({ userKey: `marty.mcfly@${CUSTOMER_DOMAIN}`, requestBody: { status: true } });
為客戶建立 Google Workspace 訂閱方案
為客戶建立訂閱項目時,請在 purchaseOrderId
欄位中放入該客戶的內部交易 ID 或 ID。如要進一步瞭解特定引數和值,請參閱「管理訂閱項目」。
如要建立訂閱項目,請使用 Subscriptions.Insert 呼叫。以下範例使用
ANNUAL_YEARLY_PAY
訂閱:Python
# Create subscription resource response = reseller_service.subscriptions().insert( customerId=CUSTOMER_DOMAIN, body={ 'customerId': CUSTOMER_DOMAIN, 'skuId': '1010020027', 'plan': { 'planName': 'ANNUAL_MONTHLY_PAY', }, 'seats': { 'numberOfSeats': 5, }, 'renewalSettings': { # only relevant for annual plans 'renewalType': 'RENEW_CURRENT_USERS_MONTHLY_PAY' } }).execute() print(response)
Java
// Create subscription resource Seats seats = new Seats() .setNumberOfSeats(5); Subscription.Plan plan = new Subscription.Plan() .setPlanName("ANNUAL_YEARLY_PAY"); RenewalSettings renewalSettings = new RenewalSettings() .setRenewalType("RENEW_CURRENT_USERS_MONTHLY_PAY"); Subscription subscription = new Subscription() .setCustomerId(CUSTOMER_DOMAIN) .setSeats(seats) .setPlan(plan) .setSkuId("1010020027") .setRenewalSettings(renewalSettings); Subscription subscriptionResponse = resellerService.subscriptions() .insert(CUSTOMER_DOMAIN, subscription).execute(); System.out.println("Created Subscription:\n" + subscriptionResponse);
C#
// Create subscription resource Seats seats = new Seats() { NumberOfSeats = 5 }; Subscription.PlanData plan = new Subscription.PlanData() { PlanName = "ANNUAL_YEARLY_PAY" }; RenewalSettings renewalSettings = new RenewalSettings() { RenewalType = "RENEW_CURRENT_USERS_MONTHLY_PAY" }; Subscription subscription = new Subscription() { CustomerId = CUSTOMER_DOMAIN, Seats = seats, Plan = plan, SkuId = "1010020027", RenewalSettings = renewalSettings }; Subscription subscriptionResponse = resellerService.Subscriptions .Insert(subscription, CUSTOMER_DOMAIN).Execute(); Console.WriteLine("Created Subscription:\n" + subscriptionResponse);
PHP
// Create subscription resource $subscription = new Google_Service_Reseller_Subscription([ 'customerId' => $CUSTOMER_DOMAIN, 'skuId' => '1010020027', 'plan' => [ 'planName' => 'ANNUAL_MONTHLY_PAY' ], 'seats' => [ 'numberOfSeats' => '5' ], 'renewalSettings' => [ 'renewalType' => 'RENEW_CURRENT_USERS_MONTHLY_PAY' ] ]); $response = $resellerService->subscriptions->insert( $CUSTOMER_DOMAIN, $subscription ); print_r ($response);
Ruby
# Create subscription resource subscription = Google::Apis::ResellerV1::Subscription.new( customer_id: CUSTOMER_DOMAIN, sku_id: '1010020027', plan: { plan_name: 'ANNUAL_MONTHLY_PAY' }, seats: { number_of_seats: 5, }, renewal_settings: { renewal_type: 'RENEW_CURRENT_USERS_MONTHLY_PAY' } ) response = reseller_service.insert_subscription(CUSTOMER_DOMAIN, subscription) puts response.inspect
Node.js
// Create subscription resource const insertSubscriptionPromise = resellerService.subscriptions.insert({ customerId: CUSTOMER_DOMAIN, requestBody: { customerId: CUSTOMER_DOMAIN, skuId: '1010020027', plan: { planName: 'ANNUAL_MONTHLY_PAY', }, seats: { numberOfSeats: 5, }, renewalSettings: { // only relevant for annual plans renewalType: 'RENEW_CURRENT_USERS_MONTHLY_PAY', } } }).then(({data}) => { console.log(data); return data; });
在客戶管理員登入並接受《服務條款》之前,訂閱項目會處於
SUSPENDED
狀態。客戶管理員首次存取任何 Google 資源 (例如 Gmail 或 Google 雲端硬碟) 時,系統會將他們重新導向至《服務條款》。
驗證網域並指定網域擁有者
這個步驟為選用步驟,但如果您能夠驗證客戶的網域,建議您進行驗證。Site Verification API webResource.insert()
呼叫會驗證網域,並將您在要求主體的 owners[]
參數中指定的擁有者指派給該網域。
以下範例說明如何驗證 INET_DOMAIN
:
Python
# Verify domain and designate domain owners response = verification_service.webResource().insert( verificationMethod='DNS_TXT', body={ 'site': { 'type': 'INET_DOMAIN', 'identifier': CUSTOMER_DOMAIN }, 'owners': ['marty.mcfly@' + CUSTOMER_DOMAIN] }).execute() print(response)
Java
// Verify domain and designate domain owners SiteVerificationWebResourceResource.Site verifySite = new SiteVerificationWebResourceResource.Site() .setIdentifier(CUSTOMER_DOMAIN) .setType("INET_DOMAIN"); List<String> owners = Arrays.asList(userEmail); SiteVerificationWebResourceResource resource = new SiteVerificationWebResourceResource() .setSite(verifySite) .setOwners(owners); SiteVerificationWebResourceResource verifyResponse = verificationService.webResource().insert("DNS_TXT", resource).execute(); System.out.println("Site Verification Web Resource:\n" + verifyResponse);
C#
// Verify domain and designate domain owners SiteVerificationWebResourceResource.SiteData verifySite = new SiteVerificationWebResourceResource.SiteData() { Identifier = CUSTOMER_DOMAIN, Type = "INET_DOMAIN" }; string[] owners = { userEmail }; SiteVerificationWebResourceResource resource = new SiteVerificationWebResourceResource() { Site = verifySite, Owners = owners }; SiteVerificationWebResourceResource verifyResponse = verificationService.WebResource.Insert(resource, "DNS_TXT").Execute(); Console.WriteLine("Site Verification Web Resource:\n" + verifyResponse);
PHP
// Verify domain and designate domain owners $body = new Google_Service_SiteVerification_SiteVerificationWebResourceResource([ 'site' => [ 'type' => 'INET_DOMAIN', 'identifier' => $CUSTOMER_DOMAIN, ], 'owners' => ['marty.mcfly@' . $CUSTOMER_DOMAIN] ]); $response = $verificationService->webResource->insert('DNS_TXT', $body); print_r ($response);
Ruby
# Verify domain and designate domain owners webResource = Google::Apis::SiteVerificationV1::SiteVerificationWebResourceResource.new( site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN }, owners: ['marty.mcfly@' + CUSTOMER_DOMAIN] ) response = verification_service.insert_web_resource('DNS_TXT', webResource) puts response.inspect
Node.js
// Verify domain and designate domain owners const verifyDomainPromise = verificationService.webResource.insert({ verificationMethod: 'DNS_TXT', requestBody: { site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN, }, owners: [`marty.mcfly@${CUSTOMER_DOMAIN}`], } }).then(({data}) => { console.log(data); return data; });
如果成功,此呼叫會傳回 HTTP 200
代碼。如果 webResource.insert()
無法驗證網域,則會傳回 HTTP 400
層級的錯誤代碼。重試 webResource.insert()
呼叫,並設定輪詢延遲時間,直到網域成功驗證為止。
馬上開始全面整合吧!
以下範例顯示為 Google Workspace 客戶佈建的完整程式碼:
Python
"""This is a basic example of provisioning a Google Workspace customer. """ import sys from apiclient.discovery import build from apiclient.http import HttpError from oauth2client.service_account import ServiceAccountCredentials ############## REPLACE WITH YOUR OWN VALUES #################### JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json' RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com' CUSTOMER_DOMAIN = 'example.com' CUSTOMER_SITE = 'https://www.example.com' ################################################################ # Full List of scopes: # https://developers.google.com/identity/protocols/googlescopes OAUTH2_SCOPES = [ 'https://reseller.googleapis.com/auth/apps.order', 'https://reseller.googleapis.com/auth/siteverification', 'https://reseller.googleapis.com/auth/admin.directory.user', ] credentials = ServiceAccountCredentials.from_json_keyfile_name( JSON_PRIVATE_KEY_FILE, OAUTH2_SCOPES).create_delegated(RESELLER_ADMIN_USER) reseller_service = build( serviceName='reseller', version='v1', credentials=credentials) directory_service = build( serviceName='admin', version='directory_v1', credentials=credentials) verification_service = build( serviceName='siteVerification', version='v1', credentials=credentials) # Retrieve the site verification token and place it according to: # https://developers.google.com/site-verification/v1/getting_started#tokens response = verification_service.webResource().getToken( body={ 'site': { 'type': 'INET_DOMAIN', 'identifier': CUSTOMER_DOMAIN }, 'verificationMethod': 'DNS_TXT' }).execute() print(response) # Determine if customer domain already has Google Workspace try: response = reseller_service.customers().get( customerId=CUSTOMER_DOMAIN).execute() print('Customer already exists if call succeeds') sys.exit() except HttpError as error: if int(error.resp['status']) == 404: print('Domain available for Google Workspace creation') else: raise # Create customer resource response = reseller_service.customers().insert( body={ 'customerDomain': CUSTOMER_DOMAIN, 'alternateEmail': 'marty.mcfly@gmail.com', 'postalAddress': { 'contactName': 'Marty McFly', 'organizationName': 'Acme Corp', 'postalCode': '10009', 'countryCode': 'US', } }).execute() print(response) # Create first admin user response = directory_service.users().insert( body={ 'primaryEmail': 'marty.mcfly@' + CUSTOMER_DOMAIN, 'name': { 'givenName': 'Marty', 'familyName': 'McFly', }, 'password': 'Timecircuit88' }).execute() print(response) # Promote user to admin status response = directory_service.users().makeAdmin( userKey='marty.mcfly@' + CUSTOMER_DOMAIN, body={ 'status': True }).execute() # Create subscription resource response = reseller_service.subscriptions().insert( customerId=CUSTOMER_DOMAIN, body={ 'customerId': CUSTOMER_DOMAIN, 'skuId': '1010020027', 'plan': { 'planName': 'ANNUAL_MONTHLY_PAY', }, 'seats': { 'numberOfSeats': 5, }, 'renewalSettings': { # only relevant for annual plans 'renewalType': 'RENEW_CURRENT_USERS_MONTHLY_PAY' } }).execute() print(response) # Verify domain and designate domain owners response = verification_service.webResource().insert( verificationMethod='DNS_TXT', body={ 'site': { 'type': 'INET_DOMAIN', 'identifier': CUSTOMER_DOMAIN }, 'owners': ['marty.mcfly@' + CUSTOMER_DOMAIN] }).execute() print(response)
Java
// OAuth2 and HTTP import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.HttpResponseException; import com.google.api.client.json.jackson2.JacksonFactory; // Directory API import com.google.api.services.admin.directory.Directory; import com.google.api.services.admin.directory.DirectoryScopes; import com.google.api.services.admin.directory.model.User; import com.google.api.services.admin.directory.model.UserMakeAdmin; import com.google.api.services.admin.directory.model.UserName; // Reseller API import com.google.api.services.reseller.Reseller; import com.google.api.services.reseller.ResellerScopes; import com.google.api.services.reseller.model.Address; import com.google.api.services.reseller.model.Customer; import com.google.api.services.reseller.model.RenewalSettings; import com.google.api.services.reseller.model.Seats; import com.google.api.services.reseller.model.Subscription; // Site Verification API import com.google.api.services.siteVerification.SiteVerification; import com.google.api.services.siteVerification.SiteVerificationScopes; import com.google.api.services.siteVerification.model.SiteVerificationWebResourceGettokenRequest; import com.google.api.services.siteVerification.model.SiteVerificationWebResourceGettokenResponse; import com.google.api.services.siteVerification.model.SiteVerificationWebResourceResource; // Java library imports import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.List; /** * This is a basic example of provisioning a Google Workspace customer. */ public class CodelabExample { // Full List of scopes: // https://developers.google.com/identity/protocols/googlescopes private static final List<String> OAUTH2_SCOPES = Arrays.asList( ResellerScopes.APPS_ORDER, SiteVerificationScopes.SITEVERIFICATION, DirectoryScopes.ADMIN_DIRECTORY_USER ); /***************** REPLACE WITH YOUR OWN VALUES ********************************/ public static final String JSON_PRIVATE_KEY_FILE = "path/to/json_key_file.json"; public static final String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com"; public static final String CUSTOMER_DOMAIN = "example.com"; public static final String CUSTOMER_SITE = "https://www.example.com/"; /*******************************************************************************/ public static void main(String[] args) throws IOException, GeneralSecurityException, FileNotFoundException { // Instantiate services with authenticated credentials GoogleCredential jsonCredentials = GoogleCredential .fromStream(new FileInputStream(JSON_PRIVATE_KEY_FILE)); GoogleCredential credentials = new GoogleCredential.Builder() .setTransport(GoogleNetHttpTransport.newTrustedTransport()) .setJsonFactory(JacksonFactory.getDefaultInstance()) .setServiceAccountScopes(OAUTH2_SCOPES) .setServiceAccountUser(RESELLER_ADMIN_USER) .setServiceAccountPrivateKey(jsonCredentials.getServiceAccountPrivateKey()) .setServiceAccountId(jsonCredentials.getServiceAccountId()) .build(); Reseller resellerService = new Reseller.Builder( credentials.getTransport(), credentials.getJsonFactory(), credentials).setApplicationName("Google Workspace Creator").build(); Directory directoryService = new Directory.Builder( credentials.getTransport(), credentials.getJsonFactory(), credentials).setApplicationName("Google Workspace Creator").build(); SiteVerification verificationService = new SiteVerification.Builder( credentials.getTransport(), credentials.getJsonFactory(), credentials).setApplicationName("Google Workspace Creator").build(); // Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens SiteVerificationWebResourceGettokenRequest.Site getTokenSite = new SiteVerificationWebResourceGettokenRequest.Site() .setType("INET_DOMAIN") .setIdentifier(CUSTOMER_DOMAIN); SiteVerificationWebResourceGettokenRequest request = new SiteVerificationWebResourceGettokenRequest() .setVerificationMethod("DNS_TXT") .setSite(getTokenSite); SiteVerificationWebResourceGettokenResponse getTokenResponse = verificationService.webResource().getToken(request).execute(); System.out.println("Site Verification Token: " + getTokenResponse.getToken()); // Determine if customer domain already has Google Workspace try { resellerService.customers().get(CUSTOMER_DOMAIN).execute(); System.out.println("Customer already exists if call succeeds"); System.exit(0); } catch (HttpResponseException e) { if (e.getStatusCode() == 404) { System.out.println("Domain available for Google Workspace creation"); } else { throw e; } } // Create customer resource Address address = new Address() .setContactName("Marty McFly") .setOrganizationName("Acme Corp") .setCountryCode("US") .setPostalCode("10009"); Customer customer = new Customer() .setCustomerDomain(CUSTOMER_DOMAIN) .setAlternateEmail("marty.mcfly@gmail.com") .setPostalAddress(address); Customer customerResponse = resellerService.customers() .insert(customer).execute(); System.out.println("Created Customer:\n" + customerResponse); // Create first admin user String userEmail = "marty.mcfly@" + CUSTOMER_DOMAIN; UserName name = new UserName(); name.setGivenName("Marty"); name.setFamilyName("McFly"); User user = new User(); user.setPrimaryEmail(userEmail); user.setPassword("TimeCircuit88"); user.setName(name); User userResponse = directoryService.users().insert(user).execute(); System.out.println("Created User:\n" + userResponse); // Promote user to admin status UserMakeAdmin admin = new UserMakeAdmin(); admin.setStatus(true); directoryService.users().makeAdmin(userEmail, admin).execute(); System.out.println("User promoted to Admin"); // Create subscription resource Seats seats = new Seats() .setNumberOfSeats(5); Subscription.Plan plan = new Subscription.Plan() .setPlanName("ANNUAL_YEARLY_PAY"); RenewalSettings renewalSettings = new RenewalSettings() .setRenewalType("RENEW_CURRENT_USERS_MONTHLY_PAY"); Subscription subscription = new Subscription() .setCustomerId(CUSTOMER_DOMAIN) .setSeats(seats) .setPlan(plan) .setSkuId("1010020027") .setRenewalSettings(renewalSettings); Subscription subscriptionResponse = resellerService.subscriptions() .insert(CUSTOMER_DOMAIN, subscription).execute(); System.out.println("Created Subscription:\n" + subscriptionResponse); // Verify domain and designate domain owners SiteVerificationWebResourceResource.Site verifySite = new SiteVerificationWebResourceResource.Site() .setIdentifier(CUSTOMER_DOMAIN) .setType("INET_DOMAIN"); List<String> owners = Arrays.asList(userEmail); SiteVerificationWebResourceResource resource = new SiteVerificationWebResourceResource() .setSite(verifySite) .setOwners(owners); SiteVerificationWebResourceResource verifyResponse = verificationService.webResource().insert("DNS_TXT", resource).execute(); System.out.println("Site Verification Web Resource:\n" + verifyResponse); } }
C#
// OAuth2 and HTTP using Google.Apis.Auth.OAuth2; using Google.Apis.Services; // Reseller API using Google.Apis.Reseller.v1; using Google.Apis.Reseller.v1.Data; // Directory API using Google.Apis.Admin.Directory.directory_v1; using User = Google.Apis.Admin.Directory.directory_v1.Data.User; using UserName = Google.Apis.Admin.Directory.directory_v1.Data.UserName; using UserMakeAdmin = Google.Apis.Admin.Directory.directory_v1.Data.UserMakeAdmin; //Site Verification API using Google.Apis.SiteVerification.v1; using Google.Apis.SiteVerification.v1.Data; // System imports using System; using System.IO; class CodelabExample { // Full List of scopes: // https://developers.google.com/identity/protocols/googlescopes static string[] OAUTH2_SCOPES = { ResellerService.Scope.AppsOrder, DirectoryService.Scope.AdminDirectoryUser, SiteVerificationService.Scope.Siteverification }; /***************** REPLACE WITH YOUR OWN VALUES ********************************/ public static String JSON_PRIVATE_KEY_FILE = "path/to/json_key_file.json"; public static String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com"; public static String CUSTOMER_DOMAIN = "example.com"; public static String CUSTOMER_SITE = "https://www.example.com/"; /*******************************************************************************/ static void Main(string[] args) { GoogleCredential credential; using (var stream = new FileStream(JSON_PRIVATE_KEY_FILE, FileMode.Open, FileAccess.Read)) { credential = GoogleCredential .FromStream(stream) .CreateScoped(OAUTH2_SCOPES) .CreateWithUser(RESELLER_ADMIN_USER); } var resellerService = new ResellerService(new BaseClientService.Initializer() { HttpClientInitializer = credential, }); var directoryService = new DirectoryService(new BaseClientService.Initializer() { HttpClientInitializer = credential, }); var verificationService = new SiteVerificationService(new BaseClientService.Initializer() { HttpClientInitializer = credential, }); // Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens SiteVerificationWebResourceGettokenRequest.SiteData getTokenSite = new SiteVerificationWebResourceGettokenRequest.SiteData() { Type = "INET_DOMAIN", Identifier = CUSTOMER_DOMAIN }; SiteVerificationWebResourceGettokenRequest request = new SiteVerificationWebResourceGettokenRequest() { VerificationMethod = "DNS_TXT", Site = getTokenSite }; SiteVerificationWebResourceGettokenResponse getTokenResponse = verificationService.WebResource.GetToken(request).Execute(); Console.WriteLine("Site Verification Token: {0}", getTokenResponse.Token); // Determine if customer domain already has Google Workspace try { resellerService.Customers.Get(CUSTOMER_DOMAIN).Execute(); Console.WriteLine("Customer already exists if call succeeds"); Environment.Exit(0); } catch (Google.GoogleApiException e) { if (e.Error.Code == 404) { Console.WriteLine("Domain available for Google Workspace creation"); } else throw e; } // Create customer resource Address address = new Address() { ContactName = "Marty McFly", OrganizationName = "Acme Corp", CountryCode = "US", PostalCode = "10009" }; Customer customer = new Customer() { CustomerDomain = CUSTOMER_DOMAIN, AlternateEmail = "marty.mcfly@gmail.com", PostalAddress = address }; Customer customerResponse = resellerService.Customers.Insert(customer).Execute(); Console.WriteLine("Created Customer:\n{0}", customerResponse); // Create first admin user String userEmail = "marty.mcfly@" + CUSTOMER_DOMAIN; UserName name = new UserName() { GivenName = "Marty", FamilyName = "McFly" }; User user = new User() { PrimaryEmail = userEmail, Password = "TimeCircuit88", Name = name }; User userResponse = directoryService.Users.Insert(user).Execute(); Console.WriteLine("Created User:\n{0}", userResponse); // Promote user to admin status UserMakeAdmin admin = new UserMakeAdmin() { Status = true }; directoryService.Users.MakeAdmin(admin, userEmail).Execute(); Console.WriteLine("User promoted to Admin"); // Create subscription resource Seats seats = new Seats() { NumberOfSeats = 5 }; Subscription.PlanData plan = new Subscription.PlanData() { PlanName = "ANNUAL_YEARLY_PAY" }; RenewalSettings renewalSettings = new RenewalSettings() { RenewalType = "RENEW_CURRENT_USERS_MONTHLY_PAY" }; Subscription subscription = new Subscription() { CustomerId = CUSTOMER_DOMAIN, Seats = seats, Plan = plan, SkuId = "1010020027", RenewalSettings = renewalSettings }; Subscription subscriptionResponse = resellerService.Subscriptions .Insert(subscription, CUSTOMER_DOMAIN).Execute(); Console.WriteLine("Created Subscription:\n" + subscriptionResponse); // Verify domain and designate domain owners SiteVerificationWebResourceResource.SiteData verifySite = new SiteVerificationWebResourceResource.SiteData() { Identifier = CUSTOMER_DOMAIN, Type = "INET_DOMAIN" }; string[] owners = { userEmail }; SiteVerificationWebResourceResource resource = new SiteVerificationWebResourceResource() { Site = verifySite, Owners = owners }; SiteVerificationWebResourceResource verifyResponse = verificationService.WebResource.Insert(resource, "DNS_TXT").Execute(); Console.WriteLine("Site Verification Web Resource:\n" + verifyResponse); } }
PHP
// https://developers.google.com/api-client-library/php/ require_once 'vendor/autoload.php'; // Full List of scopes: // https://developers.google.com/identity/protocols/googlescopes $OAUTH2_SCOPES = [ Google_Service_Reseller::APPS_ORDER, Google_Service_SiteVerification::SITEVERIFICATION, Google_Service_Directory::ADMIN_DIRECTORY_USER, ]; ######### REPLACE WITH YOUR OWN VALUES ############### $JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'; $RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'; $CUSTOMER_DOMAIN = 'example.com'; $CUSTOMER_SITE = 'https://www.example.com/'; ###################################################### $client = new Google_Client(); $client->setAuthConfig($JSON_PRIVATE_KEY_FILE); $client->setSubject($RESELLER_ADMIN_USER); $client->setScopes($OAUTH2_SCOPES); $resellerService = new Google_Service_Reseller($client); $directoryService = new Google_Service_Directory($client); $verificationService = new Google_Service_SiteVerification($client); // Retrieve the site verification token and place it according to: // https://developers.google.com/site-verification/v1/getting_started#tokens $body = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest([ 'verificationMethod' => 'DNS_TXT', 'site' => [ 'type' => 'INET_DOMAIN', 'identifier' => $CUSTOMER_DOMAIN ] ]); $response = $verificationService->webResource->getToken($body); print_r ($response); // Determine if customer domain already has Google Workspace try { $response = $resellerService->customers->get($CUSTOMER_DOMAIN); exit('Customer already exists if call succeeds'); } catch(Google_Service_Exception $e) { if ($e->getErrors()[0]['reason'] == 'notFound'){ print ("Domain available for Google Workspace creation\n"); } else { throw $e; } } // Create customer resource $customer = new Google_Service_Reseller_Customer([ 'customerDomain' => $CUSTOMER_DOMAIN, 'alternateEmail' => 'marty.mcfly@gmail.com', 'postalAddress' => [ 'contactName' => 'Marty McFly', 'organizationName' => 'Acme Corp', 'countryCode' => 'US', 'postalCode' => '10009' ] ]); $response = $resellerService->customers->insert($customer); print_r ($response); // Create first admin user $user = new Google_Service_Directory_User([ 'primaryEmail' => 'marty.mcfly@' . $CUSTOMER_DOMAIN, 'password' => 'Timecircuit88', 'name' => [ 'givenName' => 'Marty', 'familyName' => 'McFly', 'fullName' => 'Marty McFly' ] ]); $response = $directoryService->users->insert($user); print_r ($response); // Promote user to admin status $makeAdmin = new Google_Service_Directory_UserMakeAdmin([ 'status' => true ]); $directoryService->users->makeAdmin( 'marty.mcfly@' . $CUSTOMER_DOMAIN, $makeAdmin ); // Create subscription resource $subscription = new Google_Service_Reseller_Subscription([ 'customerId' => $CUSTOMER_DOMAIN, 'skuId' => '1010020027', 'plan' => [ 'planName' => 'ANNUAL_MONTHLY_PAY' ], 'seats' => [ 'numberOfSeats' => '5' ], 'renewalSettings' => [ 'renewalType' => 'RENEW_CURRENT_USERS_MONTHLY_PAY' ] ]); $response = $resellerService->subscriptions->insert( $CUSTOMER_DOMAIN, $subscription ); print_r ($response); // Verify domain and designate domain owners $body = new Google_Service_SiteVerification_SiteVerificationWebResourceResource([ 'site' => [ 'type' => 'INET_DOMAIN', 'identifier' => $CUSTOMER_DOMAIN, ], 'owners' => ['marty.mcfly@' . $CUSTOMER_DOMAIN] ]); $response = $verificationService->webResource->insert('DNS_TXT', $body); print_r ($response);
Ruby
require 'googleauth' require 'google/apis/reseller_v1' require 'google/apis/site_verification_v1' require 'google/apis/admin_directory_v1' # Full List of scopes: # https://developers.google.com/identity/protocols/googlescopes OAUTH2_SCOPES = [ 'https://reseller.googleapis.com/auth/apps.order', 'https://reseller.googleapis.com/auth/admin.directory.user', 'https://reseller.googleapis.com/auth/siteverification', ] ####### REPLACE WITH YOUR OWN VALUES ############### JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json' RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com' CUSTOMER_DOMAIN = 'example.com' CUSTOMER_SITE = 'https://www.example.com/' #################################################### credentials = Google::Auth::ServiceAccountCredentials.make_creds( json_key_io: File.open(JSON_PRIVATE_KEY_FILE), scope: OAUTH2_SCOPES) credentials.sub = RESELLER_ADMIN_USER Google::Apis::RequestOptions.default.authorization = credentials reseller_service = Google::Apis::ResellerV1::ResellerService.new directory_service = Google::Apis::AdminDirectoryV1::DirectoryService.new verification_service = Google::Apis::SiteVerificationV1::SiteVerificationService.new # Retrieve the site verification token and place it according to: # https://developers.google.com/site-verification/v1/getting_started#tokens request = Google::Apis::SiteVerificationV1::GetWebResourceTokenRequest.new( site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN }, verification_method: 'DNS_TXT' ) response = verification_service.get_web_resource_token(request) puts response.inspect # Determine if customer domain already has Google Workspace begin reseller_service.get_customer(CUSTOMER_DOMAIN) abort('Customer already exists if call succeeds') rescue Google::Apis::ClientError => ex if ex.status_code == 404 puts 'Domain available for Google Workspace creation' else raise ex end end # Create customer resource customer = Google::Apis::ResellerV1::Customer.new( customer_domain: CUSTOMER_DOMAIN, alternate_email: 'marty.mcfly@gmail.com', postal_address: { contact_name: 'Marty McFly', organization_name: 'Acme Corp', country_code: 'US', postal_code: '10009'}) response = reseller_service.insert_customer(customer) puts response.inspect # Create first admin user user = Google::Apis::AdminDirectoryV1::User.new( name: { given_name: 'Marty', family_name: 'McFly', full_name: 'Marty McFly' }, password: 'Timecircuit88', primary_email: 'marty.mcfly@' + CUSTOMER_DOMAIN, ) response = directory_service.insert_user(user) puts response.inspect # Promote user to admin status admin_status = Google::Apis::AdminDirectoryV1::UserMakeAdmin.new( status: true ) response = directory_service.make_user_admin('marty.mcfly@' + CUSTOMER_DOMAIN, admin_status) # Create subscription resource subscription = Google::Apis::ResellerV1::Subscription.new( customer_id: CUSTOMER_DOMAIN, sku_id: '1010020027', plan: { plan_name: 'ANNUAL_MONTHLY_PAY' }, seats: { number_of_seats: 5, }, renewal_settings: { renewal_type: 'RENEW_CURRENT_USERS_MONTHLY_PAY' } ) response = reseller_service.insert_subscription(CUSTOMER_DOMAIN, subscription) puts response.inspect # Verify domain and designate domain owners webResource = Google::Apis::SiteVerificationV1::SiteVerificationWebResourceResource.new( site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN }, owners: ['marty.mcfly@' + CUSTOMER_DOMAIN] ) response = verification_service.insert_web_resource('DNS_TXT', webResource) puts response.inspect
Node.js
// NOTE: This script needs googleapis 28.0.0 or later as it uses promises const {google} = require('googleapis'); // ############## REPLACE WITH YOUR OWN VALUES #################### const JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'; const RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'; const CUSTOMER_DOMAIN = 'example.com'; const CUSTOMER_SITE = 'https://www.example.com/'; // ################################################################ // Full List of scopes: https://developers.google.com/identity/protocols/googlescopes const OAUTH2_SCOPES = [ 'https://reseller.googleapis.com/auth/apps.order', 'https://reseller.googleapis.com/auth/siteverification', 'https://reseller.googleapis.com/auth/admin.directory.user', ]; const authJWT = new google.auth.JWT({ keyFile: JSON_PRIVATE_KEY_FILE, scopes: OAUTH2_SCOPES, subject: RESELLER_ADMIN_USER, }); const resellerService = google.reseller({version: 'v1', auth: authJWT}); const directoryService = google.admin({version: 'directory_v1', auth: authJWT}); const verificationService = google.siteVerification({version: 'v1', auth: authJWT}); // Run all the steps one after each other, and exit as soon as one of them fail Promise.resolve() .then(() => { /** * Retrieve the site verification token and place it according to: * https://developers.google.com/site-verification/v1/getting_started#tokens */ const getTokenPromise = verificationService.webResource.getToken({ requestBody: { site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN, }, verificationMethod: 'DNS_TXT', } }).then(({data}) => { console.log(data); return data; }); return getTokenPromise; }) .then(() => { // Determine if customer domain already has Google Workspace const getCustomerPromise = resellerService.customers.get({ customerId: CUSTOMER_DOMAIN }).then(() => { throw new Error('Customer already exists'); }, resErr => { if (resErr.code === 404) { console.log('Domain available for Google Workspace creation'); } else { throw resErr; } }); return getCustomerPromise; }) .then(() => { // Create customer resource const insertCustomerPromise = resellerService.customers.insert({ requestBody: { customerDomain: CUSTOMER_DOMAIN, alternateEmail: 'marty.mcfly@gmail.com', postalAddress: { contactName: 'Marty McFly', organizationName: 'Acme Corp', postalCode: '10009', countryCode: 'US', } } }).then(({data}) => { console.log(data); return data; }); return insertCustomerPromise; }) .then(() => { // Create first admin user const insertUserPromise = directoryService.users.insert({ requestBody: { primaryEmail: `marty.mcfly@${CUSTOMER_DOMAIN}`, name: { givenName: 'Marty', familyName: 'McFly', }, password: 'Timecircuit88', } }).then(({data}) => { console.log(data); return data; }); return insertUserPromise; }).then(() => { // Promote user to admin status const makeAdminPromise = directoryService.users.makeAdmin({ userKey: `marty.mcfly@${CUSTOMER_DOMAIN}`, requestBody: { status: true } }); return makeAdminPromise; }) .then(() => { // Create subscription resource const insertSubscriptionPromise = resellerService.subscriptions.insert({ customerId: CUSTOMER_DOMAIN, requestBody: { customerId: CUSTOMER_DOMAIN, skuId: '1010020027', plan: { planName: 'ANNUAL_MONTHLY_PAY', }, seats: { numberOfSeats: 5, }, renewalSettings: { // only relevant for annual plans renewalType: 'RENEW_CURRENT_USERS_MONTHLY_PAY', } } }).then(({data}) => { console.log(data); return data; }); return insertSubscriptionPromise; }) .then(() => { // Verify domain and designate domain owners const verifyDomainPromise = verificationService.webResource.insert({ verificationMethod: 'DNS_TXT', requestBody: { site: { type: 'INET_DOMAIN', identifier: CUSTOMER_DOMAIN, }, owners: [`marty.mcfly@${CUSTOMER_DOMAIN}`], } }).then(({data}) => { console.log(data); return data; }); return verifyDomainPromise; }) .catch(err => { console.error('Error:', err.message); if (err.code) { console.log('Error code:', err.code); } if (err.errors) { console.log('Details:', err.errors); } });