チュートリアル: C でのBing Ads API Desktop アプリケーション#
この例の C# コンソール アプリケーションは、指定した資格情報を使用してユーザーの同意を求め、認証されたユーザーがアクセスできるアカウントを取得します。
最初にアプリケーションを登録し、クライアント ID (登録済みアプリケーション ID) を書き留めておく必要があります。 アプリケーションの登録と承認コード付与フローの詳細については、「 OAuth による認証」を参照してください。
運用 開発者トークンも必要です。 以下で説明するように、サンプルを段階的に作成するか、 GitHub からより多くの例をダウンロードできます。
コードチュートリアル
Visual Studio 開発環境を開きます。
ファイル -New ->>Project を使用して新しいプロジェクトを作成する
[ 新しいプロジェクト ] ウィンドウで、ドロップダウンで [.NET Framework 4.8 ] を選択し、[ コンソール アプリ (.NET Framework)] テンプレートをクリックします。 プロジェクトに BingAdsConsoleApp という名前を付け、[OK] をクリック します。
BingAdsConsoleApp 用の NuGet を使用して SDK をインストールします。 依存関係の詳細については、「 SDK のインストール」を参照してください。 [ツール] ->[NuGet パッケージ マネージャー] -[パッケージ マネージャー コンソール] の順>にクリックします。 プロンプトで、次のコマンドを入力して、パッケージを一度に 1 つずつインストールします。
Install-Package Microsoft.BingAds.SDK
とInstall-Package System.Configuration.ConfigurationManager
です。App.config ファイルを開き、その内容を次のコード ブロックに置き換えます。 BingAdsEnvironment を編集して、サンドボックスから運用環境に移行します。 運用環境を対象とする場合は、 4c0b021c-00c3-4508-838f-d3127e8167ff を、運用アプリケーションを登録したときにプロビジョニングされた アプリケーション ID に置き換え、 BBD37VB98 を運用 開発者トークンに置き換える必要があります。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="BingAdsConsoleApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> </sectionGroup> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" /> </startup> <appSettings> <!-- To use the production environment, set this value to "Production". --> <add key="BingAdsEnvironment" value="Sandbox"/> <add key="ClientSettingsProvider.ServiceUri" value=""/> </appSettings> <userSettings> <BingAdsConsoleApp.Properties.Settings> <setting name="DeveloperToken" serializeAs="String"> <value>BBD37VB98</value> </setting> <setting name="ClientId" serializeAs="String"> <value>4c0b021c-00c3-4508-838f-d3127e8167ff</value> </setting> </BingAdsConsoleApp.Properties.Settings> </userSettings> </configuration>
設定ファイルを作成します。 BingAdsConsoleApp のプロジェクト ビューで、[ プロパティ ] を右クリックし、[ 開く] をクリックします。 [ 設定] をクリックし、テキストをクリックします 。プロジェクトには既定の設定ファイルが含まれていません。ここをクリックして作成します。 app.config からの新しい値が自動的に追加されます。
Program.cs ファイルを開き、その内容を次のコード ブロックに置き換えます。
using System; using System.Linq; using System.Configuration; using System.Net.Http; using System.ServiceModel; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.BingAds; using Microsoft.BingAds.V13.CustomerManagement; using BingAdsConsoleApp.Properties; using System.IO; namespace BingAdsConsoleApp { class Program { private static AuthorizationData _authorizationData; private static ServiceClient<ICustomerManagementService> _customerManagementService; private static string ClientState = "ClientStateGoesHere"; static void Main(string[] args) { try { Authentication authentication = AuthenticateWithOAuth(); // Most Bing Ads API service operations require account and customer ID. // This utiltiy operation sets the global authorization data instance // to the first account that the current authenticated user can access. SetAuthorizationDataAsync(authentication).Wait(); // You can extend the console app with the examples library at: // https://github.com/BingAds/BingAds-dotNet-SDK/tree/main/examples/BingAdsExamples } // Catch authentication exceptions catch (OAuthTokenRequestException ex) { OutputStatusMessage(string.Format("OAuthTokenRequestException Message:\n{0}", ex.Message)); if (ex.Details != null) { OutputStatusMessage(string.Format("OAuthTokenRequestException Details:\nError: {0}\nDescription: {1}", ex.Details.Error, ex.Details.Description)); } } // Catch Customer Management service exceptions catch (FaultException<AdApiFaultDetail> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => { if ((error.Code == 105) || (error.Code == 106)) { return "Authorization data is missing or incomplete for the specified environment.\n" + "To run the examples switch users or contact support for help with the following error.\n"; } return string.Format("{0}: {1}", error.Code, error.Message); }))); OutputStatusMessage(string.Join("; ", ex.Detail.Errors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (FaultException<Microsoft.BingAds.V13.CustomerManagement.ApiFault> ex) { OutputStatusMessage(string.Join("; ", ex.Detail.OperationErrors.Select(error => string.Format("{0}: {1}", error.Code, error.Message)))); } catch (HttpRequestException ex) { OutputStatusMessage(ex.Message); } } /// <summary> /// Utility method for setting the customer and account identifiers within the global /// <see cref="_authorizationData"/> instance. /// </summary> /// <param name="authentication">The OAuth authentication credentials.</param> /// <returns></returns> private static async Task SetAuthorizationDataAsync(Authentication authentication) { _authorizationData = new AuthorizationData { Authentication = authentication, DeveloperToken = Settings.Default["DeveloperToken"].ToString() }; var apiEnvironment = ConfigurationManager.AppSettings["BingAdsEnvironment"] == ApiEnvironment.Sandbox.ToString() ? ApiEnvironment.Sandbox : ApiEnvironment.Production; _customerManagementService = new ServiceClient<ICustomerManagementService>( _authorizationData, apiEnvironment ); var getUserRequest = new GetUserRequest { UserId = null }; var getUserResponse = (await _customerManagementService.CallAsync((s, r) => s.GetUserAsync(r), getUserRequest)); var user = getUserResponse.User; var predicate = new Predicate { Field = "UserId", Operator = PredicateOperator.Equals, Value = user.Id.ToString() }; var paging = new Paging { Index = 0, Size = 10 }; var searchAccountsRequest = new SearchAccountsRequest { Ordering = null, PageInfo = paging, Predicates = new[] { predicate } }; var searchAccountsResponse = (await _customerManagementService.CallAsync((s, r) => s.SearchAccountsAsync(r), searchAccountsRequest)); var accounts = searchAccountsResponse.Accounts.ToArray(); if (accounts.Length <= 0) return; _authorizationData.AccountId = (long)accounts[0].Id; _authorizationData.CustomerId = (int)accounts[0].ParentCustomerId; OutputArrayOfAdvertiserAccount(accounts); return; } /// <summary> /// Authenticates the current user via OAuth. /// </summary> /// <returns>The OAuth authentication instance for a user.</returns> private static Authentication AuthenticateWithOAuth() { var apiEnvironment = ConfigurationManager.AppSettings["BingAdsEnvironment"] == ApiEnvironment.Sandbox.ToString() ? ApiEnvironment.Sandbox : ApiEnvironment.Production; var oAuthDesktopMobileAuthCodeGrant = new OAuthDesktopMobileAuthCodeGrant( Settings.Default["ClientId"].ToString(), apiEnvironment ); // It is recommended that you specify a non guessable 'state' request parameter to help prevent // cross site request forgery (CSRF). oAuthDesktopMobileAuthCodeGrant.State = ClientState; string refreshToken; // If you have previously securely stored a refresh token, try to use it. if (GetRefreshToken(out refreshToken)) { AuthorizeWithRefreshTokenAsync(oAuthDesktopMobileAuthCodeGrant, refreshToken).Wait(); } else { // You must request user consent at least once through a web browser control. Console.WriteLine(string.Format( "Open a new web browser and navigate to {0}\n\n" + "Grant consent in the web browser for the application to access " + "your advertising accounts, and then enter the response URI that includes " + "the authorization 'code' parameter: \n", oAuthDesktopMobileAuthCodeGrant.GetAuthorizationEndpoint()) ); // Request access and refresh tokens using the URI that you provided manually during program execution. var responseUri = new Uri(Console.ReadLine()); if (oAuthDesktopMobileAuthCodeGrant.State != ClientState) throw new HttpRequestException("The OAuth response state does not match the client request state."); oAuthDesktopMobileAuthCodeGrant.RequestAccessAndRefreshTokensAsync(responseUri).Wait(); SaveRefreshToken(oAuthDesktopMobileAuthCodeGrant.OAuthTokens.RefreshToken); } // 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. // When calling Bing Ads API service operations with ServiceClient<TService>, BulkServiceManager, or ReportingServiceManager, // each instance will refresh your access token automatically if they detect the AuthenticationTokenExpired (109) error code. oAuthDesktopMobileAuthCodeGrant.NewOAuthTokensReceived += (sender, tokens) => SaveRefreshToken(tokens.NewRefreshToken); return oAuthDesktopMobileAuthCodeGrant; } /// <summary> /// Requests new access and refresh tokens given an existing refresh token. /// </summary> /// <param name="authentication">The OAuth authentication instance for a user.</param> /// <param name="refreshToken">The previous refresh token.</param> /// <returns></returns> private static Task<OAuthTokens> AuthorizeWithRefreshTokenAsync( OAuthDesktopMobileAuthCodeGrant authentication, string refreshToken) { return authentication.RequestAccessAndRefreshTokensAsync(refreshToken); } /// <summary> /// You should modify the example, and store the refresh token securely. /// </summary> /// <param name="newRefreshtoken">The refresh token to save.</param> private static void SaveRefreshToken(string newRefreshtoken) { if (newRefreshtoken != null) { using (StreamWriter outputFile = new StreamWriter( Environment.CurrentDirectory + @"\refreshtoken.txt", false)) { outputFile.WriteLine(newRefreshtoken); } } } /// <summary> /// Returns the prior refresh token if available. /// </summary> /// <param name="refreshToken"></param> /// <returns>The latest stored refresh token.</returns> private static bool GetRefreshToken(out string refreshToken) { var filePath = Environment.CurrentDirectory + @"\refreshtoken.txt"; if (!File.Exists(filePath)) { refreshToken = null; return false; } String fileContents; using (StreamReader sr = new StreamReader(filePath)) { fileContents = sr.ReadToEnd(); } if (string.IsNullOrEmpty(fileContents)) { refreshToken = null; return false; } try { refreshToken = fileContents; return true; } catch (FormatException) { refreshToken = null; return false; } } #region OutputHelpers /** * You can extend the console app with the example helpers at: * https://github.com/BingAds/BingAds-dotNet-SDK/tree/main/examples/BingAdsExamples **/ private static void OutputArrayOfAdvertiserAccount(IList<AdvertiserAccount> dataObjects) { if (null != dataObjects) { foreach (var dataObject in dataObjects) { OutputAdvertiserAccount(dataObject); OutputStatusMessage("\n"); } } } private static void OutputAdvertiserAccount(AdvertiserAccount dataObject) { if (null != dataObject) { OutputStatusMessage(string.Format("BillToCustomerId: {0}", dataObject.BillToCustomerId)); OutputStatusMessage(string.Format("CurrencyCode: {0}", dataObject.CurrencyCode)); OutputStatusMessage(string.Format("AccountFinancialStatus: {0}", dataObject.AccountFinancialStatus)); OutputStatusMessage(string.Format("Id: {0}", dataObject.Id)); OutputStatusMessage(string.Format("Language: {0}", dataObject.Language)); OutputStatusMessage(string.Format("LastModifiedByUserId: {0}", dataObject.LastModifiedByUserId)); OutputStatusMessage(string.Format("LastModifiedTime: {0}", dataObject.LastModifiedTime)); OutputStatusMessage(string.Format("Name: {0}", dataObject.Name)); OutputStatusMessage(string.Format("Number: {0}", dataObject.Number)); OutputStatusMessage(string.Format("ParentCustomerId: {0}", dataObject.ParentCustomerId)); OutputStatusMessage(string.Format("PaymentMethodId: {0}", dataObject.PaymentMethodId)); OutputStatusMessage(string.Format("PaymentMethodType: {0}", dataObject.PaymentMethodType)); OutputStatusMessage(string.Format("PrimaryUserId: {0}", dataObject.PrimaryUserId)); OutputStatusMessage(string.Format("AccountLifeCycleStatus: {0}", dataObject.AccountLifeCycleStatus)); OutputStatusMessage(string.Format("TimeStamp: {0}", dataObject.TimeStamp)); OutputStatusMessage(string.Format("TimeZone: {0}", dataObject.TimeZone)); OutputStatusMessage(string.Format("PauseReason: {0}", dataObject.PauseReason)); OutputArrayOfKeyValuePairOfstringstring(dataObject.ForwardCompatibilityMap); OutputArrayOfCustomerInfo(dataObject.LinkedAgencies); OutputStatusMessage(string.Format("SalesHouseCustomerId: {0}", dataObject.SalesHouseCustomerId)); OutputArrayOfKeyValuePairOfstringstring(dataObject.TaxInformation); OutputStatusMessage(string.Format("BackUpPaymentInstrumentId: {0}", dataObject.BackUpPaymentInstrumentId)); OutputStatusMessage(string.Format("BillingThresholdAmount: {0}", dataObject.BillingThresholdAmount)); OutputAddress(dataObject.BusinessAddress); OutputStatusMessage(string.Format("AutoTagType: {0}", dataObject.AutoTagType)); OutputStatusMessage(string.Format("SoldToPaymentInstrumentId: {0}", dataObject.SoldToPaymentInstrumentId)); } } private static void OutputAddress(Address dataObject) { if (null != dataObject) { OutputStatusMessage(string.Format("City: {0}", dataObject.City)); OutputStatusMessage(string.Format("CountryCode: {0}", dataObject.CountryCode)); OutputStatusMessage(string.Format("Id: {0}", dataObject.Id)); OutputStatusMessage(string.Format("Line1: {0}", dataObject.Line1)); OutputStatusMessage(string.Format("Line2: {0}", dataObject.Line2)); OutputStatusMessage(string.Format("Line3: {0}", dataObject.Line3)); OutputStatusMessage(string.Format("Line4: {0}", dataObject.Line4)); OutputStatusMessage(string.Format("PostalCode: {0}", dataObject.PostalCode)); OutputStatusMessage(string.Format("StateOrProvince: {0}", dataObject.StateOrProvince)); OutputStatusMessage(string.Format("TimeStamp: {0}", dataObject.TimeStamp)); OutputStatusMessage(string.Format("BusinessName: {0}", dataObject.BusinessName)); } } private static void OutputArrayOfKeyValuePairOfstringstring(IList<KeyValuePair<string, string>> dataObjects) { if (null != dataObjects) { foreach (var dataObject in dataObjects) { OutputKeyValuePairOfstringstring(dataObject); } } } private static void OutputKeyValuePairOfstringstring(KeyValuePair<string, string> dataObject) { if (null != dataObject.Key) { OutputStatusMessage(string.Format("key: {0}", dataObject.Key)); OutputStatusMessage(string.Format("value: {0}", dataObject.Value)); } } private static void OutputCustomerInfo(CustomerInfo dataObject) { if (null != dataObject) { OutputStatusMessage(string.Format("Id: {0}", dataObject.Id)); OutputStatusMessage(string.Format("Name: {0}", dataObject.Name)); } } private static void OutputArrayOfCustomerInfo(IList<CustomerInfo> dataObjects) { if (null != dataObjects) { foreach (var dataObject in dataObjects) { OutputCustomerInfo(dataObject); OutputStatusMessage("\n"); } } } private static void OutputStatusMessage(String msg) { Console.WriteLine(msg); } #endregion OutputHelpers } }
[ ビルド ] ->[ビルド] [BingAdsConsoleApp] の順にクリックし、アプリケーションを実行します。 アプリケーションを起動すると、運用環境で認証するための Microsoft アカウント資格情報が既定で求められます。
サンドボックスの構成
サンドボックスを使用するには、プロジェクト ルートのApp.configファイルの appSettings ノード内で< BingAdsEnvironment> キーを Sandbox に設定します。
<add key="BingAdsEnvironment" value ="Sandbox"/>
また、各 ServiceClient の環境を次のように個別に設定することもできます。
_customerManagementService = new ServiceClient<ICustomerManagementService>(
_authorizationData,
ApiEnvironment.Sandbox
);
ServiceClient 環境をグローバルまたは個別に設定する場合でも、個別に OAuth 環境をサンドボックスに設定する必要もあります。
var oAuthDesktopMobileAuthCodeGrant = new OAuthDesktopMobileAuthCodeGrant(
ClientId,
ApiEnvironment.Sandbox
);