使用 SDK 进行身份验证

本文介绍必应广告 SDK 的身份验证和基本服务调用。

配置沙盒

SDK 默认使用生产环境。 使用 .NET 和 Java SDK,可以将其更改为具有全局配置的沙盒。 而全局配置不适用于 PHP 和 Python SDK,你可以创建全局配置或其他自定义解决方案。

// Set the BingAdsEnvironment key to Sandbox within the <appSettings> node 
// of your project root's Web.config file (for web apps) or App.config file (for native apps).
<add key="BingAdsEnvironment" value ="Sandbox"/>
// Create a new text file named bingads.properties within your project source root directory 
// e.g. **ProjectName\src\bingads.properties** and add only the following text. 
// If the sandbox environment setting is malformed or missing, the default environment is production.
environment=Sandbox

还可以设置单个批量Service Manager服务客户端报表Service Manager实例的 API 环境参数。 设置 apiEnvironment 将仅覆盖一个或多个指定服务客户端实例的全局设置。 除非另有预期,否则应注意不要无意中配置一组混合环境。

注意

BulkServiceManagerReportingServiceManager 可用于 .NET、Java 和 Python SDK。

BulkServiceManager BulkService = new BulkServiceManager(authorizationData, ApiEnvironment.Sandbox);

ServiceClient<ICustomerManagementService> Service = new ServiceClient<ICustomerManagementService>(authorizationData, ApiEnvironment.Sandbox);
    
ReportingServiceManager ReportingService = new ReportingServiceManager(authorizationData, ApiEnvironment.Sandbox);
BulkServiceManager BulkService = new BulkServiceManager(authorizationData, ApiEnvironment.SANDBOX);

ServiceClient<ICustomerManagementService> CustomerService = 
    new ServiceClient<ICustomerManagementService>(
        authorizationData,
        ApiEnvironment.SANDBOX,
        ICustomerManagementService.class
    );
    
ReportingServiceManager ReportingService = new ReportingServiceManager(authorizationData, ApiEnvironment.SANDBOX);
$customerProxy = new ServiceClient(ServiceClientType::CustomerManagementVersion13, $authorizationData, ApiEnvironment::Sandbox);
# Set the environment property of each ServiceClient instance to 'sandbox' (not case sensitive). 
# If the sandbox environment setting is malformed or missing, the default environment is production.
# Once the environment is initialized you may not reset it for the service client instance. 
# To switch between sandbox and production, you must create a new service client instance.

bulk_service_manager = BulkServiceManager(
    authorization_data=authorization_data, 
    version = 13,
    poll_interval_in_milliseconds = 5000, 
    environment = 'sandbox',
)

customer_service = ServiceClient(
    'CustomerManagementService', 
    version = 13,
    authorization_data=authorization_data, 
    environment = 'sandbox',
)

reporting_service_manager = ReportingServiceManager(
    authorization_data=authorization_data, 
    version = 13,
    poll_interval_in_milliseconds = 5000, 
    environment = 'sandbox',
)

使用 OAuth

必应广告 SDK 支持 OAuth 2.0 授权框架中详细定义的标准 OAuth 2.0 流。SDK 中的 OAuth 类提取低级用户授权详细信息,例如设置授权和重定向 URI 的格式、设置请求标头以及分析重定向流量和响应流。 若要将 OAuth 与必应广告 .NET SDK 配合使用,必须将 AuthorizationData 对象的 Authentication 属性设置为身份验证派生类,例如 OAuthWebAuthCodeGrantOAuthDesktopMobileAuthCodeGrantOAuthDesktopMobileImplicitGrant

