Add payment page link to Registrar Console

The payment page has also been updated to refuse to show itself if
the registrar is not set to credit card billing terms.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=117983313
This commit is contained in:
jart 2016-03-23 16:49:56 -07:00 committed by Justine Tunney
parent b6b13333dd
commit 89fa3caaba
14 changed files with 73 additions and 12 deletions

View file

@ -189,9 +189,13 @@ registry.registrar.Payment.prototype.bindToDom = function(id) {
*/ */
registry.registrar.Payment.prototype.onSetup_ = function(response) { registry.registrar.Payment.prototype.onSetup_ = function(response) {
if (response.status != 'SUCCESS') { if (response.status != 'SUCCESS') {
if (response.message == 'sandbox') { // XXX: Hard-coded from backend. // Check for hard-coded error message codes from backend.
if (response.message == 'sandbox') {
goog.soy.renderElement(this.content_, goog.soy.renderElement(this.content_,
registry.soy.registrar.payment.sandbox); registry.soy.registrar.payment.sandbox);
} else if (response.message == 'not-using-cc-billing') {
goog.soy.renderElement(this.content_,
registry.soy.registrar.payment.notUsingCcBilling);
} else { } else {
registry.forms.displayError(response.message); registry.forms.displayError(response.message);
} }

View file

@ -96,6 +96,7 @@ public final class ConsoleUiAction implements Runnable {
data.put("username", userService.getCurrentUser().getNickname()); data.put("username", userService.getCurrentUser().getNickname());
data.put("isAdmin", userService.isUserAdmin()); data.put("isAdmin", userService.isUserAdmin());
data.put("logoutUrl", userService.createLogoutURL(PATH)); data.put("logoutUrl", userService.createLogoutURL(PATH));
data.put("showPaymentLink", registrar.getBillingMethod() == Registrar.BillingMethod.BRAINTREE);
response.setPayload( response.setPayload(
TOFU_SUPPLIER.get() TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.MAIN) .newRenderer(ConsoleSoyInfo.MAIN)

View file

@ -23,6 +23,7 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.config.ConfigModule.Config; import com.google.domain.registry.config.ConfigModule.Config;
import com.google.domain.registry.config.RegistryEnvironment; import com.google.domain.registry.config.RegistryEnvironment;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.request.Action; import com.google.domain.registry.request.Action;
import com.google.domain.registry.request.JsonActionRunner; import com.google.domain.registry.request.JsonActionRunner;
import com.google.domain.registry.request.JsonActionRunner.JsonAction; import com.google.domain.registry.request.JsonActionRunner.JsonAction;
@ -76,6 +77,7 @@ public final class RegistrarPaymentSetupAction implements Runnable, JsonAction {
@Inject BraintreeGateway braintreeGateway; @Inject BraintreeGateway braintreeGateway;
@Inject JsonActionRunner jsonActionRunner; @Inject JsonActionRunner jsonActionRunner;
@Inject Registrar registrar;
@Inject RegistryEnvironment environment; @Inject RegistryEnvironment environment;
@Inject @Config("brainframe") String brainframe; @Inject @Config("brainframe") String brainframe;
@Inject @Config("braintreeMerchantAccountIds") ImmutableMap<CurrencyUnit, String> accountIds; @Inject @Config("braintreeMerchantAccountIds") ImmutableMap<CurrencyUnit, String> accountIds;
@ -91,11 +93,14 @@ public final class RegistrarPaymentSetupAction implements Runnable, JsonAction {
if (!json.isEmpty()) { if (!json.isEmpty()) {
return JsonResponseHelper.create(ERROR, "JSON request object must be empty"); return JsonResponseHelper.create(ERROR, "JSON request object must be empty");
} }
// Prevent registrar customers from accidentally remitting payment via OT&E environment. // payment.js is hard-coded to display a specific SOY error template when encountering the
// following error messages.
if (environment == RegistryEnvironment.SANDBOX) { if (environment == RegistryEnvironment.SANDBOX) {
// XXX: payment.js is hard-coded to display a specific SOY error template when encountering // Prevent registrar customers from accidentally remitting payment via OT&E environment.
// an error message with this specific value.
return JsonResponseHelper.create(ERROR, "sandbox"); return JsonResponseHelper.create(ERROR, "sandbox");
} else 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");
} }
return JsonResponseHelper return JsonResponseHelper
.create(SUCCESS, "Success", asList( .create(SUCCESS, "Success", asList(

View file

@ -12,6 +12,7 @@
{@param username: string} /** Arbitrary username to display. */ {@param username: string} /** Arbitrary username to display. */
{@param isAdmin: bool} /** Is this user an App Engine account admin? */ {@param isAdmin: bool} /** Is this user an App Engine account admin? */
{@param logoutUrl: string} /** Generated URL for logging out of Google. */ {@param logoutUrl: string} /** Generated URL for logging out of Google. */
{@param showPaymentLink: bool}
{call registry.soy.console.header} {call registry.soy.console.header}
{param app: 'registrar' /} {param app: 'registrar' /}
{param subtitle: 'Registrar Console' /} {param subtitle: 'Registrar Console' /}
@ -19,7 +20,7 @@
{call registry.soy.console.googlebar data="all" /} {call registry.soy.console.googlebar data="all" /}
<div id="reg-app"> <div id="reg-app">
<div id="reg-appbar" class="{css kd-appbar}"></div> <div id="reg-appbar" class="{css kd-appbar}"></div>
{call .navbar_ /} {call .navbar_ data="all" /}
<div id="reg-content-and-footer"> <div id="reg-content-and-footer">
<div id="reg-content"> <div id="reg-content">
// Dynamic content goes here. // Dynamic content goes here.
@ -50,12 +51,17 @@
/** Sidebar nav. Ids on each elt for testing only. */ /** Sidebar nav. Ids on each elt for testing only. */
{template .navbar_ private="true"} {template .navbar_ private="true"}
{@param showPaymentLink: bool}
<div id="reg-nav" class="{css kd-content-sidebar}"> <div id="reg-nav" class="{css kd-content-sidebar}">
<ul id="reg-navlist"> <ul id="reg-navlist">
<li> <li>
<a href="/registrar#">Home</a> <a href="/registrar#">Home</a>
<li> <li>
<a href="/registrar#resources">Resources &amp; billing</a> <a href="/registrar#resources">Resources &amp; billing</a>
{if $showPaymentLink}
<li>
<a href="/registrar#payment">Pay invoice</a>
{/if}
<li> <li>
<ul> <ul>
<span class="{css reg-navlist-sub}">Settings</span> <span class="{css reg-navlist-sub}">Settings</span>

View file

@ -124,3 +124,15 @@
login to the production Registrar Console. login to the production Registrar Console.
</div> </div>
{/template} {/template}
/** Page indicating customer is not on credit card billing terms. */
{template .notUsingCcBilling}
<div class="{css reg-payment}">
<h1>Payment Page Disabled</h1>
<p>
Your customer account is not on credit card billing terms. Please{sp}
<a href="/registrar#contact-us">contact support</a> to have your account
switched over.
</div>
{/template}

View file

@ -140,6 +140,7 @@ public enum Fixture {
persistResource( persistResource(
Registrar.loadByClientId("TheRegistrar").asBuilder() Registrar.loadByClientId("TheRegistrar").asBuilder()
.setAllowedTlds(ImmutableSet.of("example", "xn--q9jyb4c")) .setAllowedTlds(ImmutableSet.of("example", "xn--q9jyb4c"))
.setBillingMethod(Registrar.BillingMethod.BRAINTREE)
.build()); .build());
} }
}; };

View file

@ -50,7 +50,8 @@ function setUp() {
username: 'blah', username: 'blah',
logoutUrl: 'omg', logoutUrl: 'omg',
isAdmin: true, isAdmin: true,
clientId: test.testClientId clientId: test.testClientId,
showPaymentLink: false
}); });
registry.registrar.ConsoleTestUtil.setup(test); registry.registrar.ConsoleTestUtil.setup(test);
var regNavlist = $('reg-navlist'); var regNavlist = $('reg-navlist');

View file

@ -49,7 +49,8 @@ function setUp() {
username: 'blah', username: 'blah',
logoutUrl: 'omg', logoutUrl: 'omg',
isAdmin: true, isAdmin: true,
clientId: test.testClientId clientId: test.testClientId,
showPaymentLink: false
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
registry.registrar.ConsoleTestUtil.setup(test); registry.registrar.ConsoleTestUtil.setup(test);

View file

@ -40,7 +40,8 @@ function setUp() {
username: 'blah', username: 'blah',
logoutUrl: 'omg', logoutUrl: 'omg',
isAdmin: true, isAdmin: true,
clientId: 'daddy' clientId: 'daddy',
showPaymentLink: false
}); });
registry.registrar.ConsoleTestUtil.setup(test); registry.registrar.ConsoleTestUtil.setup(test);
} }

View file

@ -46,7 +46,8 @@ function setUp() {
username: 'jart', username: 'jart',
logoutUrl: 'https://justinetunney.com', logoutUrl: 'https://justinetunney.com',
isAdmin: true, isAdmin: true,
clientId: 'ignore' clientId: 'ignore',
showPaymentLink: false
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);

View file

@ -46,7 +46,8 @@ function setUp() {
username: 'jart', username: 'jart',
logoutUrl: 'https://example.com', logoutUrl: 'https://example.com',
isAdmin: true, isAdmin: true,
clientId: 'ignore' clientId: 'ignore',
showPaymentLink: false
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);

View file

@ -54,7 +54,8 @@ function setUp() {
logoutUrl: 'https://example.com', logoutUrl: 'https://example.com',
isAdmin: true, isAdmin: true,
xsrfToken: test.testXsrfToken, xsrfToken: test.testXsrfToken,
clientId: test.testClientId clientId: test.testClientId,
showPaymentLink: false
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
registry.registrar.ConsoleTestUtil.setup(test); registry.registrar.ConsoleTestUtil.setup(test);

View file

@ -48,7 +48,8 @@ function setUp() {
username: 'blah', username: 'blah',
logoutUrl: 'omg', logoutUrl: 'omg',
isAdmin: true, isAdmin: true,
clientId: test.testClientId clientId: test.testClientId,
showPaymentLink: false
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
registry.registrar.ConsoleTestUtil.setup(test); registry.registrar.ConsoleTestUtil.setup(test);

View file

@ -20,12 +20,15 @@ import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.domain.registry.config.RegistryEnvironment; import com.google.domain.registry.config.RegistryEnvironment;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.testing.AppEngineRule;
import com.braintreegateway.BraintreeGateway; import com.braintreegateway.BraintreeGateway;
import com.braintreegateway.ClientTokenGateway; import com.braintreegateway.ClientTokenGateway;
import org.joda.money.CurrencyUnit; import org.joda.money.CurrencyUnit;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
@ -35,6 +38,11 @@ import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class RegistrarPaymentSetupActionTest { public class RegistrarPaymentSetupActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Mock @Mock
private BraintreeGateway braintreeGateway; private BraintreeGateway braintreeGateway;
@ -46,6 +54,10 @@ public class RegistrarPaymentSetupActionTest {
@Before @Before
public void before() throws Exception { public void before() throws Exception {
action.braintreeGateway = braintreeGateway; action.braintreeGateway = braintreeGateway;
action.registrar =
Registrar.loadByClientId("TheRegistrar").asBuilder()
.setBillingMethod(Registrar.BillingMethod.BRAINTREE)
.build();
when(braintreeGateway.clientToken()).thenReturn(clientTokenGateway); when(braintreeGateway.clientToken()).thenReturn(clientTokenGateway);
} }
@ -87,4 +99,17 @@ public class RegistrarPaymentSetupActionTest {
"message", "sandbox", "message", "sandbox",
"results", asList()); "results", asList());
} }
@Test
public void testNotOnCreditCardBillingTerms_showsErrorPage() throws Exception {
action.registrar =
Registrar.loadByClientId("TheRegistrar").asBuilder()
.setBillingMethod(Registrar.BillingMethod.EXTERNAL)
.build();
assertThat(action.handleJsonRequest(ImmutableMap.<String, Object>of()))
.containsExactly(
"status", "ERROR",
"message", "not-using-cc-billing",
"results", asList());
}
} }