-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Initial version of sample code to call payments reseller APIs #10146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Pre-requisites: | ||
|
||
You will need to be added to a specific allow list which will allow you to impersonate | ||
the service account `payment-reseller-test-serv-734@eng-diagram-369411.iam.gserviceaccount.com` | ||
|
||
<How to verify this as a developer?> | ||
|
||
Steps: | ||
|
||
- Save your google cloud credentials to a local file to run the code. | ||
- Run the command `gcloud auth application-default login`. This should | ||
trigger an oauth screen asking permissions run google cloud cli. Login with | ||
the allow listed account and give permissions. | ||
|
||
Credentials will be saved to a local file with directory path | ||
`~/.config/gcloud/application_default_credentials.json` | ||
|
||
|
||
- You are all setup, you can execute specific code | ||
Verify with running an impersonate code which should print the access token |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The PR checklist indicates that the |
||
|
||
<groupId>com.example</groupId> | ||
<artifactId>google-reseller-java</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
|
||
<properties> | ||
<maven.compiler.source>11</maven.compiler.source> | ||
<maven.compiler.target>11</maven.compiler.target> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.google.api-client</groupId> | ||
<artifactId>google-api-client</artifactId> | ||
<version>2.2.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.auth</groupId> | ||
<artifactId>google-auth-library-oauth2-http</artifactId> | ||
<version>1.33.1</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.apis</groupId> | ||
<artifactId>google-api-services-paymentsresellersubscription</artifactId> | ||
<version>v1-rev20250302-2.0.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.http-client</groupId> | ||
<artifactId>google-http-client-gson</artifactId> | ||
<version>1.43.3</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
<profiles> | ||
<profile> | ||
<id>runImpersonateServiceAccountAndProvisionSubscription</id> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.codehaus.mojo</groupId> | ||
<artifactId>exec-maven-plugin</artifactId> | ||
<version>3.0.0</version> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>java</goal> | ||
</goals> | ||
<configuration> | ||
<mainClass>com.google.cloud.reseller.subscription.samples.ProvisionSubscription</mainClass> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
<profile> | ||
<id>runImpersonateServiceAccountAndGenerateUserSession</id> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.codehaus.mojo</groupId> | ||
<artifactId>exec-maven-plugin</artifactId> | ||
<version>3.0.0</version> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>java</goal> | ||
</goals> | ||
<configuration> | ||
<mainClass>com.google.cloud.reseller.subscription.samples.GenerateUserSession</mainClass> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
</profiles> | ||
</project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.google.cloud.reseller.subscription.samples; | ||
|
||
public class Constants { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
public static final String PARTNER_ID = "yt_ptm_staging"; | ||
public static final String NFT_PRODUCT_ID = "YTPD-acb26288-d14b-4865-a748-a132c5f37f6d"; | ||
public static final String PRODUCT_ID = "YTPD-902fd916-219d-4aa0-b735-40fc57bd9b5b"; | ||
public static final String ELIGIBILITY_ID = "yt_ptm_staging:ibv2-bundle-plan"; | ||
public static final String PROMOTION = "YTPM-CilZVFBELTkwMmZkOTE2LTIxOWQtNGFhMC1iNzM1LTQwZmM1N2JkOWI1YhAC"; | ||
public static final String PROMOTION_SUB_LEVEL = "YTPM-CilZVFBELTkwMmZkOTE2LTIxOWQtNGFhMC1iNzM1LTQwZmM1N2JkOWI1YhAB"; | ||
public static final String PLAN_TYPE = "PARTNER_PLAN_TYPE_HARD_BUNDLE"; | ||
public static final String REGION_CODE = "US"; | ||
public static final String SUB_ID = "onboarding-partner-testing"; | ||
public static final String TARGET_SERVICE_ACCOUNT_EMAIL = "payment-reseller-test-serv-734@eng-diagram-369411.iam.gserviceaccount.com"; | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package com.google.cloud.reseller.subscription.samples; | ||
|
||
import static com.google.cloud.reseller.subscription.samples.Constants.ELIGIBILITY_ID; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.NFT_PRODUCT_ID; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.PARTNER_ID; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.PLAN_TYPE; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.PRODUCT_ID; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.PROMOTION; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.PROMOTION_SUB_LEVEL; | ||
Comment on lines
+7
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
import static com.google.cloud.reseller.subscription.samples.Constants.REGION_CODE; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.SUB_ID; | ||
import static com.google.cloud.reseller.subscription.samples.Constants.TARGET_SERVICE_ACCOUNT_EMAIL; | ||
|
||
import com.google.api.client.http.HttpRequestInitializer; | ||
import com.google.api.client.http.HttpTransport; | ||
import com.google.api.client.http.javanet.NetHttpTransport; | ||
import com.google.api.client.json.gson.GsonFactory; | ||
import com.google.api.services.paymentsresellersubscription.v1.PaymentsResellerSubscription; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1CreateSubscriptionIntent; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1GenerateUserSessionRequest; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1GenerateUserSessionResponse; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1IntentPayload; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1Location; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1ProductPayload; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1Subscription; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1SubscriptionLineItem; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1SubscriptionPromotionSpec; | ||
import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1YoutubePayload; | ||
import com.google.auth.http.HttpCredentialsAdapter; | ||
import com.google.common.collect.ImmutableList; | ||
import java.io.IOException; | ||
import java.time.Instant; | ||
import java.time.ZoneOffset; | ||
import java.time.format.DateTimeFormatter; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
public class GenerateUserSession { | ||
|
||
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); | ||
|
||
public static void main(String[] args) throws IOException { | ||
List<String> scopes = Collections.singletonList( | ||
"https://www.googleapis.com/auth/youtube.commerce.partnership.integrated-billing"); | ||
|
||
ImpersonateServiceAccount impersonateServiceAccount = new ImpersonateServiceAccount(scopes, TARGET_SERVICE_ACCOUNT_EMAIL); | ||
impersonateServiceAccount.refreshCredentials(); | ||
|
||
// call provision API using service account credentials | ||
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter( | ||
impersonateServiceAccount.getImpersonatedCredentials()); | ||
PaymentsResellerSubscription client = new PaymentsResellerSubscription.Builder( | ||
HTTP_TRANSPORT, GsonFactory.getDefaultInstance(), | ||
requestInitializer | ||
).setRootUrl("https://preprod-paymentsresellersubscription.googleapis.com").build(); | ||
System.out.println("partners/" + PARTNER_ID + "/products/" + NFT_PRODUCT_ID); | ||
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone( | ||
ZoneOffset.UTC); // RFC 3339, with offset | ||
String subscriptionId = SUB_ID + Instant.now().toEpochMilli(); | ||
GoogleCloudPaymentsResellerSubscriptionV1GenerateUserSessionResponse generateUserSessionResponse = client.partners() | ||
.userSessions().generate("partners/" + PARTNER_ID, | ||
new GoogleCloudPaymentsResellerSubscriptionV1GenerateUserSessionRequest().setIntentPayload( | ||
new GoogleCloudPaymentsResellerSubscriptionV1IntentPayload().setCreateIntent( | ||
new GoogleCloudPaymentsResellerSubscriptionV1CreateSubscriptionIntent().setParent( | ||
"partners/" + PARTNER_ID).setSubscriptionId(subscriptionId) | ||
.setSubscription( | ||
new GoogleCloudPaymentsResellerSubscriptionV1Subscription() | ||
.setLineItems( | ||
ImmutableList | ||
.of(new GoogleCloudPaymentsResellerSubscriptionV1SubscriptionLineItem() | ||
.setProduct("partners/" + PARTNER_ID + "/products/" | ||
+ NFT_PRODUCT_ID) | ||
.setProductPayload( | ||
new GoogleCloudPaymentsResellerSubscriptionV1ProductPayload() | ||
.setYoutubePayload( | ||
new GoogleCloudPaymentsResellerSubscriptionV1YoutubePayload() | ||
.setPartnerEligibilityIds( | ||
List.of(ELIGIBILITY_ID)) | ||
.setPartnerPlanType(PLAN_TYPE) | ||
)) | ||
// .setLineItemPromotionSpecs(ImmutableList.of(new GoogleCloudPaymentsResellerSubscriptionV1SubscriptionPromotionSpec().setPromotion("partners/" + PARTNER_ID + "/promotions/" + PROMOTION))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
)) | ||
.setPartnerUserToken("[email protected]") | ||
.setServiceLocation( | ||
new GoogleCloudPaymentsResellerSubscriptionV1Location() | ||
.setPostalCode("94043") | ||
.setRegionCode(REGION_CODE)) | ||
.setPurchaseTime(formatter.format(Instant.now())) | ||
// .setPromotionSpecs(ImmutableList.of(new GoogleCloudPaymentsResellerSubscriptionV1SubscriptionPromotionSpec().setPromotion("partners/" + PARTNER_ID + "/promotions/" + PROMOTION_SUB_LEVEL))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
)))).execute(); | ||
System.out.println("Subscription Id::" + subscriptionId); | ||
System.out.printf("Sandbox URL to create subscription:: https://serviceactivation.sandbox.google.com/subscription/new/%s \n", generateUserSessionResponse.getUserSession().getToken()); | ||
|
||
} | ||
} | ||
// mvn clean compile | ||
// mvn exec:java -Dexec.mainClass="com.google.cloud.reseller.subscription.samples.GenerateUserSession" | ||
Comment on lines
+96
to
+97
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.google.cloud.reseller.subscription.samples; | ||
|
||
import static com.google.cloud.reseller.subscription.samples.Constants.TARGET_SERVICE_ACCOUNT_EMAIL; | ||
|
||
import com.google.auth.oauth2.GoogleCredentials; | ||
import com.google.auth.oauth2.ImpersonatedCredentials; | ||
|
||
import com.google.auth.oauth2.OAuth2Utils; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
/** A utility wrapper to impersonate a target service account for a list of provided oauth scopes. */ | ||
public class ImpersonateServiceAccount { | ||
public static final String USER_HOME = System.getProperty("user.home"); | ||
private ImpersonatedCredentials impersonatedCredentials; | ||
|
||
public ImpersonateServiceAccount(List<String> oauthScopes, String targetServiceAccount) { | ||
try { | ||
// File name output from: $gcloud auth application-default login | ||
GoogleCredentials sourceCredentials = GoogleCredentials.fromStream(new FileInputStream( | ||
USER_HOME.concat("/.config/gcloud/application_default_credentials.json"))); | ||
Comment on lines
+22
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The path to the application default credentials file is hardcoded. This is not robust as the location can vary, and it's not platform-independent. It's better to use GoogleCredentials sourceCredentials = GoogleCredentials.getApplicationDefault(); |
||
|
||
impersonatedCredentials = ImpersonatedCredentials.newBuilder() | ||
.setSourceCredentials(sourceCredentials) | ||
.setTargetPrincipal(targetServiceAccount) | ||
.setScopes(oauthScopes) | ||
.setDelegates(null) //Optional delegation | ||
.setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY) | ||
.build(); | ||
|
||
} catch (IOException e) { | ||
System.err.println("Failed to get impersonated credentials: " + e.getMessage()); | ||
System.err.println( | ||
"Ensure your source credentials have the 'Service Account Token Creator' role on the target SA and that ADC is set up correctly."); | ||
} | ||
} | ||
Comment on lines
+19
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The constructor swallows the public ImpersonateServiceAccount(List<String> oauthScopes, String targetServiceAccount) throws IOException {
// File name output from: $gcloud auth application-default login
GoogleCredentials sourceCredentials = GoogleCredentials.fromStream(new FileInputStream(
USER_HOME.concat("/.config/gcloud/application_default_credentials.json")));
impersonatedCredentials = ImpersonatedCredentials.newBuilder()
.setSourceCredentials(sourceCredentials)
.setTargetPrincipal(targetServiceAccount)
.setScopes(oauthScopes)
.setDelegates(null) //Optional delegation
.setHttpTransportFactory(OAuth2Utils.HTTP_TRANSPORT_FACTORY)
.build();
} |
||
|
||
public void refreshCredentials() throws IOException { | ||
impersonatedCredentials.refresh(); | ||
} | ||
|
||
public String getAccessToken() { | ||
return impersonatedCredentials.getAccessToken().getTokenValue(); | ||
} | ||
|
||
public ImpersonatedCredentials getImpersonatedCredentials() { | ||
return impersonatedCredentials; | ||
} | ||
|
||
public static void main(String[] args) throws IOException { | ||
List<String> scopes = Collections.singletonList( | ||
"https://www.googleapis.com/auth/youtube.commerce.partnership.integrated-billing"); | ||
|
||
ImpersonateServiceAccount impersonateServiceAccount = new ImpersonateServiceAccount(scopes, TARGET_SERVICE_ACCOUNT_EMAIL); | ||
impersonateServiceAccount.refreshCredentials(); | ||
System.out.printf("AccessToken:: [%s]\n", impersonateServiceAccount.getAccessToken()); | ||
} | ||
} | ||
|
||
// mvn clean compile | ||
// mvn exec:java -Dexec.mainClass="com.google.cloud.reseller.subscription.samples.ImpersonateServiceAccount" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line appears to be a placeholder comment for the developer. It should be replaced with actual instructions or removed to finalize the documentation.