為什麼要自動驗證網域?
雖然 Cloud Channel API 可讓您大規模地佈建 Google Workspace 授權,但客戶仍需採取下列行動才能啟用服務。
- 接受《服務條款》
- 驗證網域擁有權
- 設定 MX 記錄
新建立的客戶首次存取管理控制台 (位於 admin.google.com) 時,系統會引導他們完成相關程序。
如果您有網域 DNS 記錄的程式輔助存取權 (例如,如果您將網域轉售給客戶),您可以自動執行步驟 2 和 3 來提高啟用率,因為這些步驟通常需要轉售客戶的技術知識。
本程式碼研究室說明如何使用 Site Verification API 實作這項自動化功能。
事前準備
請務必完成 API 設定程式碼研究室,設定Google Cloud 專案並建立服務帳戶,以便呼叫 Cloud Channel API。
建議您使用測試合作夥伴銷售資訊主控台進行本程式碼研究室。
本程式碼研究室也要求您完成工作區端對端佈建程式碼研究室。
總覽
驗證 Google Workspace 授權的網域需要進行數個 API 呼叫。
網站驗證 API 並非經銷商專用。網域驗證是各種 Google 產品 (搜尋控制台、Google Ads 等) 使用的信號。如要完成這項程序,您必須將經銷商網域的超級管理員設為網域的「擁有者」,並將客戶的第一位管理員設為共同擁有者。如要進一步瞭解這些概念,請參閱「開始使用 Site Verification API」頁面。
步驟 1:為網站驗證 API 做好準備
- 前往 Google Cloud 控制台的「API 程式庫」部分,啟用「網站驗證 API」。
- 使用經銷商網域的超級管理員帳戶前往網域層級委派頁面。
- 在服務帳戶所在的資料列中,按一下「編輯」。
- 在「OAuth 範圍」欄位中輸入
https://www.googleapis.com/auth/siteverification
。 - 按一下 [授權]。
- 安裝 Site Verification API 用戶端程式庫。
步驟 2:取得驗證權杖
這個程式碼研究室將著重於驗證網域最常見的方式:使用 TXT
DNS 記錄。網站驗證 API 支援其他驗證方法。
如要擷取您要放置為 TXT
記錄的符記,您必須取得 type=INET_DOMAIN
和 verificationMethod=DNS_TXT
的符記。
在下列程式碼中,使用您的資訊填入這些變數。
jsonKeyFile
:建立服務帳戶時產生的 JSON 金鑰檔案路徑。resellerAdminUser
:經銷商網域超級管理員的電子郵件地址。customerDomain
:最終客戶的網域。如果您要在測試版 Partner Sales Console 上執行本程式碼研究室,請務必確保網域遵循網域命名慣例。
C#
使用下列匯入功能:
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.SiteVerification.v1;
using Google.Apis.SiteVerification.v1.Data;
建立 API 用戶端並擷取權杖:
// Set up credentials with user impersonation
ICredential credential = GoogleCredential.FromFile(jsonKeyFile)
.CreateScoped("https://www.googleapis.com/auth/siteverification")
.CreateWithUser(resellerAdminUser);
// Create the API service
var verificationService = new SiteVerificationService(new BaseClientService.Initializer{
HttpClientInitializer = credential,
});
// Fetch the token
var request = new SiteVerificationWebResourceGettokenRequest {
VerificationMethod = "DNS_TXT",
Site = new SiteVerificationWebResourceGettokenRequest.SiteData {
Type = "INET_DOMAIN",
Identifier = customerDomain
}
};
var response = verificationService.WebResource.GetToken(request).Execute();
string token = response.Token;
Console.WriteLine("Site Verification token: " + token);
Go
使用下列匯入功能:
import (
"context"
"fmt"
"os"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
"google.golang.org/api/siteverification/v1"
)
建立 API 用戶端並擷取權杖:
ctx := context.Background()
// Set up credentials with user impersonation
jsonKey, _ := os.ReadFile(jsonKeyFile)
jwt, _ := google.JWTConfigFromJSON(jsonKey, "https://www.googleapis.com/auth/siteverification")
jwt.Subject = resellerAdminUser
tokenSource := jwt.TokenSource(ctx)
// Create the API Service
verificationService, _ := siteverification.NewService(ctx, option.WithTokenSource(tokenSource))
// Fetch the token
req := &siteverification.SiteVerificationWebResourceGettokenRequest{
Site: &siteverification.SiteVerificationWebResourceGettokenRequestSite{
Type: "INET_DOMAIN",
Identifier: customerDomain,
},
VerificationMethod: "DNS_TXT",
}
res, _ := verificationService.WebResource.GetToken(req).Do()
token := res.Token
fmt.Println("Site verification token: " + token)
Java
使用下列匯入功能:
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
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;
import java.io.FileInputStream;
import java.util.Arrays;
建立 API 用戶端並擷取權杖:
// Set up credentials with user impersonation
FileInputStream jsonKeyFileSteam = new FileInputStream(JSON_KEY_FILE);
GoogleCredentials credentials = ServiceAccountCredentials.fromStream(jsonKeyFileSteam)
.createScoped("https://www.googleapis.com/auth/siteverification")
.createDelegated(RESELLER_ADMIN_USER);
// Create the API service
SiteVerification verificationService = new SiteVerification.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JacksonFactory.getDefaultInstance(),
new HttpCredentialsAdapter(credentials)).build();
// Fetch the token
SiteVerificationWebResourceGettokenRequest request =
new SiteVerificationWebResourceGettokenRequest()
.setVerificationMethod("DNS_TXT")
.setSite(new SiteVerificationWebResourceGettokenRequest.Site()
.setType("INET_DOMAIN")
.setIdentifier(CUSTOMER_DOMAIN));
SiteVerificationWebResourceGettokenResponse response =
verificationService.webResource().getToken(request).execute();
String token = response.getToken();
System.out.println("Site Verification token: " + token);
Node.js
使用以下匯入功能:
const {google} = require('googleapis');
建立 API 用戶端並擷取權杖:
// Set up credentials with user impersonation
const authJWT = new JWT({
keyFile: jsonKeyFile,
scopes: ['https://www.googleapis.com/auth/siteverification'],
subject: resellerAdminUser,
});
// Create the API service
const verificationService = google.siteVerification({version: 'v1', auth: authJWT});
// Fetch the token
const { data } = await verificationService.webResource.getToken({
requestBody: {
site: {
type: 'INET_DOMAIN',
identifier: customerDomain,
},
verificationMethod: 'DNS_TXT',
}
});
const token = data.token;
console.log(`Site Verification token: ${token}`);
PHP
建立 API 用戶端並擷取權杖:
// Set up credentials with user impersonation
$client = new Google_Client();
$client->setAuthConfig($JSON_KEY_FILE);
$client->setSubject($RESELLER_ADMIN_USER);
$client->setScopes('https://www.googleapis.com/auth/siteverification');
// Create the API service
$verificationService = new Google_Service_SiteVerification($client);
// Fetch the token
$request = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest([
'verificationMethod' => 'DNS_TXT',
'site' => [
'type' => 'INET_DOMAIN',
'identifier' => $CUSTOMER_DOMAIN
]
]);
$response = $verificationService->webResource->getToken($request);
$token = $response->token;
print 'Site Verification token: ' . $token . PHP_EOL;
Python
使用下列匯入功能:
from google.oauth2 import service_account
from apiclient.discovery import build
建立 API 用戶端並擷取權杖:
# Set up credentials with user impersonation
credentials = service_account.Credentials.from_service_account_file(
JSON_KEY_FILE, scopes=["https://www.googleapis.com/auth/siteverification"])
credentials_delegated = credentials.with_subject(RESELLER_ADMIN_USER)
# Create the API service
verification_service = build(serviceName="siteVerification", version="v1",
credentials=credentials_delegated)
# Fetch the token
response = verification_service.webResource().getToken(
body={
"site": {
"type": "INET_DOMAIN",
"identifier": CUSTOMER_DOMAIN
},
"verificationMethod": "DNS_TXT"
}).execute()
token = response["token"]
print("Site Verification token: " + token)
步驟 3:放置驗證權杖
編寫程式碼,將權杖新增為客戶網域的 DNS 記錄中的 TXT
記錄。
如果是新網域,現在正是設定 Gmail 所需MX
記錄的最佳時機。
步驟 4:觸發網域驗證
將符記設為 TXT
記錄後,您就可以呼叫 Site Verification API 觸發驗證程序。方法是呼叫 webResource.insert()
。
如果找不到預期的權杖,呼叫就會失敗,並傳回 400 錯誤。您可以實作指數遞減重試策略,直到呼叫成功為止,以彌補 DNS 傳播延遲。
如果呼叫傳回的結果沒有錯誤,Site Verification API 會視為網域已完成驗證,且 webResource
的 owners
欄位中的任何電子郵件地址都是已驗證的擁有者。
驗證狀態可能需要約 3 小時才會套用到客戶的 Google Workspace 帳戶。您可以將客戶的管理員 (在呼叫 provisionCloudIdentity
時建立) 設為 webResource
的 owner
,藉此強制立即套用狀態。
C#
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
string[] owners = { "admin@" + customerDomain };
var resource = new SiteVerificationWebResourceResource {
Site = new SiteVerificationWebResourceResource.SiteData {
Type = "INET_DOMAIN",
Identifier = customerDomain
},
Owners = owners
};
resource = verificationService.WebResource.Insert(resource, "DNS_TXT").Execute();
Console.WriteLine("=== Domain has been verified");
Go
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
resource := &siteverification.SiteVerificationWebResourceResource{
Site: &siteverification.SiteVerificationWebResourceResourceSite{
Type: "INET_DOMAIN",
Identifier: customerDomain,
},
Owners: []string{"admin@" + customerDomain},
}
resource, err := verificationService.WebResource.Insert("DNS_TXT", resource).Do()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("=== Domain has been verified")
}
Java
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
SiteVerificationWebResourceResource resource =
new SiteVerificationWebResourceResource()
.setSite(new SiteVerificationWebResourceResource.Site()
.setIdentifier(CUSTOMER_DOMAIN)
.setType("INET_DOMAIN"))
.setOwners(Arrays.asList("admin@" + CUSTOMER_DOMAIN));
resource = verificationService.webResource().insert("DNS_TXT", resource).execute();
System.out.println("=== Domain has been verified");
Node.js
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
await verificationService.webResource.insert({
verificationMethod: 'DNS_TXT',
requestBody: {
site: {
type: 'INET_DOMAIN',
identifier: customerDomain,
},
owners: [`admin@${customerDomain}`],
}
});
console.log('=== Domain has been verified');
PHP
// Set the customer's admin user as an owner to make sure the domain
// verification status is instantly propagated to the Workspace account
$resource = new Google_Service_SiteVerification_SiteVerificationWebResourceResource([
'site' => [
'type' => 'INET_DOMAIN',
'identifier' => $CUSTOMER_DOMAIN,
],
'owners' => ['admin@' . $CUSTOMER_DOMAIN]
]);
$resource = $verificationService->webResource->insert('DNS_TXT', $resource);
print '=== Domain has been verified' . PHP_EOL;
Python
# Set the customer's admin user as an owner to make sure the domain
# verification status is instantly propagated to the Workspace account
resource = verification_service.webResource().insert(
verificationMethod="DNS_TXT",
body={
"site": {
"type": "INET_DOMAIN",
"identifier": CUSTOMER_DOMAIN
},
"owners": ["admin@" + CUSTOMER_DOMAIN]
}).execute()
print("=== Domain has been verified")