bing_ads_api_v9 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +74 -0
  3. data/lib/ads_common_for_bing_ads.rb +47 -0
  4. data/lib/ads_common_for_bing_ads/api_config.rb +41 -0
  5. data/lib/ads_common_for_bing_ads/auth/client_login_handler.rb +161 -0
  6. data/lib/ads_common_for_bing_ads/auth/oauth2_handler.rb +33 -0
  7. data/lib/ads_common_for_bing_ads/build/savon_generator.rb +23 -0
  8. data/lib/ads_common_for_bing_ads/build/savon_registry.rb +17 -0
  9. data/lib/ads_common_for_bing_ads/parameters_validator.rb +36 -0
  10. data/lib/ads_common_for_bing_ads/savon_headers/base_header_handler.rb +13 -0
  11. data/lib/ads_common_for_bing_ads/savon_headers/client_login_header_handler.rb +24 -0
  12. data/lib/ads_common_for_bing_ads/savon_headers/oauth_header_handler.rb +31 -0
  13. data/lib/ads_common_for_bing_ads/savon_headers_base_header_handler.rb +9 -0
  14. data/lib/ads_common_for_bing_ads/savon_service.rb +143 -0
  15. data/lib/bing_ads_api.rb +215 -0
  16. data/lib/bing_ads_api/api_config.rb +164 -0
  17. data/lib/bing_ads_api/client_login_header_handler.rb +21 -0
  18. data/lib/bing_ads_api/credential_handler.rb +91 -0
  19. data/lib/bing_ads_api/errors.rb +564 -0
  20. data/lib/bing_ads_api/report_header_handler.rb +46 -0
  21. data/lib/bing_ads_api/report_utils.rb +202 -0
  22. data/lib/bing_ads_api/v8/ad_intelligence_service.rb +86 -0
  23. data/lib/bing_ads_api/v8/ad_intelligence_service_registry.rb +30 -0
  24. data/lib/bing_ads_api/v8/administration_service.rb +38 -0
  25. data/lib/bing_ads_api/v8/administration_service_registry.rb +30 -0
  26. data/lib/bing_ads_api/v8/bulk_service.rb +42 -0
  27. data/lib/bing_ads_api/v8/bulk_service_registry.rb +30 -0
  28. data/lib/bing_ads_api/v8/campaign_management_service.rb +390 -0
  29. data/lib/bing_ads_api/v8/campaign_management_service_registry.rb +30 -0
  30. data/lib/bing_ads_api/v8/customer_billing_service.rb +62 -0
  31. data/lib/bing_ads_api/v8/customer_billing_service_registry.rb +30 -0
  32. data/lib/bing_ads_api/v8/customer_management_service.rb +162 -0
  33. data/lib/bing_ads_api/v8/customer_management_service_registry.rb +30 -0
  34. data/lib/bing_ads_api/v8/notification_service.rb +38 -0
  35. data/lib/bing_ads_api/v8/notification_service_registry.rb +30 -0
  36. data/lib/bing_ads_api/v8/optimizer_service.rb +46 -0
  37. data/lib/bing_ads_api/v8/optimizer_service_registry.rb +30 -0
  38. data/lib/bing_ads_api/v8/reporting_service.rb +38 -0
  39. data/lib/bing_ads_api/v8/reporting_service_registry.rb +30 -0
  40. data/lib/bing_ads_api/v9/ad_intelligence_service.rb +86 -0
  41. data/lib/bing_ads_api/v9/ad_intelligence_service_registry.rb +30 -0
  42. data/lib/bing_ads_api/v9/bulk_service.rb +58 -0
  43. data/lib/bing_ads_api/v9/bulk_service_registry.rb +30 -0
  44. data/lib/bing_ads_api/v9/campaign_management_service.rb +298 -0
  45. data/lib/bing_ads_api/v9/campaign_management_service_registry.rb +30 -0
  46. data/lib/bing_ads_api/v9/customer_billing_service.rb +66 -0
  47. data/lib/bing_ads_api/v9/customer_billing_service_registry.rb +30 -0
  48. data/lib/bing_ads_api/v9/customer_management_service.rb +154 -0
  49. data/lib/bing_ads_api/v9/customer_management_service_registry.rb +30 -0
  50. data/lib/bing_ads_api/v9/optimizer_service.rb +62 -0
  51. data/lib/bing_ads_api/v9/optimizer_service_registry.rb +30 -0
  52. data/lib/bing_ads_api/v9/reporting_service.rb +38 -0
  53. data/lib/bing_ads_api/v9/reporting_service_registry.rb +30 -0
  54. data/lib/bing_ads_api/version.rb +5 -0
  55. data/rakefile.rb +54 -0
  56. metadata +168 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9b3aed5be42fde099fa6a30ce66e69835ed547c6
