diff --git a/java/google/registry/braintree/BUILD b/java/google/registry/braintree/BUILD deleted file mode 100644 index 116cefbb3..000000000 --- a/java/google/registry/braintree/BUILD +++ /dev/null @@ -1,20 +0,0 @@ -package( - default_visibility = ["//visibility:public"], -) - -licenses(["notice"]) # Apache 2.0 - -java_library( - name = "braintree", - srcs = glob(["*.java"]), - deps = [ - "//java/google/registry/config", - "//java/google/registry/keyring/api", - "//java/google/registry/model", - "@com_braintreepayments_gateway_braintree_java", - "@com_google_code_findbugs_jsr305", - "@com_google_dagger", - "@com_google_guava", - "@javax_inject", - ], -) diff --git a/java/google/registry/braintree/BraintreeModule.java b/java/google/registry/braintree/BraintreeModule.java deleted file mode 100644 index ba9c7072d..000000000 --- a/java/google/registry/braintree/BraintreeModule.java +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.braintree; - -import com.braintreegateway.BraintreeGateway; -import dagger.Module; -import dagger.Provides; -import google.registry.config.RegistryConfig.Config; -import google.registry.config.RegistryEnvironment; -import google.registry.keyring.api.KeyModule.Key; -import javax.inject.Singleton; - -/** Dagger module for Braintree Payments API. */ -@Module -public final class BraintreeModule { - - @Provides - @Singleton - static BraintreeGateway provideBraintreeGateway( - RegistryEnvironment environment, - @Config("braintreeMerchantId") String merchantId, - @Config("braintreePublicKey") String publicKey, - @Key("braintreePrivateKey") String privateKey) { - return new BraintreeGateway( - environment == RegistryEnvironment.PRODUCTION - ? com.braintreegateway.Environment.PRODUCTION - : com.braintreegateway.Environment.SANDBOX, - merchantId, - publicKey, - privateKey); - } -} diff --git a/java/google/registry/braintree/BraintreeRegistrarSyncer.java b/java/google/registry/braintree/BraintreeRegistrarSyncer.java deleted file mode 100644 index 1bac45154..000000000 --- a/java/google/registry/braintree/BraintreeRegistrarSyncer.java +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.braintree; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Verify.verify; - -import com.braintreegateway.BraintreeGateway; -import com.braintreegateway.Customer; -import com.braintreegateway.CustomerRequest; -import com.braintreegateway.Result; -import com.braintreegateway.exceptions.NotFoundException; -import com.google.common.base.VerifyException; -import google.registry.model.registrar.Registrar; -import google.registry.model.registrar.RegistrarContact; -import java.util.Optional; -import javax.inject.Inject; - -/** Helper for creating Braintree customer entries for registrars. */ -public class BraintreeRegistrarSyncer { - - private final BraintreeGateway braintree; - - @Inject - BraintreeRegistrarSyncer(BraintreeGateway braintreeGateway) { - this.braintree = braintreeGateway; - } - - /** - * Syncs {@code registrar} with Braintree customer entry, creating it if one doesn't exist. - * - *

