Skip to content

Commit 8423dfc

Browse files
authored
Add AddBillingSetupExample (#321)
1 parent 662d60b commit 8423dfc

2 files changed

Lines changed: 265 additions & 0 deletions

File tree

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.ads.googleads.examples.billing;
16+
17+
import com.beust.jcommander.Parameter;
18+
import com.google.ads.googleads.examples.utils.ArgumentNames;
19+
import com.google.ads.googleads.examples.utils.CodeSampleParams;
20+
import com.google.ads.googleads.lib.GoogleAdsClient;
21+
import com.google.ads.googleads.v4.utils.ResourceNames;
22+
import com.google.ads.googleads.v4.errors.GoogleAdsError;
23+
import com.google.ads.googleads.v4.errors.GoogleAdsException;
24+
import com.google.ads.googleads.v4.resources.BillingSetup;
25+
import com.google.ads.googleads.v4.resources.BillingSetup.PaymentsAccountInfo;
26+
import com.google.ads.googleads.v4.services.BillingSetupOperation;
27+
import com.google.ads.googleads.v4.services.BillingSetupServiceClient;
28+
import com.google.ads.googleads.v4.services.GoogleAdsServiceClient;
29+
import com.google.ads.googleads.v4.services.GoogleAdsServiceClient.SearchPagedResponse;
30+
import com.google.ads.googleads.v4.services.MutateBillingSetupResponse;
31+
import org.joda.time.DateTime;
32+
import com.google.protobuf.StringValue;
33+
import java.io.FileNotFoundException;
34+
import java.io.IOException;
35+
36+
/**
37+
* Creates a billing setup for a customer. A billing setup is a link between a payments account and
38+
* a customer. The new billing setup can either reuse an existing payments account, or create a new
39+
* payments account with a given payments profile. Billing setups are applicable for clients on
40+
* monthly invoicing only. See here for details about applying for monthly invoicing:
41+
* https://support.google.com/google-ads/answer/2375377. In the case of consolidated billing, a
42+
* payments account is linked to the manager account and is linked to a customer account via a
43+
* billing setup.
44+
*/
45+
public class AddBillingSetup {
46+
private static class AddBillingSetupParams extends CodeSampleParams {
47+
48+
@Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
49+
private Long customerId;
50+
51+
@Parameter(names = ArgumentNames.PAYMENTS_ACCOUNT_ID_ID)
52+
private String paymentsAccountId;
53+
54+
@Parameter(names = ArgumentNames.PAYMENTS_PROFILE_ID)
55+
private String paymentsProfileId;
56+
}
57+
58+
public static void main(String[] args) {
59+
AddBillingSetupParams params = new AddBillingSetupParams();
60+
61+
if (!params.parseArguments(args)) {
62+
63+
// Either pass the required parameters for this example on the command line, or insert them
64+
// into the code here. See the parameter class definition above for descriptions.
65+
params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE");
66+
67+
// Either a payments account ID or a payments profile ID must be provided for the example
68+
// to run successfully. If both are provided, only the payments account ID will be used.
69+
// See:
70+
// https://developers.google.com/google-ads/api/docs/billing/billing-setups#creating_new_billing_setups
71+
// Provide an existing payments account ID to link to the new billing setup. Must be
72+
// formatted as "1234-5678-9012-3456".
73+
params.paymentsAccountId = "INSERT_PAYMENTS_ACCOUNT_ID_HERE";
74+
// Alternatively, provide a payments profile ID, which will be linked to a new payments
75+
// account and the new billing setup. Must be formatted as "1234-5678-9012".
76+
params.paymentsProfileId = "INSERT_PAYMENTS_PROFILE_ID_HERE";
77+
}
78+
79+
GoogleAdsClient googleAdsClient;
80+
try {
81+
googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build();
82+
} catch (FileNotFoundException fnfe) {
83+
System.err.printf(
84+
"Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe);
85+
return;
86+
} catch (IOException ioe) {
87+
System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe);
88+
return;
89+
}
90+
91+
try {
92+
new AddBillingSetup()
93+
.runExample(
94+
googleAdsClient,
95+
params.customerId,
96+
params.paymentsAccountId,
97+
params.paymentsProfileId);
98+
} catch (GoogleAdsException gae) {
99+
// GoogleAdsException is the base class for most exceptions thrown by an API request.
100+
// Instances of this exception have a message and a GoogleAdsFailure that contains a
101+
// collection of GoogleAdsErrors that indicate the underlying causes of the
102+
// GoogleAdsException.
103+
System.err.printf(
104+
"Request ID %s failed due to GoogleAdsException. Underlying errors:%n",
105+
gae.getRequestId());
106+
int i = 0;
107+
for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) {
108+
System.err.printf(" Error %d: %s%n", i++, googleAdsError);
109+
}
110+
} catch (Exception e) {
111+
System.err.printf(" Error: %s%n", e);
112+
}
113+
}
114+
115+
/**
116+
* Runs the example.
117+
*
118+
* @param googleAdsClient the Google Ads API client.
119+
* @param customerId the customer ID containing the BillingSetup to remove.
120+
* @param paymentsAccountId optional payments account ID to attach to the new billing setup. Must
121+
* be formatted as "1234-5678-9012-3456".
122+
* @param paymentsProfileId optional payments profile ID to attach to a new payments account and
123+
* to the new billing setup. Must be formatted as "1234-5678-9012".
124+
*/
125+
private void runExample(
126+
GoogleAdsClient googleAdsClient,
127+
long customerId,
128+
String paymentsAccountId,
129+
String paymentsProfileId)
130+
throws Exception {
131+
// Constructs a new billing setup.
132+
BillingSetup billingSetup =
133+
createBillingSetup(customerId, paymentsAccountId, paymentsProfileId);
134+
135+
billingSetup = setBillingSetupDateTimes(googleAdsClient, customerId, billingSetup);
136+
137+
// Creates the billing setup operation.
138+
BillingSetupOperation operation =
139+
BillingSetupOperation.newBuilder().setCreate(billingSetup).build();
140+
141+
// Creates the service client.
142+
try (BillingSetupServiceClient billingSetupServiceClient =
143+
googleAdsClient.getLatestVersion().createBillingSetupServiceClient()) {
144+
// Issues the mutate request to add the billing setup.
145+
MutateBillingSetupResponse billingResponse =
146+
billingSetupServiceClient.mutateBillingSetup(Long.toString(customerId), operation);
147+
148+
System.out.printf(
149+
"Added new billing setup with resource name '%s'.%n",
150+
billingResponse.getResult().getResourceName());
151+
}
152+
}
153+
154+
/**
155+
* Creates and returns a new Billing Setup instance with complete payment details. One of
156+
* paymentsAccountId or paymentsProfileId must be provided.
157+
*
158+
* @param customerId the customer ID containing the BillingSetup to remove.
159+
* @param paymentsAccountId optional payments account ID to attach to the new billing setup. Must
160+
* be formatted as "1234-5678-9012-3456".
161+
* @param paymentsProfileId optional payments profile ID to attach to a new payments account and
162+
* to the new billing setup. Must be formatted as "1234-5678-9012".
163+
* @return new Billing Setup instance with complete payment details.
164+
*/
165+
private BillingSetup createBillingSetup(
166+
long customerId, String paymentsAccountId, String paymentsProfileId) throws Exception {
167+
BillingSetup.Builder billingSetupBuilder = BillingSetup.newBuilder();
168+
169+
// Sets the appropriate payments account field.
170+
if (paymentsAccountId != null) {
171+
// If a payments account id has been provided, set PaymentsAccount to its resource
172+
// name. You can list available payments accounts via the PaymentsAccountService's
173+
// ListPaymentsAccounts method.
174+
billingSetupBuilder.setPaymentsAccount(
175+
StringValue.of(ResourceNames.paymentsAccount(customerId, paymentsAccountId)));
176+
} else if (paymentsProfileId != null) {
177+
// Otherwise, create a new payments account by setting the PaymentsAccountInfo
178+
// field. See https://support.google.com/google-ads/answer/7268503 for information
179+
// about payments profiles.
180+
billingSetupBuilder.setPaymentsAccountInfo(
181+
PaymentsAccountInfo.newBuilder()
182+
.setPaymentsAccountName(
183+
StringValue.of("Payments Account #" + System.currentTimeMillis()))
184+
.setPaymentsProfileId(StringValue.of(paymentsProfileId))
185+
.build());
186+
} else {
187+
throw new Exception("No paymentsAccountId or paymentsProfileId provided.");
188+
}
189+
190+
return billingSetupBuilder.build();
191+
}
192+
193+
/**
194+
* Sets the starting and ending date times for the new billing setup. Queries the customer's
195+
* account to see if there are any approved billing setups. If there are any, the new billing
196+
* setup starting date time is set to one day after the last. If not, the billing setup is set to
197+
* start immediately. The ending date is set to one day after the starting date time.
198+
*
199+
* @param googleAdsClient the Google Ads API client.
200+
* @param customerId the customer ID containing the BillingSetup to remove.
201+
* @param billingSetup The instance of BillingSetup whose starting date time will be set.
202+
* @return Billing Setup with updated start and end date time.
203+
*/
204+
private BillingSetup setBillingSetupDateTimes(
205+
GoogleAdsClient googleAdsClient, long customerId, BillingSetup billingSetup)
206+
throws Exception {
207+
// Defines a query to search existing approved billing setups in the end date time descending
208+
// order.
209+
// See GetBillingSetup.java for a more detailed example of requesting billing setup
210+
// information.
211+
String query =
212+
"SELECT billing_setup.end_date_time "
213+
+ "FROM billing_setup "
214+
+ "WHERE billing_setup.status = 'APPROVED' "
215+
+ "ORDER BY billing_setup.end_date_time DESC";
216+
217+
// Creates the service client.
218+
try (GoogleAdsServiceClient googleAdsServiceClient =
219+
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
220+
// Issues a search request.
221+
SearchPagedResponse searchPagedResponse =
222+
googleAdsServiceClient.search(Long.toString(customerId), query);
223+
224+
BillingSetup.Builder billingSetupBuilder = billingSetup.toBuilder();
225+
if (searchPagedResponse.getPage().getResponse().getResultsCount() > 0) {
226+
// Retrieves the ending date time of the last billing setup.
227+
StringValue lastEndingDateTimeString =
228+
searchPagedResponse
229+
.getPage()
230+
.getResponse()
231+
.getResults(0)
232+
.getBillingSetup()
233+
.getEndDateTime();
234+
235+
// A null ending date time indicates that the current billing setup is set to run
236+
// indefinitely. Billing setups cannot overlap, so throw an exception in this case.
237+
if (lastEndingDateTimeString == null) {
238+
throw new Exception(
239+
"Cannot set starting and ending date times for the new billing setup; the latest"
240+
+ " existing billing setup is set to run indefinitely.");
241+
}
242+
243+
DateTime lastEndingDateTime = DateTime.parse(lastEndingDateTimeString.toString());
244+
245+
// Sets the new billing setup to start one day after the ending date time.
246+
billingSetupBuilder.setStartDateTime(
247+
StringValue.of(lastEndingDateTime.plusDays(1).toString("yyyy-MM-dd")));
248+
249+
// Sets the new billing setup to end one day after the starting date time.
250+
billingSetupBuilder.setEndDateTime(
251+
StringValue.of(lastEndingDateTime.plusDays(2).toString("yyyy-MM-dd")));
252+
} else {
253+
// Otherwise, the only acceptable start time is DateTime.now().
254+
billingSetupBuilder.setStartDateTime(StringValue.of(DateTime.now().toString()));
255+
256+
// Sets the new billing setup to end tomorrow.
257+
billingSetupBuilder.setEndDateTime(
258+
StringValue.of(new DateTime().plusDays(1).toString("yyyy-MM-dd")));
259+
}
260+
return billingSetupBuilder.build();
261+
}
262+
}
263+
}

google-ads-examples/src/main/java/com/google/ads/googleads/examples/utils/ArgumentNames.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public final class ArgumentNames {
7171
public static final String OFFLINE_USER_DATA_JOB_TYPE = "--offlineUserDataJobType";
7272
public static final String PAGE_URL = "--pageUrl";
7373
public static final String PARTNER_ID = "--partnerId";
74+
public static final String PAYMENTS_ACCOUNT_ID_ID = "--paymentsAccountId";
75+
public static final String PAYMENTS_PROFILE_ID = "--paymentsProfileId";
7476
public static final String RECOMMENDATION_ID = "--recommendationId";
7577
public static final String REPLACE_EXISTING_TREE = "--replaceExistingTree";
7678
public static final String RESTATEMENT_VALUE = "--restatementValue";

0 commit comments

Comments
 (0)