对于重复或长期身份验证,应遵循授权代码授予流来获取访问令牌。 以下步骤遵循授权代码授予流。 有关注册应用程序和授权代码授予流的详细信息,请参阅 使用 OAuth 进行身份验证

  1. 创建 OAuthWebAuthCodeGrant 的实例,该实例将用于管理 Microsoft 帐户用户授权。 将客户端 ID (已注册的应用程序 ID) 、客户端密码 (注册的密码) 和重定向 URI 替换为注册应用程序时配置的值。

    var oAuthWebAuthCodeGrant = new OAuthWebAuthCodeGrant(ClientId, ClientSecret, new Uri(RedirectionUri), ApiEnvironment);
    
    // It is recommended that you specify a non guessable 'state' request parameter to help prevent
    // cross site request forgery (CSRF). 
    oAuthWebAuthCodeGrant.State = "ClientStateGoesHere";
    
    OAuthWebAuthCodeGrant oAuthWebAuthCodeGrant = new OAuthWebAuthCodeGrant(ClientId, ClientSecret, new URL(RedirectionUri), ApiEnvironment);
    
    // It is recommended that you specify a non guessable 'state' request parameter to help prevent
    // cross site request forgery (CSRF). 
    oAuthWebAuthCodeGrant.setState("ClientStateGoesHere");
    
    // Prepare the OAuth object for use with the authorization code grant flow. 
    // It is recommended that you specify a non guessable 'state' request parameter to help prevent
    // cross site request forgery (CSRF). 
    $authentication = (new OAuthWebAuthCodeGrant())
        ->withClientId(ClientId)
        ->withClientSecret(ClientSecret)
        ->withEnvironment(ApiEnvironment)
        ->withRedirectUri('https://' . $_SERVER['HTTP_HOST'] . RedirectUri)
        ->withState(rand(0,999999999)); 
    
    // Assign this authentication instance to the global authorization_data. 
    
    $_SESSION['AuthorizationData'] = (new AuthorizationData())
        ->withAuthentication($authentication)
        ->withDeveloperToken(AuthHelper::DeveloperToken);
    
    $_SESSION['state'] = $_SESSION['AuthorizationData']->Authentication->State;
    
    oauth_web_auth_code_grant = OAuthWebAuthCodeGrant(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        env=ENVIRONMENT,
        redirection_uri=REDIRECTION_URI
    )
    
    # It is recommended that you specify a non guessable 'state' request parameter to help prevent
    # cross site request forgery (CSRF). 
    oauth_web_auth_code_grant.state="ClientStateGoesHere"
    
  2. 通过 Web 浏览器控件连接到 Microsoft 帐户授权终结点,请求用户同意。 调用在上一步中创建的 OAuthWebAuthCodeGrant 实例的 GetAuthorizationEndpoint 方法。

    return Redirect(oAuthWebAuthCodeGrant.GetAuthorizationEndpoint().ToString());
    
    URL authorizationEndpoint = oAuthWebAuthCodeGrant.getAuthorizationEndpoint();
    response.sendRedirect(authorizationEndpoint.toString());
    
    // The user needs to provide consent for the application to access their Microsoft Advertising accounts.
    header('Location: '. $_SESSION['AuthorizationData']->Authentication->GetAuthorizationEndpoint());
    
    oauth_web_auth_code_grant.get_authorization_endpoint()
    

    系统会通过 Microsoft 帐户授权 Web 浏览器控件提示用户授予应用程序管理其 Microsoft Advertising 帐户的权限。

    授权服务使用重定向 URI 调用回应用程序,如果用户授权应用程序管理其 Microsoft Advertising 帐户,该 URI 将包含授权代码。 例如,如果用户授予应用程序管理其 Microsoft Advertising 帐户的权限,则回调 URL 包含如下授权代码: https://contoso.com/redirect/?code=CODE&state=ClientStateGoesHere。 如果用户授予应用程序管理其 Microsoft Advertising 帐户的权限,则应在下一步中立即使用该代码。 授权代码的短时间(大约 5 分钟)可能会更改。

    如果用户拒绝了应用程序管理其 Microsoft Advertising 帐户的权限,则回调 URI 包括错误和错误说明字段,如下所示: REDIRECTURI?error=access_denied&error_description=ERROR_DESCRIPTION&state=ClientStateGoesHere

  3. 使用授权代码请求访问令牌和刷新令牌。 使用 OAuthWebAuthCodeGrant 实例请求访问令牌和刷新令牌时传递完整的回调 URI。

    if (Request["code"] != null)
    {
        await oAuthWebAuthCodeGrant.RequestAccessAndRefreshTokensAsync(Request.Url);
    }
    
    if (request.getParameter("code") != null)
    {
        oAuthWebAuthCodeGrant.requestAccessAndRefreshTokens(new URL(request.getRequestURL() + "?" + request.getQueryString()));
    }
    
    if($_GET['code'] != null)
    {   
        $_SESSION['AuthorizationData']->Authentication->RequestOAuthTokensByResponseUri($_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
    
        header('Location: '. '/CallBingAdsServices.php');
    }
    
    oauth_web_auth_code_grant.request_oauth_tokens_by_response_uri(RESPONSE_URI)
    oauth_tokens = oauth_web_auth_code_grant.oauth_tokens
    access_token = oauth_tokens.access_token
    

    如果此步骤成功,则应用程序有权管理用户的 Microsoft Advertising 帐户。 若要调用必应广告 API 服务操作,应使用包含 OAuthWebAuthCodeGrant 实例的 AuthorizationData 初始化 Service ClientBulk Service ManagerReporting Service Manager

    有关详细信息,请参阅 使用 AuthorizationData使用服务客户端使用 BulkServiceManager 和使用 ReportingServiceManager

    注意

    BulkServiceManagerReportingServiceManager 可用于 .NET、Java 和 Python SDK。

  4. 使用服务客户端批量Service Manager报告Service Manager调用必应广告 API 服务操作时,请务必在收到新的 OAuth 令牌时保存最新的刷新令牌。

    // If you already have a refresh token, use it to request new access and refresh tokens.
    
    if (GetRefreshToken(out refreshToken))
    {
        oAuthWebAuthCodeGrant.RequestAccessAndRefreshTokensAsync(refreshToken);
    }
    
    // When calling Bing Ads API service operations with Service Client, Bulk Service Manager, or Reporting Service Manager, 
    // each instance will refresh your access token automatically if they detect the AuthenticationTokenExpired (109) error code. 
    // It is important to save the most recent refresh token whenever new OAuth tokens are received. 
    // You will want to subscribe to the NewOAuthTokensReceived event handler.
    
    oAuthWebAuthCodeGrant.NewOAuthTokensReceived += 
        (sender, args) => SaveRefreshToken(args.NewRefreshToken);
    
    // If you already have a refresh token, use it to request new access and refresh tokens.
    
    if (refreshToken != null)
    {
        oAuthWebAuthCodeGrant.requestAccessAndRefreshTokens(refreshToken);
    }
    
    // When calling Bing Ads API service operations with Service Client, Bulk Service Manager, or Reporting Service Manager, 
    // each instance will refresh your access token automatically if they detect the AuthenticationTokenExpired (109) error code. 
    // It is important to save the most recent refresh token whenever new OAuth tokens are received. 
    // You will want to implement event handling using the NewOAuthTokensReceivedListener.
    
    oAuthWebAuthCodeGrant.setNewTokensListener(new NewOAuthTokensReceivedListener() {
        @Override
        public void onNewOAuthTokensReceived(OAuthTokens newTokens) {
               saveRefreshToken(newTokens.getRefreshToken());
        }
    });
    
    // If you already have a refresh token, use it to request new access and refresh tokens.
    $_SESSION['AuthorizationData']->Authentication->RequestOAuthTokensByRefreshToken($refreshToken);
    
    # When calling Bing Ads API service operations with Service Client, Bulk Service Manager, or Reporting Service Manager, 
    # each instance will refresh your access token automatically if they detect the AuthenticationTokenExpired (109) error code. 
    # It is important to save the most recent refresh token whenever new OAuth tokens are received. 
    # You will want to register a callback function to automatically save the refresh token anytime it is refreshed. 
    # For example if you defined have a save_refresh_token() method that securely stores your refresh token, 
    # set the authentication token_refreshed_callback property of each OAuthWebAuthCodeGrant instance.
    
    oauth_web_auth_code_grant.token_refreshed_callback=save_refresh_token
    
    # If you already have a refresh token, use it to request new access and refresh tokens.
    
    if refresh_token is not None:
        oauth_web_auth_code_grant.request_oauth_tokens_by_refresh_token(refresh_token)
    

    重要

    刷新令牌最长可以持续 90 天。 无论如何,如果 Microsoft 帐户用户更改了密码、从受信任的设备列表中删除了设备,或者删除了应用程序代表其进行身份验证的权限,则应从步骤 1 重新开始并请求用户同意。

使用 AuthorizationData

AuthorizationData 类包含 Microsoft Advertising 用于授权用户的属性。 Service ClientBulk Service ManagerReporting Service Manager 类可处理常见的请求标头字段,使你能够在 AuthorizationData 对象中为每个服务指定一次 AuthenticationCustomerIdAccountIdDeveloperToken 属性。

注意

BulkServiceManagerReportingServiceManager 可用于 .NET、Java 和 Python SDK。

以下代码块演示如何创建 AuthorizationData 实例并设置其 AuthenticationCustomerIdAccountIdDeveloperToken 属性。

var authorizationData = new AuthorizationData
{
    Authentication = <AuthenticationGoesHere>, 
    CustomerId = <CustomerIdGoesHere>,
    AccountId = <AccountIdGoesHere>,
    DeveloperToken = "<DeveloperTokenGoesHere>"
};
static AuthorizationData authorizationData = new AuthorizationData();
authorizationData.setAuthentication(<AuthenticationGoesHere>);
authorizationData.setCustomerId("<CustomerIdGoesHere>");
authorizationData.setAccountId("<AccountIdGoesHere>");
authorizationData.setDeveloperToken("<DeveloperTokenGoesHere>");
$authorizationData = (new AuthorizationData())
    ->withAuthentication($AuthenticationGoesHere)
    ->withCustomerId($CustomerIdGoesHere)
    ->withAccountId($AccountIdGoesHere)
    ->withDeveloperToken($DeveloperTokenGoesHere);
authorization_data = AuthorizationData(
    authentication = <AuthenticationGoesHere>,
    customer_id = <CustomerIdGoesHere>,
    account_id = <AccountIdGoesHere>,
    developer_token = '<DeveloperTokenGoesHere>'
)

Authentication 属性必须设置为身份验证派生类,例如 OAuthWebAuthCodeGrantOAuthDesktopMobileAuthCodeGrantOAuthDesktopMobileImplicitGrant

某些服务(如 Customer Management)不接受 CustomerIdCustomerAccountId 标头,因此,如果在 AuthorizationData 对象中指定它们,它们将被忽略。

使用服务客户端

可以使用 ServiceClient 类的实例来调用其中一个 Microsoft Advertising Web 服务的任何方法。 ServiceClient 类处理常见的请求标头字段,允许为每个服务在 AuthorizationData 对象中指定一次 AuthenticationCustomerIdAccountIdDeveloperToken 属性。

提示

如果使用批量或报告服务,请使用批量Service Manager报告Service Manager而不是 ServiceClient。 例如,批量Service Manager会将下载请求提交到批量服务,轮询服务直到完成,然后将文件下载到请求中指定的本地目录。 你将节省更多时间,因为无需编写或分析上传文件或结果文件。

// The primary method of the ServiceClient class is CallAsync. The method parameter is the delegate 
// for the service operation that you want to call. The request parameter of this method must be a 
// request message corresponding to the name of the service operation specified by the first request parameter. 
// The request message must match the service operation that is specified as the delegate in the first request.

public async Task<TResponse> CallAsync<TRequest, TResponse>(
    Func<TService, TRequest, Task<TResponse>> method, TRequest request)

// In the following sample, the method delegate is (s, r) => s.GetUserAsync(r) which takes a GetUserRequest 
// message as the request parameter (TRequest) and returns a GetUserResponse message (TResponse).

private async Task<User> GetUserAsync(long? userId)
{
    var request = new GetUserRequest
    {
        UserId = userId
    };

    return (await _customerService.CallAsync((s, r) => s.GetUserAsync(r), request)).User;
}
// You can use the Customer Management service to get the current authenticated user.

ServiceClient<ICustomerManagementService> CustomerService = new ServiceClient<ICustomerManagementService>(
		authorizationData, 
		ICustomerManagementService.class);

java.lang.Long userId = null;
final GetUserRequest getUserRequest = new GetUserRequest();
getUserRequest.setUserId(userId);

// If you updated the authorization data such as account ID or you want to call a new operation, 
// you must call getService to set the latest request headers. 
// As a best practice you should use getService when calling any service operation.
User user = CustomerService.getService().getUser(getUserRequest).getUser();
// You can use a single instance of the ServiceClient class to call any methods in the service, 
// for example you can set the CustomerManagementVersion13 service client type as follows.

$customerProxy = new ServiceClient(ServiceClientType::CustomerManagementVersion13, $authorizationData, ApiEnvironment::Sandbox);
)
# You can use the Customer Management service to get the current authenticated user.

customer_service = ServiceClient(
    'CustomerManagementService', 
    version = 13,
    authorization_data=authorization_data, 
    environment = ENVIRONMENT,
)

user = customer_service.GetUser(UserId = None).User

重要

如果在请求参数(例如 GetUserRequest)中设置 AuthenticationTokenCustomerIdAccountIdDeveloperToken 标头元素,它们将被忽略。 服务客户端 始终使用初始化时提供的 AuthorizationData

另请参阅

沙盒
必应广告 API 代码示例
必应广告 API Web 服务地址