4
+ data.tar.gz: fc5b869aff5c3da8d8d319433cd56c0cff41b9a8
5
+ SHA512:
6
+ metadata.gz: c2a05c573391798cd031e405a4f9762db6cc8f823b29a9b79978b7aa70da15566f8d917797755685a88abbd52f47feda71e118a8edd94cea330051ce83fd6b9d
7
+ data.tar.gz: 18e4da0cfe5b37162539deddb1784d5e35ba49573ed8541649fb18b8e6704320dc3e24175f32d791dc810a6eed63eb524555ada0315107a86cb01070390fcd27
@@ -0,0 +1,74 @@
1
+ Bing Ads Api Client
2
+ =============
3
+
4
+ Description
5
+ -------------
6
+ A simple ruby wrapper for the Bing Ads API based on the gem "google-ads-common".
7
+
8
+ Usage
9
+ -------------
10
+
11
+ # install in your gem file
12
+ gem 'bing_ads_api', :git => 'https://github.com/arambert/bing_ads_api.git'
13
+
14
+ # initialize the client
15
+ client = BingAdsApi::Api.new(
16
+ {
17
+ :authentication => {
18
+ :method => 'ClientLogin',
19
+ :developer_token => 'DEVELOPER_TOKEN',
20
+ :user_name => 'USERNAME',
21
+ :password => 'PASSWORD',
22
+ :customer_id => 'customer_id', # may be optional for some requests
23
+ :customer_account_id => 'customer_account_id' # may be optional for some requests
24
+ },
25
+ :service => {:environment => 'PRODUCTION'},
26
+ :library => {:log_level => 'DEBUG'}
27
+ })
28
+
29
+ oauth2_client = BingAdsApi::Api.new(
30
+ {
31
+ :authentication => {
32
+ :method => 'OAUTH2',
33
+ :developer_token => Developer Token,
34
+ :oauth2_client_id: Client Id From Bing,
35
+ :oauth2_client_secret: Secret Client From Bing,
36
+ :oauth2_callback: http://myservice.com/adcenter_oauth2, #public callback
37
+ :oauth2_token => {
38
+ :access_token => Access Token,
39
+ :refresh_token => Refresh Token
40
+ }
41
+ },
42
+ :service => {:environment => 'PRODUCTION'},
43
+ :library => {:log_level => 'DEBUG'}
44
+ })
45
+
46
+ # select the service and the API version (:v8 or :v9)
47
+ administration_service = client.service(:AdministrationService, :v9)
48
+
49
+ # send your request
50
+ result = administration_service.get_assigned_quota()
51
+
52
+ # select another service
53
+ campaign_service = client.service(:CampaignManagementService, :v9)
54
+
55
+ # send another request
56
+ result = campaign_service.get_campaigns_by_account_id({:account_id => 00000})
57
+
58
+ # create a campaign
59
+ result2 = campaign_service.add_campaigns({:account_id => 00000,
60
+ :campaigns => {:campaign => [{:budget_type => "DailyBudgetWithMaximumMonthlySpend",
61
+ :conversion_tracking_enabled => false,
62
+ :daily_budget => 5,
63
+ :daylight_saving => false,
64
+ :description => "A perfect new campaign",
65
+ :monthly_budget => 50,
66
+ :name => "perfectcampaign",
67
+ :time_zone => "BrusselsCopenhagenMadridParis"}]
68
+ }
69
+ })
70
+
71
+ About the gem
72
+ -------------
73
+ The tests still have to be written.
74
+ Any help is welcome !
@@ -0,0 +1,47 @@
1
+ require 'ads_common/api'
2
+ require 'ads_common/api_config'
3
+ require 'ads_common/credential_handler'
4
+ require 'ads_common/errors'
5
+ require 'ads_common/http'
6
+ require 'ads_common/savon_service'
7
+ require 'ads_common/parameters_validator'
8
+ require 'ads_common/build/savon_generator'
9
+ require 'ads_common/build/savon_registry'
10
+ require 'ads_common/savon_headers/base_header_handler'
11
+ require 'ads_common/savon_headers/oauth_header_handler'
12
+
13
+ ####### AdsCommon Overriden for Bing Ads #########
14
+ module AdsCommonForBingAds
15
+ class Api < AdsCommon::Api; end
16
+ module ApiConfig; include AdsCommon::ApiConfig; end
17
+ class Config < AdsCommon::Config; end
18
+ class CredentialHandler < AdsCommon::CredentialHandler; end
19
+ module Errors; include AdsCommon::Errors; end
20
+ class Http < AdsCommon::Http; end
21
+ class ParametersValidator < AdsCommon::ParametersValidator; end
22
+ class ResultsExtractor < AdsCommon::ResultsExtractor; end
23
+ class SavonService < AdsCommon::SavonService; end
24
+ module Utils; include AdsCommon::Utils; end
25
+ module ApiConfig; include AdsCommon::ApiConfig; end
26
+ # Auth
27
+ module Auth
28
+ class BaseHandler < AdsCommon::Auth::BaseHandler; end
29
+ class ClientLoginHandler < AdsCommon::Auth::ClientLoginHandler; end
30
+ class OAuth2Handler < AdsCommon::Auth::OAuth2Handler; end
31
+ end
32
+ # Build
33
+ module Build
34
+ class SavonAbstractGenerator < AdsCommon::Build::SavonAbstractGenerator; end
35
+ class SavonGenerator < AdsCommon::Build::SavonGenerator; end
36
+ class SavonRegistry < AdsCommon::Build::SavonRegistry; end
37
+ class SavonRegistryGenerator < AdsCommon::Build::SavonRegistryGenerator; end
38
+ class SavonServiceGenerator < AdsCommon::Build::SavonServiceGenerator; end
39
+ end
40
+ # SavonHeaders
41
+ module SavonHeaders
42
+ class BaseHeaderHandler < AdsCommon::SavonHeaders::BaseHeaderHandler; end
43
+ class OAuthHeaderHandler < AdsCommon::SavonHeaders::OAuthHeaderHandler; end
44
+ # httpi_request_proxy is ::OAuth::RequestProxy::HTTPIRequest < OAuth::RequestProxy::Base
45
+ end
46
+
47
+ end
@@ -0,0 +1,41 @@
1
+ ####### Overriden for Bing Ads #########
2
+ AdsCommonForBingAds::ApiConfig.module_eval do
3
+ # Get the endpoint for a service on a given environment and API version.
4
+ #
5
+ # Args:
6
+ # - environment: the service environment to be used
7
+ # - version: the API version
8
+ # - service: the name of the API service
9
+ #
10
+ # Returns:
11
+ # The endpoint URL
12
+ #
13
+ def endpoint(environment, version, service)
14
+ if !address_config().nil?
15
+ address_config()[version][service][environment].to_s
16
+ else
17
+ ""
18
+ end
19
+ end
20
+ # Generates an array of WSDL URLs based on defined Services and version
21
+ # supplied. This method is used by generators to determine what service
22
+ # wrappers to generate.
23
+ #
24
+ # Args:
25
+ # - version: the API version.
26
+ #
27
+ # Returns
28
+ # hash of pairs Service => WSDL URL
29
+ #
30
+ def get_wsdls(version)
31
+ res = {}
32
+ services(version).each do |service|
33
+ if (!address_config().nil?)
34
+ path = address_config()[version][service][default_environment()].to_s
35
+ end
36
+ res[service.to_s] = path || ""
37
+ end
38
+ return res
39
+ end
40
+
41
+ end
@@ -0,0 +1,161 @@
1
+ ####### Overriden for Bing Ads #########
2
+ module AdsCommonForBingAds
3
+ module Auth
4
+
5
+ class ClientLoginHandler
6
+
7
+
8
+ # Invalidates the stored token if the user_name, password or provided auth
9
+ # token have changed.
10
+ def property_changed(prop, value)
11
+ if [:user_name, :password].include?(prop)
12
+ @token = nil
13
+ end
14
+ if :auth_token.eql?(prop)
15
+ @token = create_token_from_string(value)
16
+ end
17
+ end
18
+
19
+ # Handle specific ClientLogin errors.
20
+ def handle_error(error)
21
+ # TODO: Add support for automatically regenerating auth tokens when they
22
+ # expire.
23
+ get_logger().error(error)
24
+ raise error
25
+ end
26
+
27
+ # Returns authorization string.
28
+ def auth_string(credentials, request)
29
+ return [AUTH_PREFIX, get_token(credentials)].join
30
+ end
31
+
32
+ private
33
+
34
+ # Auxiliary method to validate the credentials for token generation.
35
+ #
36
+ # Args:
37
+ # - credentials: a hash with the credentials for the account being
38
+ # accessed
39
+ #
40
+ # Raises:
41
+ # - AdsCommonForBingAds::Errors::AuthError if validation fails
42
+ #
43
+ def validate_credentials(credentials)
44
+ if credentials.nil?
45
+ raise AdsCommonForBingAds::Errors::AuthError, 'No credentials supplied.'
46
+ end
47
+
48
+ if credentials[:auth_token].nil?
49
+ if credentials[:user_name].nil?
50
+ raise AdsCommonForBingAds::Errors::AuthError,
51
+ 'UserName address not included in credentials.'
52
+ end
53
+ if credentials[:password].nil?
54
+ raise AdsCommonForBingAds::Errors::AuthError,
55
+ 'Password not included in credentials.'
56
+ end
57
+ else
58
+ if credentials[:user_name] and credentials[:password]
59
+ get_logger().warn('Both auth_token and login credentials present' +
60
+ ', preferring auth_token.')
61
+ end
62
+ end
63
+ end
64
+
65
+ # Auxiliary method to generate an authentication token for login in via
66
+ # the ClientLogin API.
67
+ #
68
+ # Args:
69
+ # - credentials: a hash with the credentials for the account being
70
+ # accessed
71
+ #
72
+ # Returns:
73
+ # - The auth token for the account
74
+ #
75
+ # Raises:
76
+ # - AdsCommonForBingAds::Errors::AuthError if authentication fails
77
+ #
78
+ def create_token(credentials)
79
+ token = credentials.include?(:auth_token) ?
80
+ create_token_from_string(credentials[:auth_token]) :
81
+ generate_token(credentials)
82
+ return token
83
+ end
84
+
85
+ # Creates token for provided auth string. Trivial for this handler.
86
+ def create_token_from_string(token_string)
87
+ return token_string
88
+ end
89
+
90
+ # Prepares POST data for ClientLogin request.
91
+ def get_login_data(credentials)
92
+ user_name = CGI.escape(credentials[:user_name])
93
+ password = CGI.escape(credentials[:password])
94
+ service_name = @service_name
95
+ data = "accountType=%s&Email=%s&Passwd=%s&service=%s" %
96
+ [ACCOUNT_TYPE, user_name, password, service_name]
97
+ if credentials[:logintoken] and credentials[:logincaptcha]
98
+ data += "&logintoken=%s&logincaptcha=%s" %
99
+ [CGI.escape(credentials[:logintoken]),
100
+ CGI.escape(credentials[:logincaptcha])]
101
+ end
102
+ return data
103
+ end
104
+
105
+ # Generates new client login token based on credentials.
106
+ def generate_token(credentials)
107
+ validate_credentials(credentials)
108
+
109
+ url = @server + AUTH_PATH
110
+ data = get_login_data(credentials)
111
+ headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
112
+
113
+ response = AdsCommonForBingAds::Http.post_response(url, data, @config, headers)
114
+ results = parse_token_text(response.body)
115
+
116
+ if response.code == 200 and results.include?('Auth')
117
+ return results['Auth']
118
+ else
119
+ handle_login_error(credentials, response, results)
120
+ end
121
+ end
122
+
123
+ # Raises relevant error based on response and parsed results.
124
+ def handle_login_error(credentials, response, results)
125
+ # Handling for known errors.
126
+ if 'CaptchaRequired'.eql?(results['Error'])
127
+ captcha_url = @server + CAPTCHA_PATH + results['CaptchaUrl']
128
+ raise AdsCommonForBingAds::Errors::CaptchaRequiredError.new(results['Error'],
129
+ results['CaptchaToken'], captcha_url, results['Url'])
130
+ end
131
+ # For other errors throwing a generic error.
132
+ error_message = "ClientLogin failed for user_name '%s': HTTP code %d." %
133
+ [credentials[:user_name], response.code]
134
+ error_str = results['Error'] || response.body
135
+ error_message += " Error: %s." % error_str if error_str
136
+ if results.include?('Info')
137
+ error_message += " Info: %s." % results['Info']
138
+ end
139
+ raise AdsCommonForBingAds::Errors::AuthError.new(error_message, error_str,
140
+ results['Info'])
141
+ end
142
+
143
+ # Extracts key-value pairs from ClientLogin server response.
144
+ #
145
+ # Args:
146
+ # - text: server response string
147
+ #
148
+ # Returns:
149
+ # Hash of key-value pairs
150
+ #
151
+ def parse_token_text(text)
152
+ return text.split("\n").inject({}) do |result, line|
153
+ key, *values = line.split('=')
154
+ result[key] = values.join('=')
155
+ result
156
+ end
157
+ end
158
+
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,33 @@
1
+ ####### Overriden for Bing Ads #########
2
+ module AdsCommonForBingAds
3
+ module Auth
4
+
5
+ class OAuth2Handler
6
+
7
+ OAUTH2_CONFIG_BING = {
8
+ :authorization_uri =>
9
+ 'https://login.live.com/oauth20_authorize.srf',
10
+ :token_credential_uri =>
11
+ 'https://login.live.com/oauth20_token.srf'
12
+ }
13
+
14
+ def auth_string(credentials)
15
+ token = get_token(credentials)
16
+ token[:access_token]
17
+ end
18
+
19
+ private
20
+
21
+ def create_client(credentials)
22
+ oauth_options_bing = OAUTH2_CONFIG_BING.merge({
23
+ :client_id => credentials[:oauth2_client_id],
24
+ :client_secret => credentials[:oauth2_client_secret],
25
+ :scope => @scope,
26
+ :redirect_uri => credentials[:oauth2_callback] || DEFAULT_CALLBACK,
27
+ :state => credentials[:oauth2_state]
28
+ }).reject {|k, v| v.nil?}
29
+ return Signet::OAuth2::Client.new(oauth_options_bing)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module AdsCommonForBingAds
2
+ module Build
3
+
4
+ class SavonGenerator
5
+
6
+ private
7
+
8
+ # Generates registry file.
9
+ def write_registry(wsdl, file_name)
10
+ registry_file = create_new_file(file_name)
11
+ generator = SavonRegistryGenerator.new(@generator_args)
12
+ registry = SavonRegistry.new(wsdl, @generator_args)
13
+ generator.add_exceptions(registry.soap_exceptions)
14
+ generator.add_methods(registry.soap_methods)
15
+ generator.add_namespaces(registry.soap_namespaces)
16
+ generator.add_types(registry.soap_types)
17
+ registry_file.write(generator.generate_code())
18
+ registry_file.close
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module AdsCommonForBingAds
2
+ module Build
3
+
4
+ class SavonRegistry
5
+
6
+ # Extracts input parameters of given method as an array.
7
+ def extract_input_parameters(op_node, doc)
8
+ input_element = REXML::XPath.first(op_node, 'descendant::wsdl:input')
9
+ input_name = get_element_name(input_element)
10
+ input_fields = find_sequence_fields(input_name, doc)
11
+ return {:name => input_name.snakecase, :fields => input_fields}
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ module AdsCommonForBingAds
2
+
3
+ class ParametersValidator
4
+ # Validates input parameters to:
5
+ # - add parameter names;
6
+ # - resolve xsi:type where required;
7
+ # - convert some native types to XML.
8
+ def validate_args(action_name, args)
9
+ in_params = @registry.get_method_signature(action_name)[:input] # Hash like {:name=>"get_accounts_info_request", :fields=>[]}
10
+ # TODO: compare number of parameters.
11
+ args_hash = args#{in_params[:name] => deep_copy(args)}
12
+ #validate_arguments(args_hash, in_params)
13
+ return args_hash
14
+ end
15
+
16
+ private
17
+
18
+ # Validates given arguments based on provided fields list.
19
+ def validate_arguments(args_hash, fields_list, type_ns = nil)
20
+ check_extra_fields(args_hash, array_from_named_list(fields_list))
21
+ add_order_key(args_hash, fields_list)
22
+ fields_list.each do |field|
23
+ key = field[:name]
24
+ item = args_hash[key]
25
+ check_required_argument_present(item, field)
26
+ if item
27
+ item_type = get_full_type_signature(field[:type])
28
+ item_ns = field[:ns] || type_ns
29
+ key = handle_namespace_override(args_hash, key, item_ns) if item_ns
30
+ validate_arg(item, args_hash, key, item_type)
31
+ end
32
+ end
33
+ return args_hash
34
+ end
35
+ end
36
+ end