diff --git a/payments/reseller/subscription/snippets/README b/payments/reseller/subscription/snippets/README new file mode 100644 index 00000000000..bc4b2fdc7b8 --- /dev/null +++ b/payments/reseller/subscription/snippets/README @@ -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` + + + +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 \ No newline at end of file diff --git a/payments/reseller/subscription/snippets/pom.xml b/payments/reseller/subscription/snippets/pom.xml new file mode 100644 index 00000000000..b22deb6c54f --- /dev/null +++ b/payments/reseller/subscription/snippets/pom.xml @@ -0,0 +1,85 @@ + + 4.0.0 + + com.example + google-reseller-java + 1.0-SNAPSHOT + + + 11 + 11 + UTF-8 + + + + + com.google.api-client + google-api-client + 2.2.0 + + + com.google.auth + google-auth-library-oauth2-http + 1.33.1 + + + com.google.apis + google-api-services-paymentsresellersubscription + v1-rev20250302-2.0.0 + + + com.google.http-client + google-http-client-gson + 1.43.3 + + + + + + runImpersonateServiceAccountAndProvisionSubscription + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + + java + + + com.google.cloud.reseller.subscription.samples.ProvisionSubscription + + + + + + + + + runImpersonateServiceAccountAndGenerateUserSession + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + + java + + + com.google.cloud.reseller.subscription.samples.GenerateUserSession + + + + + + + + + diff --git a/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/Constants.java b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/Constants.java new file mode 100644 index 00000000000..250043fc340 --- /dev/null +++ b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/Constants.java @@ -0,0 +1,17 @@ +package com.google.cloud.reseller.subscription.samples; + +public class Constants { + + 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"; + + +} diff --git a/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/GenerateUserSession.java b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/GenerateUserSession.java new file mode 100644 index 00000000000..46085bb5d3d --- /dev/null +++ b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/GenerateUserSession.java @@ -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; +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 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))) + )) + .setPartnerUserToken("g1.tvc.test2@gmail.com") + .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))) + )))).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" + diff --git a/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/ImpersonateServiceAccount.java b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/ImpersonateServiceAccount.java new file mode 100644 index 00000000000..1d46d55e453 --- /dev/null +++ b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/ImpersonateServiceAccount.java @@ -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 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"))); + + 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."); + } + } + + 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 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" diff --git a/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/ProvisionSubscription.java b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/ProvisionSubscription.java new file mode 100644 index 00000000000..aab06bcd3ab --- /dev/null +++ b/payments/reseller/subscription/snippets/src/main/java/com/google/cloud/reseller/subscription/samples/ProvisionSubscription.java @@ -0,0 +1,96 @@ +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; +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.GoogleCloudPaymentsResellerSubscriptionV1Location; +import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1ProductPayload; +import com.google.api.services.paymentsresellersubscription.v1.model.GoogleCloudPaymentsResellerSubscriptionV1Promotion; +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 ProvisionSubscription { + + private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void main(String[] args) throws IOException { + List 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.println("Testing code " + impersonateServiceAccount.getImpersonatedCredentials()); + + try { + // 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(); + DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone( + ZoneOffset.UTC); // RFC 3339, with offset + String subscriptionId = SUB_ID + Instant.now().toEpochMilli(); + GoogleCloudPaymentsResellerSubscriptionV1Subscription provision = client.partners() + .subscriptions() + .provision("partners/" + PARTNER_ID, + 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))) + )) + .setPartnerUserToken("pr.api.sandbox.tvc.test1@gmail.com") + .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))) + ) + .setSubscriptionId(subscriptionId) + .execute(); + System.out.println("Subscription Id::" + subscriptionId); + System.out.println("Provision result:: " + provision); + + } catch (Exception e) { + System.err.println("Failed to provision subscription: " + e.getMessage()); + } + + } +} + +// mvn clean compile +// mvn exec:java -Dexec.mainClass="com.google.cloud.reseller.subscription.samples.ProvisionSubscription"