The customer ID will be the same as {@link Registrar#getClientId()}. - * - *

Creating a customer object in Braintree's database is a necessary step in order to associate - * a payment with a registrar. The transaction will fail if the customer object doesn't exist. - * - * @throws IllegalArgumentException if {@code registrar} is not using BRAINTREE billing - * @throws VerifyException if the Braintree API returned a failure response - */ - public void sync(Registrar registrar) { - String id = registrar.getClientId(); - checkArgument(registrar.getBillingMethod() == Registrar.BillingMethod.BRAINTREE, - "Registrar (%s) billing method (%s) is not BRAINTREE", id, registrar.getBillingMethod()); - CustomerRequest request = createRequest(registrar); - Result result; - if (doesCustomerExist(id)) { - result = braintree.customer().update(id, request); - } else { - result = braintree.customer().create(request); - } - verify(result.isSuccess(), - "Failed to sync registrar (%s) to braintree customer: %s", id, result.getMessage()); - } - - private CustomerRequest createRequest(Registrar registrar) { - CustomerRequest result = - new CustomerRequest() - .id(registrar.getClientId()) - .customerId(registrar.getClientId()) - .company(registrar.getRegistrarName()); - Optional contact = getBillingContact(registrar); - if (contact.isPresent()) { - result.email(contact.get().getEmailAddress()); - result.phone(contact.get().getPhoneNumber()); - result.fax(contact.get().getFaxNumber()); - } else { - result.email(registrar.getEmailAddress()); - result.phone(registrar.getPhoneNumber()); - result.fax(registrar.getFaxNumber()); - } - return result; - } - - private Optional getBillingContact(Registrar registrar) { - for (RegistrarContact contact : registrar.getContacts()) { - if (contact.getTypes().contains(RegistrarContact.Type.BILLING)) { - return Optional.of(contact); - } - } - return Optional.empty(); - } - - private boolean doesCustomerExist(String id) { - try { - braintree.customer().find(id); - return true; - } catch (NotFoundException e) { - return false; - } - } -} diff --git a/java/google/registry/braintree/package-info.java b/java/google/registry/braintree/package-info.java deleted file mode 100644 index 280aa3852..000000000 --- a/java/google/registry/braintree/package-info.java +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** Braintree payment gateway utilities. */ -@javax.annotation.ParametersAreNonnullByDefault -package google.registry.braintree; diff --git a/java/google/registry/config/RegistryConfig.java b/java/google/registry/config/RegistryConfig.java index 4519ca242..4abe9afc0 100644 --- a/java/google/registry/config/RegistryConfig.java +++ b/java/google/registry/config/RegistryConfig.java @@ -32,14 +32,11 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.net.URI; import java.net.URL; -import java.util.Map; -import java.util.Map.Entry; import java.util.Optional; import javax.annotation.Nullable; import javax.inject.Named; import javax.inject.Qualifier; import javax.inject.Singleton; -import org.joda.money.CurrencyUnit; import org.joda.time.DateTimeConstants; import org.joda.time.Duration; @@ -887,51 +884,6 @@ public final class RegistryConfig { return null; } - /** - * Returns Braintree Merchant Account IDs for each supported currency. - * - * @see google.registry.ui.server.registrar.RegistrarPaymentAction - * @see google.registry.ui.server.registrar.RegistrarPaymentSetupAction - */ - @Provides - @Config("braintreeMerchantAccountIds") - public static ImmutableMap provideBraintreeMerchantAccountId( - RegistryConfigSettings config) { - Map merchantAccountIds = config.braintree.merchantAccountIdsMap; - ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - for (Entry entry : merchantAccountIds.entrySet()) { - builder.put(CurrencyUnit.of(entry.getKey()), entry.getValue()); - } - return builder.build(); - } - - /** - * Returns Braintree Merchant ID of Registry, used for accessing Braintree API. - * - *

This is a base32 value copied from the Braintree website. - * - * @see google.registry.braintree.BraintreeModule - */ - @Provides - @Config("braintreeMerchantId") - public static String provideBraintreeMerchantId(RegistryConfigSettings config) { - return config.braintree.merchantId; - } - - /** - * Returns Braintree Public Key of Registry, used for accessing Braintree API. - * - *

This is a base32 value copied from the Braintree website. - * - * @see google.registry.braintree.BraintreeModule - * @see google.registry.keyring.api.Keyring#getBraintreePrivateKey() - */ - @Provides - @Config("braintreePublicKey") - public static String provideBraintreePublicKey(RegistryConfigSettings config) { - return config.braintree.publicKey; - } - /** * Disclaimer displayed at the end of WHOIS query results. * diff --git a/java/google/registry/config/RegistryConfigSettings.java b/java/google/registry/config/RegistryConfigSettings.java index 3245bd18a..3a7d0dfaa 100644 --- a/java/google/registry/config/RegistryConfigSettings.java +++ b/java/google/registry/config/RegistryConfigSettings.java @@ -15,7 +15,6 @@ package google.registry.config; import java.util.List; -import java.util.Map; /** The POJO that YAML config files are deserialized into. */ public class RegistryConfigSettings { @@ -33,7 +32,6 @@ public class RegistryConfigSettings { public RegistrarConsole registrarConsole; public Monitoring monitoring; public Misc misc; - public Braintree braintree; public Kms kms; public RegistryTool registryTool; @@ -158,13 +156,6 @@ public class RegistryConfigSettings { public int asyncDeleteDelaySeconds; } - /** Configuration for Braintree credit card payment processing. */ - public static class Braintree { - public String merchantId; - public String publicKey; - public Map merchantAccountIdsMap; - } - /** Configuration options for the registry tool. */ public static class RegistryTool { public String clientSecretFilename; diff --git a/java/google/registry/config/files/default-config.yaml b/java/google/registry/config/files/default-config.yaml index ac8bbb00d..001d3ce95 100644 --- a/java/google/registry/config/files/default-config.yaml +++ b/java/google/registry/config/files/default-config.yaml @@ -246,21 +246,6 @@ misc: # hosts from being used on domains. asyncDeleteDelaySeconds: 90 -# Braintree is a credit card payment processor that is used on the registrar -# console to allow registrars to pay their invoices. -braintree: - # Merchant ID of the Braintree account. - merchantId: example - - # Public key used for accessing Braintree API (this is found on their site). - publicKey: example - - # A map of JODA Money CurrencyUnits, specified in three letter ISO-4217 - # format, to Braintree account IDs (each account is limited to a single - # currency). For example, one entry might be: - # USD: accountIdUsingUSD - merchantAccountIdsMap: {} - kms: # GCP project containing the KMS keyring. Should only be used for KMS in # order to keep a simple locked down IAM configuration. diff --git a/java/google/registry/config/files/nomulus-config-production-sample.yaml b/java/google/registry/config/files/nomulus-config-production-sample.yaml index 57c0863df..cb4d4c32b 100644 --- a/java/google/registry/config/files/nomulus-config-production-sample.yaml +++ b/java/google/registry/config/files/nomulus-config-production-sample.yaml @@ -57,15 +57,5 @@ registrarConsole: misc: sheetExportId: placeholder -# You only need to specify this section if using Braintree. -braintree: - merchantId: placeholder - publicKey: placeholder - # Only include currencies that you use. - merchantAccountIdsMap: - EUR: placeholder - JPY: placeholder - USD: placeholder - kms: projectId: placeholder diff --git a/java/google/registry/config/files/nomulus-config-unittest.yaml b/java/google/registry/config/files/nomulus-config-unittest.yaml index 1a1e07305..cd3078a5e 100644 --- a/java/google/registry/config/files/nomulus-config-unittest.yaml +++ b/java/google/registry/config/files/nomulus-config-unittest.yaml @@ -19,8 +19,3 @@ caching: staticPremiumListMaxCachedEntries: 50 eppResourceCachingEnabled: true eppResourceCachingSeconds: 0 - -braintree: - merchantAccountIdsMap: - USD: accountIdUsd - JPY: accountIdJpy diff --git a/java/google/registry/env/common/default/WEB-INF/web.xml b/java/google/registry/env/common/default/WEB-INF/web.xml index fb123396e..ad42c0f06 100644 --- a/java/google/registry/env/common/default/WEB-INF/web.xml +++ b/java/google/registry/env/common/default/WEB-INF/web.xml @@ -31,18 +31,6 @@ /registrar - - - frontend-servlet - /registrar-payment-setup - - - - - frontend-servlet - /registrar-payment - - frontend-servlet @@ -73,7 +61,6 @@ /assets/js/registrar_bin.js.map /assets/js/registrar_dbg.js - /assets/js/brain_bin.js.map /assets/css/registrar_dbg.css diff --git a/java/google/registry/env/common/pubapi/WEB-INF/web.xml b/java/google/registry/env/common/pubapi/WEB-INF/web.xml index ca266e06e..2cd19223d 100644 --- a/java/google/registry/env/common/pubapi/WEB-INF/web.xml +++ b/java/google/registry/env/common/pubapi/WEB-INF/web.xml @@ -61,7 +61,6 @@ /assets/js/registrar_bin.js.map /assets/js/registrar_dbg.js - /assets/js/brain_bin.js.map /assets/css/registrar_dbg.css diff --git a/java/google/registry/keyring/api/DummyKeyringModule.java b/java/google/registry/keyring/api/DummyKeyringModule.java index e0a99682e..15d17d2b6 100644 --- a/java/google/registry/keyring/api/DummyKeyringModule.java +++ b/java/google/registry/keyring/api/DummyKeyringModule.java @@ -109,7 +109,6 @@ public final class DummyKeyringModule { "not a real login", "not a real password", "not a real login", - "not a real credential", - "not a real key"); + "not a real credential"); } } diff --git a/java/google/registry/keyring/api/InMemoryKeyring.java b/java/google/registry/keyring/api/InMemoryKeyring.java index 85080eff8..516d164cb 100644 --- a/java/google/registry/keyring/api/InMemoryKeyring.java +++ b/java/google/registry/keyring/api/InMemoryKeyring.java @@ -38,7 +38,6 @@ public final class InMemoryKeyring implements Keyring { private final String marksdbLordnPassword; private final String marksdbSmdrlLogin; private final String jsonCredential; - private final String braintreePrivateKey; public InMemoryKeyring( PGPKeyPair rdeStagingKey, @@ -52,8 +51,7 @@ public final class InMemoryKeyring implements Keyring { String marksdbDnlLogin, String marksdbLordnPassword, String marksdbSmdrlLogin, - String jsonCredential, - String braintreePrivateKey) { + String jsonCredential) { checkArgument(PgpHelper.isSigningKey(rdeSigningKey.getPublicKey()), "RDE signing key must support signing: %s", rdeSigningKey.getKeyID()); checkArgument(rdeStagingKey.getPublicKey().isEncryptionKey(), @@ -76,7 +74,6 @@ public final class InMemoryKeyring implements Keyring { this.marksdbLordnPassword = checkNotNull(marksdbLordnPassword, "marksdbLordnPassword"); this.marksdbSmdrlLogin = checkNotNull(marksdbSmdrlLogin, "marksdbSmdrlLogin"); this.jsonCredential = checkNotNull(jsonCredential, "jsonCredential"); - this.braintreePrivateKey = checkNotNull(braintreePrivateKey, "braintreePrivateKey"); } @Override @@ -144,11 +141,6 @@ public final class InMemoryKeyring implements Keyring { return jsonCredential; } - @Override - public String getBraintreePrivateKey() { - return braintreePrivateKey; - } - /** Does nothing. */ @Override public void close() {} diff --git a/java/google/registry/keyring/api/KeyModule.java b/java/google/registry/keyring/api/KeyModule.java index 99c9b6409..d0b72a352 100644 --- a/java/google/registry/keyring/api/KeyModule.java +++ b/java/google/registry/keyring/api/KeyModule.java @@ -120,10 +120,4 @@ public final class KeyModule { static String provideJsonCredential(Keyring keyring) { return keyring.getJsonCredential(); } - - @Provides - @Key("braintreePrivateKey") - static String provideBraintreePrivateKey(Keyring keyring) { - return keyring.getBraintreePrivateKey(); - } } diff --git a/java/google/registry/keyring/api/Keyring.java b/java/google/registry/keyring/api/Keyring.java index 3954053e8..8841963c1 100644 --- a/java/google/registry/keyring/api/Keyring.java +++ b/java/google/registry/keyring/api/Keyring.java @@ -149,15 +149,6 @@ public interface Keyring extends AutoCloseable { */ String getJsonCredential(); - /** - * Returns Braintree API private key for Registry. - * - *

This is a base32 value copied from the Braintree website. - * - * @see google.registry.config.RegistryConfig.ConfigModule#provideBraintreePublicKey - */ - String getBraintreePrivateKey(); - // Don't throw so try-with-resources works better. @Override void close(); diff --git a/java/google/registry/keyring/kms/KmsKeyring.java b/java/google/registry/keyring/kms/KmsKeyring.java index d4e4a9e89..f18241447 100644 --- a/java/google/registry/keyring/kms/KmsKeyring.java +++ b/java/google/registry/keyring/kms/KmsKeyring.java @@ -64,7 +64,6 @@ public class KmsKeyring implements Keyring { } enum StringKeyLabel { - BRAINTREE_PRIVATE_KEY_STRING, ICANN_REPORTING_PASSWORD_STRING, JSON_CREDENTIAL_STRING, MARKSDB_DNL_LOGIN_STRING, @@ -150,11 +149,6 @@ public class KmsKeyring implements Keyring { return getString(StringKeyLabel.JSON_CREDENTIAL_STRING); } - @Override - public String getBraintreePrivateKey() { - return getString(StringKeyLabel.BRAINTREE_PRIVATE_KEY_STRING); - } - /** No persistent resources are maintained for this Keyring implementation. */ @Override public void close() {} diff --git a/java/google/registry/keyring/kms/KmsUpdater.java b/java/google/registry/keyring/kms/KmsUpdater.java index 6a0bc6930..1a40ddbd7 100644 --- a/java/google/registry/keyring/kms/KmsUpdater.java +++ b/java/google/registry/keyring/kms/KmsUpdater.java @@ -24,7 +24,6 @@ import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.BRDA_SIGNING import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_RECEIVER_PUBLIC; import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_SIGNING_PUBLIC; import static google.registry.keyring.kms.KmsKeyring.PublicKeyLabel.RDE_STAGING_PUBLIC; -import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.BRAINTREE_PRIVATE_KEY_STRING; import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.ICANN_REPORTING_PASSWORD_STRING; import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.JSON_CREDENTIAL_STRING; import static google.registry.keyring.kms.KmsKeyring.StringKeyLabel.MARKSDB_DNL_LOGIN_STRING; @@ -116,10 +115,6 @@ public final class KmsUpdater { return setString(credential, JSON_CREDENTIAL_STRING); } - public KmsUpdater setBraintreePrivateKey(String braintreePrivateKey) { - return setString(braintreePrivateKey, BRAINTREE_PRIVATE_KEY_STRING); - } - /** * Generates new encryption keys in KMS, encrypts the updated secrets with them, and persists the * encrypted secrets to Datastore. diff --git a/java/google/registry/model/registrar/Registrar.java b/java/google/registry/model/registrar/Registrar.java index d02e77c95..e45327456 100644 --- a/java/google/registry/model/registrar/Registrar.java +++ b/java/google/registry/model/registrar/Registrar.java @@ -158,16 +158,6 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable SUSPENDED; } - /** Method for acquiring money from a registrar customer. */ - public enum BillingMethod { - - /** Billing method where billing invoice data is exported to an external accounting system. */ - EXTERNAL, - - /** Billing method where we accept Braintree credit card payments in the Registrar Console. */ - BRAINTREE; - } - /** Regex for E.164 phone number format specified by {@code contact.xsd}. */ private static final Pattern E164_PATTERN = Pattern.compile("\\+[0-9]{1,3}\\.[0-9]{1,14}"); @@ -398,16 +388,6 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable */ boolean contactsRequireSyncing = true; - /** - * Method for receiving money from a registrar customer. - * - *

Each registrar may opt-in to their preferred billing method. This value can be changed at - * any time using the {@code update_registrar} command. - * - *

Note: This value should not be changed if the balance is non-zero. - */ - BillingMethod billingMethod; - /** Whether the registrar must acknowledge the price to register non-standard-priced domains. */ boolean premiumPriceAckRequired; @@ -555,10 +535,6 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable return driveFolderId; } - public BillingMethod getBillingMethod() { - return firstNonNull(billingMethod, BillingMethod.EXTERNAL); - } - /** * Returns a list of all {@link RegistrarContact} objects for this registrar sorted by their email * address. @@ -834,11 +810,6 @@ public class Registrar extends ImmutableObject implements Buildable, Jsonifiable return this; } - public Builder setBillingMethod(BillingMethod billingMethod) { - getInstance().billingMethod = billingMethod; - return this; - } - public Builder setPassword(String password) { // Passwords must be [6,16] chars long. See "pwType" in the base EPP schema of RFC 5730. checkArgument( diff --git a/java/google/registry/module/frontend/BUILD b/java/google/registry/module/frontend/BUILD index a37dec480..1f99a1b17 100644 --- a/java/google/registry/module/frontend/BUILD +++ b/java/google/registry/module/frontend/BUILD @@ -8,7 +8,6 @@ java_library( name = "frontend", srcs = glob(["*.java"]), deps = [ - "//java/google/registry/braintree", "//java/google/registry/config", "//java/google/registry/dns", "//java/google/registry/flows", diff --git a/java/google/registry/module/frontend/FrontendComponent.java b/java/google/registry/module/frontend/FrontendComponent.java index 93410de45..8d5700437 100644 --- a/java/google/registry/module/frontend/FrontendComponent.java +++ b/java/google/registry/module/frontend/FrontendComponent.java @@ -17,7 +17,6 @@ package google.registry.module.frontend; import com.google.monitoring.metrics.MetricReporter; import dagger.Component; import dagger.Lazy; -import google.registry.braintree.BraintreeModule; import google.registry.config.RegistryConfig.ConfigModule; import google.registry.flows.ServerTridProviderModule; import google.registry.flows.custom.CustomLogicFactoryModule; @@ -34,7 +33,7 @@ import google.registry.request.Modules.UrlFetchTransportModule; import google.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule; import google.registry.request.Modules.UserServiceModule; import google.registry.request.auth.AuthModule; -import google.registry.ui.ConsoleConfigModule; +import google.registry.ui.ConsoleDebug.ConsoleConfigModule; import google.registry.util.SystemClock.SystemClockModule; import google.registry.util.SystemSleeper.SystemSleeperModule; import javax.inject.Singleton; @@ -45,7 +44,6 @@ import javax.inject.Singleton; modules = { AppIdentityCredentialModule.class, AuthModule.class, - BraintreeModule.class, ConfigModule.class, ConsoleConfigModule.class, CustomLogicFactoryModule.class, diff --git a/java/google/registry/module/frontend/FrontendRequestComponent.java b/java/google/registry/module/frontend/FrontendRequestComponent.java index badeb2131..316da2b51 100644 --- a/java/google/registry/module/frontend/FrontendRequestComponent.java +++ b/java/google/registry/module/frontend/FrontendRequestComponent.java @@ -26,8 +26,6 @@ import google.registry.request.RequestComponentBuilder; import google.registry.request.RequestModule; import google.registry.request.RequestScope; import google.registry.ui.server.registrar.ConsoleUiAction; -import google.registry.ui.server.registrar.RegistrarPaymentAction; -import google.registry.ui.server.registrar.RegistrarPaymentSetupAction; import google.registry.ui.server.registrar.RegistrarSettingsAction; /** Dagger component with per-request lifetime for "default" App Engine module. */ @@ -44,8 +42,6 @@ interface FrontendRequestComponent { EppConsoleAction eppConsoleAction(); EppTlsAction eppTlsAction(); FlowComponent.Builder flowComponentBuilder(); - RegistrarPaymentAction registrarPaymentAction(); - RegistrarPaymentSetupAction registrarPaymentSetupAction(); RegistrarSettingsAction registrarSettingsAction(); @Subcomponent.Builder diff --git a/java/google/registry/repositories.bzl b/java/google/registry/repositories.bzl index eb3ac5454..9bf9427ed 100644 --- a/java/google/registry/repositories.bzl +++ b/java/google/registry/repositories.bzl @@ -23,7 +23,6 @@ def domain_registry_bazel_check(): def domain_registry_repositories( omit_com_beust_jcommander=False, - omit_com_braintreepayments_gateway_braintree_java=False, omit_com_fasterxml_jackson_core=False, omit_com_fasterxml_jackson_core_jackson_annotations=False, omit_com_fasterxml_jackson_core_jackson_databind=False, @@ -163,8 +162,6 @@ def domain_registry_repositories( domain_registry_bazel_check() if not omit_com_beust_jcommander: com_beust_jcommander() - if not omit_com_braintreepayments_gateway_braintree_java: - com_braintreepayments_gateway_braintree_java() if not omit_com_fasterxml_jackson_core: com_fasterxml_jackson_core() if not omit_com_fasterxml_jackson_core_jackson_annotations: @@ -447,17 +444,6 @@ def com_beust_jcommander(): licenses = ["notice"], # The Apache Software License, Version 2.0 ) -def com_braintreepayments_gateway_braintree_java(): - java_import_external( - name = "com_braintreepayments_gateway_braintree_java", - jar_sha256 = "e6fa51822d05334971d60a8353d4bfcab155b9639d9d8d3d052fe75ead534dd9", - jar_urls = [ - "http://domain-registry-maven.storage.googleapis.com/repo1.maven.org/maven2/com/braintreepayments/gateway/braintree-java/2.54.0/braintree-java-2.54.0.jar", - "http://repo1.maven.org/maven2/com/braintreepayments/gateway/braintree-java/2.54.0/braintree-java-2.54.0.jar", - ], - licenses = ["notice"], # MIT license - ) - def com_fasterxml_jackson_core(): java_import_external( name = "com_fasterxml_jackson_core", diff --git a/java/google/registry/tools/CreateOrUpdateRegistrarCommand.java b/java/google/registry/tools/CreateOrUpdateRegistrarCommand.java index e1b88cab1..1b828c926 100644 --- a/java/google/registry/tools/CreateOrUpdateRegistrarCommand.java +++ b/java/google/registry/tools/CreateOrUpdateRegistrarCommand.java @@ -29,7 +29,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import google.registry.model.registrar.Registrar; -import google.registry.model.registrar.Registrar.BillingMethod; import google.registry.model.registrar.RegistrarAddress; import google.registry.model.registry.Registry; import google.registry.tools.params.KeyValueMapParameter.CurrencyUnitToStringMap; @@ -187,12 +186,6 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand { ) private Map billingAccountMap; - @Nullable - @Parameter( - names = "--billing_method", - description = "Method by which registry bills this registrar customer") - private BillingMethod billingMethod; - @Nullable @Parameter( names = "--street", @@ -367,7 +360,6 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand { newBillingAccountMap.putAll(billingAccountMap); builder.setBillingAccountMap(newBillingAccountMap); } - Optional.ofNullable(billingMethod).ifPresent(builder::setBillingMethod); List streetAddressFields = Arrays.asList(street, city, state, zip, countryCode); checkArgument( streetAddressFields.stream().anyMatch(isNull()) diff --git a/java/google/registry/tools/GetKeyringSecretCommand.java b/java/google/registry/tools/GetKeyringSecretCommand.java index 0f0236f85..ad832f5c4 100644 --- a/java/google/registry/tools/GetKeyringSecretCommand.java +++ b/java/google/registry/tools/GetKeyringSecretCommand.java @@ -57,9 +57,6 @@ final class GetKeyringSecretCommand implements RemoteApiCommand { Security.addProvider(new BouncyCastleProvider()); switch (keyringKeyName) { - case BRAINTREE_PRIVATE_KEY: - out.write(KeySerializer.serializeString(keyring.getBraintreePrivateKey())); - break; case BRDA_RECEIVER_PUBLIC_KEY: out.write(KeySerializer.serializePublicKey(keyring.getBrdaReceiverKey())); break; diff --git a/java/google/registry/tools/UpdateKmsKeyringCommand.java b/java/google/registry/tools/UpdateKmsKeyringCommand.java index 11c8780ad..4137148c0 100644 --- a/java/google/registry/tools/UpdateKmsKeyringCommand.java +++ b/java/google/registry/tools/UpdateKmsKeyringCommand.java @@ -56,9 +56,6 @@ final class UpdateKmsKeyringCommand implements RemoteApiCommand { byte[] input = Files.readAllBytes(inputPath); switch (keyringKeyName) { - case BRAINTREE_PRIVATE_KEY: - kmsUpdater.setBraintreePrivateKey(deserializeString(input)); - break; case BRDA_RECEIVER_PUBLIC_KEY: kmsUpdater.setBrdaReceiverPublicKey(deserializePublicKey(input)); break; diff --git a/java/google/registry/tools/params/KeyringKeyName.java b/java/google/registry/tools/params/KeyringKeyName.java index 6f7804ac9..c97a73a22 100644 --- a/java/google/registry/tools/params/KeyringKeyName.java +++ b/java/google/registry/tools/params/KeyringKeyName.java @@ -21,7 +21,6 @@ package google.registry.tools.params; * any secret update command such as UpdateKmsKeyringCommand. */ public enum KeyringKeyName { - BRAINTREE_PRIVATE_KEY, BRDA_RECEIVER_PUBLIC_KEY, BRDA_SIGNING_KEY_PAIR, BRDA_SIGNING_PUBLIC_KEY, diff --git a/java/google/registry/ui/BUILD b/java/google/registry/ui/BUILD index 8240e7ed9..4a9d9a99d 100644 --- a/java/google/registry/ui/BUILD +++ b/java/google/registry/ui/BUILD @@ -10,7 +10,6 @@ exports_files(["globals.txt"]) filegroup( name = "runfiles", srcs = glob(["assets/**"]) + [ - "brain_bin.js", "registrar_bin.js", "//java/google/registry/ui/css:registrar_bin.css", "//java/google/registry/ui/html:html_files", @@ -27,7 +26,6 @@ filegroup( filegroup( name = "runfiles_debug", srcs = [ - ":brain_bin", ":deps", ":registrar_bin", ":registrar_dbg", @@ -63,7 +61,6 @@ zip_file( out = "ui_debug.war", data = [":runfiles_debug"], mappings = { - "domain_registry/java/google/registry/ui/brain_bin.js.map": "assets/js/brain_bin.js.map", "domain_registry/java/google/registry/ui/registrar_bin.js.map": "assets/js/registrar_bin.js.map", "domain_registry/java/google/registry/ui/registrar_dbg.js": "assets/js/registrar_dbg.js", "domain_registry/java/google/registry/ui/css/registrar_dbg.css": "assets/css/registrar_dbg.css", @@ -77,7 +74,6 @@ java_library( srcs = glob(["*.java"]), visibility = ["//visibility:public"], deps = [ - "//java/google/registry/config", "@com_google_appengine_api_1_0_sdk", "@com_google_code_findbugs_jsr305", "@com_google_dagger", @@ -124,16 +120,3 @@ closure_js_binary( "//java/google/registry/ui/js/registrar", ], ) - -################################################################################ -## Braintree Payment Method Frame (Brainframe) - -closure_js_binary( - name = "brain_bin", - entry_points = ["goog:registry.registrar.BrainFrame.main"], - output_wrapper = "%output%//# sourceMappingURL=brain_bin.js.map", - deps = [ - "//java/google/registry/ui/externs", - "//java/google/registry/ui/js/registrar", - ], -) diff --git a/java/google/registry/ui/ConsoleConfigModule.java b/java/google/registry/ui/ConsoleConfigModule.java deleted file mode 100644 index 15bf5ee64..000000000 --- a/java/google/registry/ui/ConsoleConfigModule.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.ui; - -import com.google.appengine.api.users.UserService; -import dagger.Module; -import dagger.Provides; -import google.registry.config.RegistryConfig.Config; - -/** Dagger module for UI configuration. */ -@Module -public final class ConsoleConfigModule { // TODO(b/26829015): Move to config package. - - @Provides - static ConsoleDebug provideConsoleDebug() { - return ConsoleDebug.get(); - } - - /** URL of Braintree iframe sandbox iframe static HTML file. */ - @Provides - @Config("brainframe") - static String provideBrainframe( - ConsoleDebug debug, - UserService userService, - @Config("projectId") String projectId) { - switch (debug) { - case PRODUCTION: - return String.format("https://%s.storage.googleapis.com/%s", - projectId, - userService.isUserLoggedIn() && userService.isUserAdmin() - ? "brainframe-map.html" - : "brainframe.html"); - case DEBUG: - case RAW: - case TEST: - return "/assets/html/insecure-brainframe.html"; - default: - throw new AssertionError(debug.toString()); - } - } -} diff --git a/java/google/registry/ui/ConsoleDebug.java b/java/google/registry/ui/ConsoleDebug.java index f9e7e2d16..31e748c42 100644 --- a/java/google/registry/ui/ConsoleDebug.java +++ b/java/google/registry/ui/ConsoleDebug.java @@ -14,6 +14,9 @@ package google.registry.ui; +import dagger.Module; +import dagger.Provides; + /** Enum defining which JS/CSS files get rendered in a soy templates. */ public enum ConsoleDebug { @@ -44,4 +47,14 @@ public enum ConsoleDebug { public static void set(ConsoleDebug value) { System.setProperty(PROPERTY, value.toString()); } + + /** Dagger module for ConsoleDebug. */ + @Module + public static final class ConsoleConfigModule { + + @Provides + static ConsoleDebug provideConsoleDebug() { + return ConsoleDebug.get(); + } + } } diff --git a/java/google/registry/ui/assets/html/brainframe-alpha.html b/java/google/registry/ui/assets/html/brainframe-alpha.html deleted file mode 100644 index 6efcfa671..000000000 --- a/java/google/registry/ui/assets/html/brainframe-alpha.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - -
- diff --git a/java/google/registry/ui/assets/html/brainframe.html b/java/google/registry/ui/assets/html/brainframe.html deleted file mode 100644 index 09a4d0156..000000000 --- a/java/google/registry/ui/assets/html/brainframe.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - -
- diff --git a/java/google/registry/ui/assets/html/insecure-brainframe.html b/java/google/registry/ui/assets/html/insecure-brainframe.html deleted file mode 100644 index 72b29c07a..000000000 --- a/java/google/registry/ui/assets/html/insecure-brainframe.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - -
- - diff --git a/java/google/registry/ui/assets/html/integration-test-brainframe.html b/java/google/registry/ui/assets/html/integration-test-brainframe.html deleted file mode 100644 index b5c528802..000000000 --- a/java/google/registry/ui/assets/html/integration-test-brainframe.html +++ /dev/null @@ -1,4 +0,0 @@ - - -
- diff --git a/java/google/registry/ui/css/console.css b/java/google/registry/ui/css/console.css index 3a9f96d08..69224bf10 100644 --- a/java/google/registry/ui/css/console.css +++ b/java/google/registry/ui/css/console.css @@ -75,28 +75,3 @@ div.domain-registrar-contact div.tooltip .pointer { padding-left: 1em; list-style: disc inside; } - -.reg-payment p { - max-width: 45em; -} - -/* Note: Empty definitions are for class name minimization. */ - -.reg-payment-form {} - -.reg-payment-form-method {} - -.reg-payment-form-method.kd-formerror { - border: none; -} - -.reg-payment-form-method-info {} - -.reg-payment-form-submit {} - -.reg-payment-form-loader { - vertical-align: middle; - padding-left: 10px; -} - -.reg-payment-again {} diff --git a/java/google/registry/ui/externs/braintree.js b/java/google/registry/ui/externs/braintree.js deleted file mode 100644 index a91340dcc..000000000 --- a/java/google/registry/ui/externs/braintree.js +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Braintree JS SDK v2 externs. This file tells the Closure - * Compiler how Braintree's API is defined, which allows us to use it with type - * safety and dot-notation. - * @externs - */ - - -/** - * @type {!braintreepayments.Braintree} - */ -var braintree; - - -/** - * Fake namespace for pure Closure Compiler types not defined by the SDK. - */ -var braintreepayments = {}; - - - -/** - * @constructor - * @final - */ -braintreepayments.Braintree = function() {}; - - -/** - * @param {string} clientTokenFromServer - * @param {string} integrationType Either 'dropin' or 'custom'. - * @param {{container: (string|!Element|undefined), - * dataCollector: (!Object|undefined), - * enableCORS: (boolean|undefined), - * form: (string|undefined), - * hostedFields: (!Object|undefined), - * id: (string|undefined), - * onError: (function(!braintreepayments.Error)|undefined), - * onPaymentMethodReceived: - * (function(!braintreepayments.PaymentMethod)|undefined), - * onReady: (function(!braintreepayments.Integrator)|undefined), - * paypal: (undefined|{ - * amount: (number|undefined), - * container: (string|!Element), - * currency: (string|undefined), - * displayName: (string|undefined), - * enableBillingAddress: (boolean|undefined), - * enableShippingAddress: (boolean|undefined), - * headless: (boolean|undefined), - * locale: (string|undefined), - * onCancelled: (function()|undefined), - * onPaymentMethodReceived: - * (function(!braintreepayments.PaymentMethod)|undefined), - * onUnsupported: (function()|undefined), - * paymentMethodNonceInputField: (string|!Element|undefined), - * shippingAddressOverride: (undefined|{ - * recipientName: string, - * streetAddress: string, - * extendedAddress: (string|undefined), - * locality: string, - * countryCodeAlpha2: string, - * postalCode: string, - * region: string, - * phone: (string|undefined), - * editable: boolean - * }), - * singleUse: (boolean|undefined) - * }) - * }} options - * @see https://developers.braintreepayments.com/guides/client-sdk/javascript/v2#global-setup - */ -braintreepayments.Braintree.prototype.setup = - function(clientTokenFromServer, integrationType, options) {}; - - - -/** - * @constructor - * @final - * @see https://developers.braintreepayments.com/guides/drop-in/javascript/v2#onerror - */ -braintreepayments.Error = function() {}; - - -/** - * Describes type of error that occurred (e.g. "CONFIGURATION", "VALIDATION".) - * @type {string} - * @const - */ -braintreepayments.Error.prototype.type; - - -/** - * Human-readable string describing the error. - * @type {string} - * @const - */ -braintreepayments.Error.prototype.message; - - -/** - * @type {(!braintreepayments.ErrorDetails|undefined)} - * @const - */ -braintreepayments.Error.prototype.details; - - - -/** - * @constructor - * @final - */ -braintreepayments.ErrorDetails = function() {}; - - -/** - * @type {(!Array|undefined)} - * @const - */ -braintreepayments.ErrorDetails.prototype.invalidFields; - - - -/** - * @constructor - * @final - */ -braintreepayments.ErrorField = function() {}; - - -/** - * Field which failed validation. It will match one of the following: "number", - * "cvv", "expiration", or "postalCode". - * @type {string} - * @const - */ -braintreepayments.ErrorField.prototype.fieldKey; - - -/** - * This will be `true` if the associated input is empty. - * @type {(boolean|undefined)} - * @const - */ -braintreepayments.ErrorField.prototype.isEmpty; - - - -/** - * @constructor - * @final - */ -braintreepayments.Integrator = function() {}; - - -/** - * @type {string} - * @const - */ -braintreepayments.Integrator.prototype.deviceData; - - -/** - * @type {!braintreepayments.PaypalIntegrator} - * @const - */ -braintreepayments.Integrator.prototype.paypal; - - -/** - * @param {function()=} opt_callback - * @see https://developers.braintreepayments.com/guides/client-sdk/javascript/v2#teardown - */ -braintreepayments.Integrator.prototype.teardown = function(opt_callback) {}; - - - -/** - * @constructor - * @final - */ -braintreepayments.PaypalIntegrator = function() {}; - - -/** - * @return {void} - */ -braintreepayments.PaypalIntegrator.prototype.closeAuthFlow = function() {}; - - -/** - * @return {void} - */ -braintreepayments.PaypalIntegrator.prototype.initAuthFlow = function() {}; - - - -/** - * @constructor - * @final - */ -braintreepayments.PaymentMethod = function() {}; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaymentMethod.prototype.nonce; - - -/** - * Either 'CreditCard' or 'PayPalAccount'. - * @type {string} - * @const - */ -braintreepayments.PaymentMethod.prototype.type; - - -/** - * @type {(!braintreepayments.PaymentMethodDetailsCard| - * !braintreepayments.PaymentMethodDetailsPaypal)} - * @const - */ -braintreepayments.PaymentMethod.prototype.details; - - - -/** - * @constructor - * @final - * @see https://developers.braintreepayments.com/guides/client-sdk/javascript/v2#payment-method-details - */ -braintreepayments.PaymentMethodDetailsCard = function() {}; - - -/** - * Can be 'Visa', 'MasterCard', 'Discover', 'Amex', or 'JCB'. - * @type {string} - * @const - */ -braintreepayments.PaymentMethodDetailsCard.prototype.cardType; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaymentMethodDetailsCard.prototype.lastTwo; - - - -/** - * @constructor - * @final - * @see https://developers.braintreepayments.com/guides/paypal/client-side/javascript/v2#options - */ -braintreepayments.PaymentMethodDetailsPaypal = function() {}; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaymentMethodDetailsPaypal.prototype.email; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaymentMethodDetailsPaypal.prototype.firstName; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaymentMethodDetailsPaypal.prototype.lastName; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaymentMethodDetailsPaypal.prototype.phone; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaymentMethodDetailsPaypal.prototype.payerID; - - -/** - * @type {!braintreepayments.PaypalShippingAddress} - * @const - */ -braintreepayments.PaymentMethodDetailsPaypal.prototype.shippingAddress; - - -/** - * @type {(!braintreepayments.PaypalBillingAddress|undefined)} - * @const - */ -braintreepayments.PaymentMethodDetailsPaypal.prototype.billingAddress; - - - -/** - * @constructor - * @final - */ -braintreepayments.PaypalShippingAddress = function() {}; - - -/** - * @type {number} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.id; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.type; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.recipientName; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.streetAddress; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.extendedAddress; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.locality; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.region; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.postalCode; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.countryCodeAlpha; - - -/** - * @type {boolean} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.defaultAddress; - - -/** - * @type {boolean} - * @const - */ -braintreepayments.PaypalShippingAddress.prototype.preferredAddress; - - - -/** - * @constructor - * @final - */ -braintreepayments.PaypalBillingAddress = function() {}; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalBillingAddress.prototype.streetAddress; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalBillingAddress.prototype.extendedAddress; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalBillingAddress.prototype.locality; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalBillingAddress.prototype.region; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalBillingAddress.prototype.postalCode; - - -/** - * @type {string} - * @const - */ -braintreepayments.PaypalBillingAddress.prototype.countryCodeAlpha2; diff --git a/java/google/registry/ui/externs/rpc_payment.js b/java/google/registry/ui/externs/rpc_payment.js deleted file mode 100644 index 8fefc4b19..000000000 --- a/java/google/registry/ui/externs/rpc_payment.js +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview RegistrarPaymentAction JSON RPC definitions. - * @externs - */ - - -/** - * @suppress {duplicate} - */ -var registry = {}; - - -/** - * @suppress {duplicate} - */ -registry.rpc = {}; -registry.rpc.Payment = {}; - - -/** - * @typedef {{ - * currency: string, - * amount: string, - * paymentMethodNonce: string - * }} - */ -registry.rpc.Payment.Request; - - -/** - * @typedef {registry.json.Response.} - */ -registry.rpc.Payment.Response; - - - -/** - * @constructor - */ -registry.rpc.Payment.Result = function() {}; - - -/** - * @type {string} - */ -registry.rpc.Payment.Result.prototype.id; - - -/** - * @type {string} - */ -registry.rpc.Payment.Result.prototype.formattedAmount; diff --git a/java/google/registry/ui/externs/rpc_paymentsetup.js b/java/google/registry/ui/externs/rpc_paymentsetup.js deleted file mode 100644 index c6d8cab36..000000000 --- a/java/google/registry/ui/externs/rpc_paymentsetup.js +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview RegistrarPaymentSetupAction JSON RPC definitions. - * @externs - */ - - -/** - * @suppress {duplicate} - */ -var registry = {}; - - -/** - * @suppress {duplicate} - */ -registry.rpc = {}; -registry.rpc.PaymentSetup = {}; - - -/** - * @typedef {Object} - */ -registry.rpc.PaymentSetup.Request; - - -/** - * @typedef {registry.json.Response.} - */ -registry.rpc.PaymentSetup.Response; - - - -/** - * @constructor - */ -registry.rpc.PaymentSetup.Result = function() {}; - - -/** - * @type {string} - */ -registry.rpc.PaymentSetup.Result.prototype.token; - - -/** - * @type {string} - */ -registry.rpc.PaymentSetup.Result.prototype.brainframe; - - -/** - * @type {!Array.} - */ -registry.rpc.PaymentSetup.Result.prototype.currencies; diff --git a/java/google/registry/ui/js/registrar/brainframe.js b/java/google/registry/ui/js/registrar/brainframe.js deleted file mode 100644 index 522fd5c4f..000000000 --- a/java/google/registry/ui/js/registrar/brainframe.js +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('registry.registrar.BrainFrame'); -goog.provide('registry.registrar.BrainFrame.main'); - -goog.require('goog.Timer'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.events.EventHandler'); -goog.require('goog.events.EventType'); -goog.require('goog.json'); -goog.require('goog.object'); -goog.require('goog.style'); - -goog.forwardDeclare('goog.events.BrowserEvent'); - - - -/** - * Sandboxed iframe for Braintree JS SDK v2 iframe. - * - *

This class adds an additional layer of security between the Registrar - * Console and JavaScript loaded from Braintree's web server. - * - *

The main function for this class is compiled into a separate binary, - * which is loaded within an iframe that's hosted on a different domain than - * the production environment. This ensures that cross origin browser security - * policies take effect. - * - * @param {string} origin FQDN of production environment. - * @param {string} containerId ID of Braintree container element. - * @constructor - * @extends {goog.events.EventHandler} - * @final - */ -registry.registrar.BrainFrame = function(origin, containerId) { - registry.registrar.BrainFrame.base(this, 'constructor'); - - /** - * Hostname of production registry, e.g. domain-registry.appspot.com. - * @private {string} - * @const - */ - this.origin_ = origin; - - /** - * Div that wraps Braintree iframe. - * @private {!Element} - * @const - */ - this.container_ = goog.dom.getRequiredElement(containerId); - - /** - * Last known height of `container_`. - * @private {number} - */ - this.containerHeight_ = 0; - - /** - * Timer polling for changes in Braintree iframe height. - * @private {!goog.Timer} - * @const - */ - this.resizeTimer_ = new goog.Timer(1000 / 30); - this.registerDisposable(this.resizeTimer_); - this.listen(this.resizeTimer_, goog.Timer.TICK, this.onResizeTimer_); - - /** - * Form that wraps `container_`. - * @private {?Element} - * @const - */ - this.form_ = goog.dom.getAncestorByTagNameAndClass(this.container_, - goog.dom.TagName.FORM); - goog.asserts.assert(this.form_ != null); - - /** - * State indicating if we're submitting at behest of parent. - * @private {boolean} - */ - this.isSubmitting_ = false; - - this.listen(goog.global.window, - goog.events.EventType.MESSAGE, - this.onMessage_); -}; -goog.inherits(registry.registrar.BrainFrame, goog.events.EventHandler); - - -/** - * Runs Braintree sandbox environment. - */ -registry.registrar.BrainFrame.prototype.run = function() { - this.send_( - 'type', registry.registrar.BrainFrame.MessageType.TOKEN_REQUEST); -}; - - -/** - * Handles message from parent iframe which sends Braintree token. - * @param {!goog.events.BrowserEvent} e - * @private - */ -registry.registrar.BrainFrame.prototype.onMessage_ = function(e) { - var msg = /** @type {!MessageEvent.} */ (e.getBrowserEvent()); - if (msg.source != goog.global.window.parent) { - return; - } - if (this.origin_ != '*' && this.origin_ != msg.origin) { - throw new Error( - 'Message origin is "' + msg.origin + '" but wanted: ' + this.origin_); - } - var data = /** @type {!Object} */ (JSON.parse(msg.data)); - switch (goog.object.get(data, 'type')) { - case registry.registrar.BrainFrame.MessageType.TOKEN_RESPONSE: - goog.global.braintree.setup(goog.object.get(data, 'token'), 'dropin', { - container: this.container_, - onPaymentMethodReceived: goog.bind(this.onPaymentMethod_, this), - onReady: goog.bind(this.onReady_, this), - onError: goog.bind(this.onError_, this) - }); - this.resizeTimer_.start(); - break; - case registry.registrar.BrainFrame.MessageType.SUBMIT_REQUEST: - this.isSubmitting_ = true; - // Trigger Braintree JS SDK submit event listener. It does not appear to - // be possible to do this using the Closure Library. This is IE 9+ only. - this.form_.dispatchEvent(new Event(goog.events.EventType.SUBMIT)); - break; - default: - throw Error('Unexpected message: ' + msg.data); - } -}; - - -/** - * Polls for resizes of Braintree iframe and propagates them to the parent - * frame which will then use it to resize this iframe. - * @private - */ -registry.registrar.BrainFrame.prototype.onResizeTimer_ = function() { - var height = goog.style.getSize(this.container_).height; - if (height != this.containerHeight_) { - this.send_( - 'type', registry.registrar.BrainFrame.MessageType.RESIZE_REQUEST, - 'height', height); - this.containerHeight_ = height; - } -}; - - -/** - * Callback Braintree iframe has fully loaded. - * @private - */ -registry.registrar.BrainFrame.prototype.onReady_ = function() { - this.send_('type', registry.registrar.BrainFrame.MessageType.READY); -}; - - -/** - * Callback Braintree says an error happened. - * @param {!braintreepayments.Error} error - * @private - */ -registry.registrar.BrainFrame.prototype.onError_ = function(error) { - this.isSubmitting_ = false; - this.send_('type', registry.registrar.BrainFrame.MessageType.SUBMIT_ERROR, - 'message', error.message); -}; - - -/** - * Callback when user successfully gave Braintree payment details. - * @param {!braintreepayments.PaymentMethod} pm - * @private - */ -registry.registrar.BrainFrame.prototype.onPaymentMethod_ = function(pm) { - // TODO(b/26829319): The Braintree JS SDK does not seem to recognize the - // enter key while embedded inside our sandbox iframe. So - // at this time, this callback will only be invoked after - // we've submitted the form manually at the behest of - // payment.js, which means isSubmitting_ will be true. - this.send_( - 'type', registry.registrar.BrainFrame.MessageType.PAYMENT_METHOD, - 'submit', this.isSubmitting_, - 'method', pm); - this.isSubmitting_ = false; -}; - - -/** - * Sends message to parent iframe. - * @param {...*} var_args Passed along to `goog.object.create`. - * @private - */ -registry.registrar.BrainFrame.prototype.send_ = function(var_args) { - goog.asserts.assert(arguments[0] == 'type'); - registry.registrar.BrainFrame.postMessage_( - goog.json.serialize(goog.object.create.apply(null, arguments)), - this.origin_); -}; - - -/** - * Delegates to `window.parent.postMessage`. This method exists because - * IE will not allow us to mock methods on the window object. - * @param {string} message - * @param {string} origin - * @private - */ -registry.registrar.BrainFrame.postMessage_ = function(message, origin) { - goog.global.window.parent.postMessage(message, origin); -}; - - -/** - * Message types passed between brainframe and payment page. - * @enum {string} - */ -registry.registrar.BrainFrame.MessageType = { - - /** Brainframe asks payment page for Braintree token. */ - TOKEN_REQUEST: 'token_request', - - /** Payment page sends brainframe Braintree token. */ - TOKEN_RESPONSE: 'token_response', - - /** Brainframe asks payment page to be resized. */ - RESIZE_REQUEST: 'resize_request', - - /** Brainframe tells payment page it finished loading. */ - READY: 'ready', - - /** Payment page asks brainframe to submit Braintree payment method form. */ - SUBMIT_REQUEST: 'submit_request', - - /** Brainframe tells payment page it failed to submit. */ - SUBMIT_ERROR: 'submit_error', - - /** Brainframe gives payment method info and nonce to payment page. */ - PAYMENT_METHOD: 'payment_method' -}; - - -/** - * Entrypoint for {@link registry.registrar.BrainFrame}. - * @param {string} origin - * @param {string} containerId - * @export - */ -registry.registrar.BrainFrame.main = function(origin, containerId) { - new registry.registrar.BrainFrame(origin, containerId).run(); -}; diff --git a/java/google/registry/ui/js/registrar/console.js b/java/google/registry/ui/js/registrar/console.js index 68927f16e..99d8a4cfa 100644 --- a/java/google/registry/ui/js/registrar/console.js +++ b/java/google/registry/ui/js/registrar/console.js @@ -26,7 +26,6 @@ goog.require('registry.registrar.Dashboard'); goog.require('registry.registrar.Domain'); goog.require('registry.registrar.EppSession'); goog.require('registry.registrar.Host'); -goog.require('registry.registrar.Payment'); goog.require('registry.registrar.Resources'); goog.require('registry.registrar.SecuritySettings'); goog.require('registry.registrar.WhoisSettings'); @@ -86,7 +85,6 @@ registry.registrar.Console = function(params) { this.pageMap['contact-us'] = registry.registrar.ContactUs; this.pageMap['resources'] = registry.registrar.Resources; this.pageMap['contact'] = registry.registrar.Contact; - this.pageMap['payment'] = registry.registrar.Payment; this.pageMap['domain'] = registry.registrar.Domain; this.pageMap['host'] = registry.registrar.Host; this.pageMap[''] = registry.registrar.Dashboard; diff --git a/java/google/registry/ui/js/registrar/payment.js b/java/google/registry/ui/js/registrar/payment.js deleted file mode 100644 index 154953949..000000000 --- a/java/google/registry/ui/js/registrar/payment.js +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -goog.provide('registry.registrar.Payment'); - -goog.require('goog.Uri'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.events.EventType'); -goog.require('goog.json'); -goog.require('goog.object'); -goog.require('goog.soy'); -goog.require('registry.Component'); -goog.require('registry.MenuButton'); -goog.require('registry.Session'); -goog.require('registry.forms'); -goog.require('registry.registrar.BrainFrame'); -goog.require('registry.soy.registrar.console'); -goog.require('registry.soy.registrar.payment'); -goog.require('registry.util'); - -goog.forwardDeclare('goog.events.BrowserEvent'); -goog.forwardDeclare('registry.registrar.Console'); - - - -/** - * Page allowing registrar to send money to registry. - * - *

This page contains a form that asks the user to enter an arbitrary amount - * and a payment method, which can be credit card or PayPal. Multiple - * currencies are supported. - * - *

PCI Compliance

- * - *

We don't have any access whatsoever to the credit card information. We - * embed an iframe run by Braintree Payments. The user can then provide his - * credit card (or PayPal) details directly to Braintree. Braintree then gives - * us a nonce value representing the payment method, which we can use to issue - * the transaction. - * - *

Bidirectional Protection

- * - *

To use Braintree's iframe, we need to load a script from their server. We - * don't want that script to have access to the Registrar Console. If Braintree - * got pwnd, the attacker would be able to issue EPP commands as a registrar. - * - *

We fix this problem by embedding the Braintree iframe inside another - * sandbox iframe that's hosted from a Cloud Storage bucket. This frame is - * defined by `brainframe.html`. It's basically an empty shell that sends - * a request back to the production environment for `brainframe.js`. - * - *

The importance of the Cloud Storage bucket is that it is served from a - * separate domain. This causes the browser to forbid the iframe from accessing - * the contents of the parent frame. The HTML5 `sandbox` attribute does - * this too, but we can't use it, because the Venmo functionality in the - * Braintree JS SDK needs to be able to access `document.cookie`, which - * is forbidden in a sandbox environment. This HTML5 `sandbox` feature is - * also not available in older versions of Internet Explorer. - * - *

Business Logic

- * - *

This page starts off as a loading glyph, while we issue an RPC to the - * backend. We ask for a Braintree token, which currencies are available, and - * the location of the brainframe HTML file. Once we get that data, we render - * the form. - * - *

Once the sandbox iframe inside that form has loaded, it'll send us a - * message asking for the token. We give it the token, which it uses to load - * the Braintree iframe. - * - *

To make sure the sandbox iframe is the same size as the Braintree iframe, - * the sandbox iframe will send us messages on occasion asking to be resized. - * - *

The disabled state of the submit button is managed judiciously. It's - * disabled initially, until we get a READY message from the sandbox iframe, - * indicating that the Braintree iframe is fully loaded. We also disable the - * submit button during the submit process. - * - *

When the user presses the submit button, we send a message to the sandbox - * iframe asking it to submit the Braintree iframe. When the Braintree iframe - * is submitted, it gives the sandbox iframe the the payment method nonce, - * which it passes along to us. Then we pass the form data to the backend via - * the payment RPC, which invokes the Braintree Java API to issue the - * transaction. - * - *

If the payment RPC fails, we'll either show an error on a field, or in a - * bloody butterbar. If it succeeds, then the backend will give us the - * transaction ID assigned by Braintree, which we then render on a success - * page. - * - *

The success page contains a "Make Another Payment" button which, if - * clicked, will reset the state of this page back to the beginning. - * - * @param {!registry.registrar.Console} console - * @param {string} xsrfToken Security token to pass back to the server. - * @constructor - * @extends {registry.Component} - * @final - */ -registry.registrar.Payment = function(console, xsrfToken) { - registry.registrar.Payment.base(this, 'constructor', console); - - /** - * Element in which this page is rendered. - * @private {!Element} - * @const - */ - this.content_ = goog.dom.getRequiredElement('reg-content'); - - /** - * Braintree API nonce token generated by the backend. This value is a - * prerequisite to rendering the Braintree iframe. - * @private {string} - */ - this.token_ = ''; - - /** - * Braintree API nonce value for payment method selected by user. - * @private {string} - */ - this.paymentMethodNonce_ = ''; - - /** - * Currency drop-down widget in form. - * @private {?registry.MenuButton} - */ - this.currencyMenu_ = null; - - /** - * XHR client to `RegistrarPaymentSetupAction`. - * @private {!registry.Session.} - * @const - */ - this.setupRpc_ = - new registry.Session(new goog.Uri('/registrar-payment-setup'), - xsrfToken, - registry.Session.ContentType.JSON); - - /** - * XHR client to `RegistrarPaymentAction`. - * @private {!registry.Session.} - * @const - */ - this.paymentRpc_ = - new registry.Session(new goog.Uri('/registrar-payment'), - xsrfToken, - registry.Session.ContentType.JSON); - - this.listen(goog.global.window, - goog.events.EventType.MESSAGE, - this.onMessage_); -}; -goog.inherits(registry.registrar.Payment, registry.Component); - - -/** @override */ -registry.registrar.Payment.prototype.bindToDom = function(id) { - registry.registrar.Payment.base(this, 'bindToDom', id); - if (!goog.isNull(goog.dom.getElement('reg-app-buttons'))) { - goog.dom.removeChildren(goog.dom.getElement('reg-app-buttons')); - } - if (!registry.registrar.Payment.isBrowserSupported_()) { - goog.soy.renderElement(this.content_, - registry.soy.registrar.payment.unsupported); - return; - } - goog.soy.renderElement(this.content_, registry.soy.registrar.console.loading); - this.setupRpc_.sendXhrIo({}, goog.bind(this.onSetup_, this)); -}; - - -/** - * Handler invoked when we receive information from our backend, such as a - * Braintree token, which is necessary for us to render the payment form. - * @param {!registry.rpc.PaymentSetup.Response} response - * @private - */ -registry.registrar.Payment.prototype.onSetup_ = function(response) { - if (response.status != 'SUCCESS') { - if (response.message == 'not-using-cc-billing') { - goog.soy.renderElement(this.content_, - registry.soy.registrar.payment.notUsingCcBilling); - } else { - registry.forms.displayError(response.message); - } - return; - } - var result = response.results[0]; - this.token_ = result.token; - this.paymentMethodNonce_ = ''; - goog.soy.renderElement(this.content_, - registry.soy.registrar.payment.form, - result); - this.listen( - goog.dom.getRequiredElementByClass(goog.getCssName('reg-payment-form')), - goog.events.EventType.SUBMIT, - this.onSubmit_); - this.currencyMenu_ = - new registry.MenuButton(goog.dom.getRequiredElement('currency')); - this.registerDisposable(this.currencyMenu_); -}; - - -/** - * Handler invoked when payment form is submitted. - * @param {!goog.events.BrowserEvent} e - * @private - */ -registry.registrar.Payment.prototype.onSubmit_ = function(e) { - e.preventDefault(); - this.submit_(); -}; - - -/** - * Submits payment form. - * @private - */ -registry.registrar.Payment.prototype.submit_ = function() { - registry.forms.resetErrors(); - registry.registrar.Payment.setEnabled_(false); - if (this.paymentMethodNonce_ == '') { - this.send_( - 'type', registry.registrar.BrainFrame.MessageType.SUBMIT_REQUEST); - return; - } - this.paymentRpc_.sendXhrIo( - { - amount: goog.dom.getRequiredElement('amount').value, - currency: this.currencyMenu_.getValue(), - paymentMethodNonce: this.paymentMethodNonce_ - }, - goog.bind(this.onPayment_, this)); -}; - - -/** - * Callback for backend payment RPC that issues the transaction. - * @param {!registry.rpc.Payment.Response} response - * @private - */ -registry.registrar.Payment.prototype.onPayment_ = function(response) { - registry.registrar.Payment.setEnabled_(true); - if (response.status != 'SUCCESS') { - registry.forms.displayError(response.message, response.field); - return; - } - goog.soy.renderElement(this.content_, - registry.soy.registrar.payment.success, - response.results[0]); - this.listenOnce( - goog.dom.getRequiredElementByClass(goog.getCssName('reg-payment-again')), - goog.events.EventType.CLICK, - this.bindToDom); -}; - - -/** - * Handler invoked when `brainframe.js` sends us a message. - * @param {!goog.events.BrowserEvent} e - * @private - */ -registry.registrar.Payment.prototype.onMessage_ = function(e) { - var msg = /** @type {!MessageEvent.} */ (e.getBrowserEvent()); - var brainframe = - goog.dom.getElementByClass(goog.getCssName('reg-payment-form-method')); - if (brainframe == null || - msg.source != goog.dom.getFrameContentWindow(brainframe)) { - return; - } - var data; - try { - data = /** @type {!Object} */ (JSON.parse(msg.data)); - } catch (ex) { - // TODO(b/26876003): Figure out why it's possible that the Braintree iframe - // is able to propagate messages up to our level. - registry.util.log(ex, msg.source, msg.data); - return; - } - switch (goog.object.get(data, 'type')) { - case registry.registrar.BrainFrame.MessageType.TOKEN_REQUEST: - goog.asserts.assert(this.token_ != ''); - this.send_( - 'type', registry.registrar.BrainFrame.MessageType.TOKEN_RESPONSE, - 'token', this.token_); - break; - case registry.registrar.BrainFrame.MessageType.RESIZE_REQUEST: - brainframe.height = goog.object.get(data, 'height'); - break; - case registry.registrar.BrainFrame.MessageType.READY: - registry.registrar.Payment.setEnabled_(true); - break; - case registry.registrar.BrainFrame.MessageType.SUBMIT_ERROR: - registry.registrar.Payment.setEnabled_(true); - registry.forms.displayError(goog.object.get(data, 'message'), 'method'); - break; - case registry.registrar.BrainFrame.MessageType.PAYMENT_METHOD: - registry.registrar.Payment.setEnabled_(true); - this.setPaymentMethod_( - /** @type {!braintreepayments.PaymentMethod} */ ( - goog.object.get(data, 'method'))); - if (goog.object.get(data, 'submit')) { - this.submit_(); - } - break; - default: - throw Error('Unexpected message: ' + msg.data); - } -}; - - -/** - * Updates UI to display selected payment method. - * - *

We remove the iframe from the page as soon as this happens, because the - * UI would be busted otherwise. The Braintree UI for changing the payment - * method (after it's been entered) does not appear to stop respond to submit - * events. It also causes ugly scroll bars to appear inside the iframe. - * - *

This approach is also advantageous for screenshot testing. We do not want - * our continuous integration testing system to talk to Braintree's servers. So - * we mock out the brainframe with `integration-test-brainframe.html` - * which only sends us a METHOD message, which we then render ourselves. - * - * @param {!braintreepayments.PaymentMethod} pm - * @private - */ -registry.registrar.Payment.prototype.setPaymentMethod_ = function(pm) { - registry.forms.resetErrors(); - goog.dom.removeNode( - goog.dom.getElementByClass(goog.getCssName('reg-payment-form-method'))); - var paymentMethodInfoBox = - goog.dom.getRequiredElementByClass( - goog.getCssName('reg-payment-form-method-info')); - switch (pm.type) { - case 'CreditCard': - goog.soy.renderElement( - paymentMethodInfoBox, - registry.soy.registrar.payment.methodInfoCard, - {cardType: pm.details.cardType, lastTwo: pm.details.lastTwo}); - break; - case 'PayPalAccount': - goog.soy.renderElement( - paymentMethodInfoBox, - registry.soy.registrar.payment.methodInfoPaypal, - {email: pm.details.email}); - break; - default: - throw Error('Unknown payment method: ' + pm.type); - } - registry.util.setVisible(paymentMethodInfoBox, true); - this.paymentMethodNonce_ = pm.nonce; -}; - - -/** - * Sends message to brainframe. - * @param {...*} var_args Passed along to `goog.object.create`. - * @private - */ -registry.registrar.Payment.prototype.send_ = function(var_args) { - goog.asserts.assert(arguments[0] == 'type'); - var brainframeWindow = - goog.dom.getFrameContentWindow( - goog.dom.getRequiredElementByClass( - goog.getCssName('reg-payment-form-method'))); - // We send a string value to support older versions of IE. - brainframeWindow.postMessage( - goog.json.serialize(goog.object.create.apply(null, arguments)), - '*'); -}; - - -/** - * Enables submit button and hides mini loading glyph. - * @param {boolean} enabled - * @private - */ -registry.registrar.Payment.setEnabled_ = function(enabled) { - registry.forms.setEnabled( - goog.dom.getRequiredElementByClass( - goog.getCssName('reg-payment-form-submit')), enabled); - registry.util.setVisible( - goog.dom.getRequiredElementByClass( - goog.getCssName('reg-payment-form-loader')), !enabled); -}; - - -/** - * Returns `true` if browser has all the features we need. - * @return {boolean} - * @private - * @see "http://caniuse.com/#feat=dispatchevent" - */ -registry.registrar.Payment.isBrowserSupported_ = function() { - // dispatchEvent is used by brainframe.js and is IE 9+. - return goog.object.containsKey( - goog.dom.createElement(goog.dom.TagName.FORM), - 'dispatchEvent'); -}; diff --git a/java/google/registry/ui/server/registrar/BUILD b/java/google/registry/ui/server/registrar/BUILD index 1dedf981e..2723a052f 100644 --- a/java/google/registry/ui/server/registrar/BUILD +++ b/java/google/registry/ui/server/registrar/BUILD @@ -12,7 +12,6 @@ java_library( "//java/google/registry/ui/css:registrar_dbg.css.js", ], deps = [ - "//java/google/registry/braintree", "//java/google/registry/config", "//java/google/registry/export/sheet", "//java/google/registry/flows", diff --git a/java/google/registry/ui/server/registrar/ConsoleUiAction.java b/java/google/registry/ui/server/registrar/ConsoleUiAction.java index e89f493cb..e21a33131 100644 --- a/java/google/registry/ui/server/registrar/ConsoleUiAction.java +++ b/java/google/registry/ui/server/registrar/ConsoleUiAction.java @@ -137,7 +137,6 @@ public final class ConsoleUiAction implements Runnable { Registrar.loadByClientIdCached(clientId), "Registrar %s does not exist", clientId); data.put("xsrfToken", xsrfTokenManager.generateToken(userAuthInfo.user().getEmail())); data.put("clientId", clientId); - data.put("showPaymentLink", registrar.getBillingMethod() == Registrar.BillingMethod.BRAINTREE); data.put("requireFeeExtension", registrar.getPremiumPriceAckRequired()); String payload = TOFU_SUPPLIER.get() diff --git a/java/google/registry/ui/server/registrar/RegistrarPaymentAction.java b/java/google/registry/ui/server/registrar/RegistrarPaymentAction.java deleted file mode 100644 index feb55e24e..000000000 --- a/java/google/registry/ui/server/registrar/RegistrarPaymentAction.java +++ /dev/null @@ -1,350 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.ui.server.registrar; - -import static com.google.common.base.MoreObjects.firstNonNull; -import static com.google.common.base.Strings.emptyToNull; -import static com.google.common.base.Verify.verify; -import static google.registry.security.JsonResponseHelper.Status.ERROR; -import static google.registry.security.JsonResponseHelper.Status.SUCCESS; -import static java.util.Arrays.asList; - -import com.braintreegateway.BraintreeGateway; -import com.braintreegateway.Result; -import com.braintreegateway.Transaction; -import com.braintreegateway.TransactionRequest; -import com.braintreegateway.ValidationError; -import com.braintreegateway.ValidationErrors; -import com.google.common.collect.ImmutableMap; -import com.google.common.flogger.FluentLogger; -import com.google.re2j.Pattern; -import google.registry.config.RegistryConfig.Config; -import google.registry.model.registrar.Registrar; -import google.registry.request.Action; -import google.registry.request.JsonActionRunner; -import google.registry.request.JsonActionRunner.JsonAction; -import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthResult; -import google.registry.security.JsonResponseHelper; -import google.registry.ui.forms.FormField; -import google.registry.ui.forms.FormFieldException; -import java.math.BigDecimal; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import org.joda.money.CurrencyUnit; -import org.joda.money.IllegalCurrencyException; -import org.joda.money.Money; - -/** - * Action handling submission of customer payment form. - * - *

Request Object

- * - *

The request payload is a JSON object with the following fields: - * - *

- *
amount - *
String containing a fixed point value representing the amount of money the registrar - * customer wishes to send the registry. This amount is arbitrary and entered manually by the - * customer in the payment form, as there is currently no integration with the billing system. - *
currency - *
String containing a three letter ISO currency code, which is used to look up the Braintree - * merchant account ID to which payment should be posted. - *
paymentMethodNonce - *
UUID nonce string supplied by the Braintree JS SDK representing the selected payment - * method. - *
- * - *

Response Object

- * - *

The response payload will be a JSON response object (as defined by {@link JsonResponseHelper}) - * which, if successful, will contain a single result object with the following fields: - * - *

- *
id - *
String containing transaction ID returned by Braintree gateway. - *
formattedAmount - *
String containing amount paid, which can be displayed to the customer on a success page. - *
- * - *

Note: These definitions corresponds to Closure Compiler extern {@code - * registry.rpc.Payment} which must be updated should these definitions change. - * - *

PCI Compliance

- * - *

The request object will not contain credit card information, but rather a {@code - * payment_method_nonce} field that's populated by the Braintree JS SDK iframe. - * - * @see RegistrarPaymentSetupAction - */ -@Action( - path = "/registrar-payment", - method = Action.Method.POST, - auth = Auth.AUTH_PUBLIC_LOGGED_IN -) -public final class RegistrarPaymentAction implements Runnable, JsonAction { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - private static final FormField AMOUNT_FIELD = - FormField.named("amount") - .trimmed() - .emptyToNull() - .required() - .matches(Pattern.compile("-?\\d+(?:\\.\\d+)?"), "Invalid number.") - .transform( - BigDecimal.class, - value -> { - BigDecimal result = new BigDecimal(value); - if (result.signum() != 1) { - throw new FormFieldException("Must be a positive number."); - } - return result; - }) - .build(); - - private static final FormField CURRENCY_FIELD = - FormField.named("currency") - .trimmed() - .emptyToNull() - .required() - .matches(Pattern.compile("[A-Z]{3}"), "Invalid currency code.") - .transform( - CurrencyUnit.class, - value -> { - try { - return CurrencyUnit.of(value); - } catch (IllegalCurrencyException ignored) { - throw new FormFieldException("Unknown ISO currency code."); - } - }) - .build(); - - private static final FormField PAYMENT_METHOD_NONCE_FIELD = - FormField.named("paymentMethodNonce") - .trimmed() - .emptyToNull() - .required() - .build(); - - @Inject HttpServletRequest request; - @Inject BraintreeGateway braintreeGateway; - @Inject JsonActionRunner jsonActionRunner; - @Inject AuthResult authResult; - @Inject SessionUtils sessionUtils; - @Inject @Config("braintreeMerchantAccountIds") ImmutableMap accountIds; - @Inject RegistrarPaymentAction() {} - - @Override - public void run() { - jsonActionRunner.run(this); - } - - @Override - public Map handleJsonRequest(Map json) { - Registrar registrar = sessionUtils.getRegistrarForAuthResult(request, authResult); - logger.atInfo().log("Processing payment: %s", json); - String paymentMethodNonce; - Money amount; - String merchantAccountId; - try { - paymentMethodNonce = PAYMENT_METHOD_NONCE_FIELD.extractUntyped(json).get(); - try { - amount = Money.of( - CURRENCY_FIELD.extractUntyped(json).get(), - AMOUNT_FIELD.extractUntyped(json).get()); - } catch (ArithmeticException e) { - // This happens when amount has more precision than the currency allows, e.g. $3.141. - throw new FormFieldException(AMOUNT_FIELD.name(), e.getMessage()); - } - merchantAccountId = accountIds.get(amount.getCurrencyUnit()); - if (merchantAccountId == null) { - throw new FormFieldException(CURRENCY_FIELD.name(), "Unsupported currency."); - } - } catch (FormFieldException e) { - logger.atWarning().withCause(e).log("Form field error in RegistrarPaymentAction."); - return JsonResponseHelper.createFormFieldError(e.getMessage(), e.getFieldName()); - } - Result result = - braintreeGateway.transaction().sale( - new TransactionRequest() - .amount(amount.getAmount()) - .paymentMethodNonce(paymentMethodNonce) - .merchantAccountId(merchantAccountId) - .customerId(registrar.getClientId()) - .options() - .submitForSettlement(true) - .done()); - if (result.isSuccess()) { - return handleSuccessResponse(result.getTarget()); - } else if (result.getTransaction() != null) { - Transaction transaction = result.getTransaction(); - switch (transaction.getStatus()) { - case PROCESSOR_DECLINED: - return handleProcessorDeclined(transaction); - case SETTLEMENT_DECLINED: - return handleSettlementDecline(transaction); - case GATEWAY_REJECTED: - return handleRejection(transaction); - default: - return handleMiscProcessorError(transaction); - } - } else { - return handleValidationErrorResponse(result.getErrors()); - } - } - - /** - * Handles a transaction success response. - * - * @see - * Braintree - Transaction - Success - * @see - * Braintree - Statuses - Transaction - */ - private Map handleSuccessResponse(Transaction transaction) { - // XXX: Currency scaling: https://github.com/braintree/braintree_java/issues/33 - Money amount = - Money.of(CurrencyUnit.of(transaction.getCurrencyIsoCode()), - transaction.getAmount().stripTrailingZeros()); - logger.atInfo().log( - "Transaction for %s via %s %s with ID: %s", - amount, - transaction.getPaymentInstrumentType(), // e.g. credit_card, paypal_account - transaction.getStatus(), // e.g. SUBMITTED_FOR_SETTLEMENT - transaction.getId()); - return JsonResponseHelper - .create(SUCCESS, "Payment processed successfully", asList( - ImmutableMap.of( - "id", transaction.getId(), - "formattedAmount", formatMoney(amount)))); - } - - /** - * Handles a processor declined response. - * - *

This happens when the customer's bank blocks the transaction. - * - * @see - * Braintree - Transaction - Processor declined - * @see - * Braintree - Transactions/Declines - */ - private Map handleProcessorDeclined(Transaction transaction) { - logger.atWarning().log( - "Processor declined: %s %s", - transaction.getProcessorResponseCode(), transaction.getProcessorResponseText()); - return JsonResponseHelper.create(ERROR, - "Payment declined: " + transaction.getProcessorResponseText()); - } - - /** - * Handles a settlement declined response. - * - *

This is a very rare condition that, for all intents and purposes, means the same thing as a - * processor declined response. - * - * @see - * Braintree - Transaction - Processor settlement declined - * @see - * Braintree - Transactions/Declines - */ - private Map handleSettlementDecline(Transaction transaction) { - logger.atWarning().log( - "Settlement declined: %s %s", - transaction.getProcessorSettlementResponseCode(), - transaction.getProcessorSettlementResponseText()); - return JsonResponseHelper.create(ERROR, - "Payment declined: " + transaction.getProcessorSettlementResponseText()); - } - - /** - * Handles a gateway rejection response. - * - *

This happens when a transaction is blocked due to settings we configured ourselves in the - * Braintree control panel. - * - * @see - * Braintree - Transaction - Gateway rejection - * @see - * Braintree - Transactions/Gateway Rejections - * @see - * Braintree - Fruad Tools/Basic Fraud Tools - AVS and CVV rules - * @see - * Braintree - Fraud Tools/Overview - */ - private Map handleRejection(Transaction transaction) { - logger.atWarning().log("Gateway rejection: %s", transaction.getGatewayRejectionReason()); - switch (transaction.getGatewayRejectionReason()) { - case DUPLICATE: - return JsonResponseHelper.create(ERROR, "Payment rejected: Possible duplicate."); - case AVS: - return JsonResponseHelper.create(ERROR, "Payment rejected: Invalid address."); - case CVV: - return JsonResponseHelper.create(ERROR, "Payment rejected: Invalid CVV code."); - case AVS_AND_CVV: - return JsonResponseHelper.create(ERROR, "Payment rejected: Invalid address and CVV code."); - case FRAUD: - return JsonResponseHelper.create(ERROR, - "Our merchant gateway suspects this payment of fraud. Please contact support."); - default: - return JsonResponseHelper.create(ERROR, - "Payment rejected: " + transaction.getGatewayRejectionReason()); - } - } - - /** Handles a miscellaneous transaction processing error response. */ - private Map handleMiscProcessorError(Transaction transaction) { - logger.atWarning().log( - "Error processing transaction: %s %s %s", - transaction.getStatus(), - transaction.getProcessorResponseCode(), - transaction.getProcessorResponseText()); - return JsonResponseHelper.create(ERROR, - "Payment failure: " - + firstNonNull( - emptyToNull(transaction.getProcessorResponseText()), - transaction.getStatus().toString())); - } - - /** - * Handles a validation error response from Braintree. - * - * @see - * Braintree - Transaction - Validation errors - * @see - * Braintree - Validation Errors/All - */ - private Map handleValidationErrorResponse(ValidationErrors validationErrors) { - List errors = validationErrors.getAllDeepValidationErrors(); - verify(!errors.isEmpty(), "Payment failed but validation error list was empty"); - for (ValidationError error : errors) { - logger.atWarning().log( - "Payment validation failed on field: %s\nCode: %s\nMessage: %s", - error.getAttribute(), error.getCode(), error.getMessage()); - } - return JsonResponseHelper - .createFormFieldError(errors.get(0).getMessage(), errors.get(0).getAttribute()); - } - - private static String formatMoney(Money amount) { - String symbol = amount.getCurrencyUnit().getSymbol(Locale.US); - BigDecimal number = amount.getAmount().setScale(amount.getCurrencyUnit().getDecimalPlaces()); - return symbol.length() == 1 ? symbol + number : amount.toString(); - } -} diff --git a/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java b/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java deleted file mode 100644 index 3ccf791d4..000000000 --- a/java/google/registry/ui/server/registrar/RegistrarPaymentSetupAction.java +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.ui.server.registrar; - -import static com.google.common.collect.ImmutableList.toImmutableList; -import static google.registry.security.JsonResponseHelper.Status.ERROR; -import static google.registry.security.JsonResponseHelper.Status.SUCCESS; -import static java.util.Arrays.asList; - -import com.braintreegateway.BraintreeGateway; -import com.google.common.collect.ImmutableMap; -import google.registry.braintree.BraintreeRegistrarSyncer; -import google.registry.config.RegistryConfig.Config; -import google.registry.model.registrar.Registrar; -import google.registry.request.Action; -import google.registry.request.JsonActionRunner; -import google.registry.request.JsonActionRunner.JsonAction; -import google.registry.request.auth.Auth; -import google.registry.request.auth.AuthResult; -import google.registry.security.JsonResponseHelper; -import java.util.Map; -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import org.joda.money.CurrencyUnit; - -/** - * Action returning information needed to render payment form in browser. - * - *

Request Object

- * - *

The request payload must be an empty JSON object. - * - *

Response Object

- * - *

The response payload will be a JSON response object (as defined by {@link JsonResponseHelper}) - * containing a single result object with the following fields: - * - *

- *
brainframe - *
URL for iframe that loads Braintree payment method selector. - *
token - *
Nonce string obtained from the Braintree API which is needed by the Braintree JS SDK. - *
currencies - *
Array of strings, each containing a three letter currency code, which should be displayed - * to the customer in a drop-down field. This will be all currencies for which a Braintree - * merchant account exists. A currency will even be displayed if no TLD is enabled on the - * customer account that bills in that currency. - *
- * - *

Note: These definitions corresponds to Closure Compiler extern {@code - * registry.rpc.PaymentSetup} which must be updated should these definitions change. - * - * @see RegistrarPaymentAction - * @see Generate - * a client token - */ -@Action( - path = "/registrar-payment-setup", - method = Action.Method.POST, - auth = Auth.AUTH_PUBLIC_LOGGED_IN -) -public final class RegistrarPaymentSetupAction implements Runnable, JsonAction { - - @Inject HttpServletRequest request; - @Inject BraintreeGateway braintreeGateway; - @Inject BraintreeRegistrarSyncer customerSyncer; - @Inject JsonActionRunner jsonActionRunner; - @Inject AuthResult authResult; - @Inject SessionUtils sessionUtils; - @Inject @Config("brainframe") String brainframe; - @Inject @Config("braintreeMerchantAccountIds") ImmutableMap accountIds; - @Inject RegistrarPaymentSetupAction() {} - - @Override - public void run() { - jsonActionRunner.run(this); - } - - @Override - public Map handleJsonRequest(Map json) { - Registrar registrar = sessionUtils.getRegistrarForAuthResult(request, authResult); - - if (!json.isEmpty()) { - return JsonResponseHelper.create(ERROR, "JSON request object must be empty"); - } - - // payment.js is hard-coded to display a specific SOY error template for certain error messages. - if (registrar.getBillingMethod() != Registrar.BillingMethod.BRAINTREE) { - // Registrar needs to contact support to have their billing bit flipped. - return JsonResponseHelper.create(ERROR, "not-using-cc-billing"); - } - - // In order to set the customerId field on the payment, the customer must exist. - customerSyncer.sync(registrar); - - return JsonResponseHelper.create( - SUCCESS, - "Success", - asList( - ImmutableMap.of( - "brainframe", brainframe, - "token", braintreeGateway.clientToken().generate(), - "currencies", - accountIds - .keySet() - .stream() - .map(Object::toString) - .collect(toImmutableList())))); - } -} diff --git a/java/google/registry/ui/soy/registrar/Console.soy b/java/google/registry/ui/soy/registrar/Console.soy index 278bc09d8..860aba56a 100644 --- a/java/google/registry/ui/soy/registrar/Console.soy +++ b/java/google/registry/ui/soy/registrar/Console.soy @@ -25,7 +25,6 @@ {@param clientId: string} /** Registrar client identifier. */ {@param username: string} /** Arbitrary username to display. */ {@param logoutUrl: string} /** Generated URL for logging out of Google. */ - {@param showPaymentLink: bool} {@param productName: string} /** Name to display for this software product. */ {@param integrationEmail: string} {@param supportEmail: string} @@ -76,17 +75,12 @@ /** Sidebar nav. Ids on each elt for testing only. */ {template .navbar_ visibility="private"} - {@param showPaymentLink: bool}