diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index f4fe2bcc3..bedab7f9f 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -42,6 +42,7 @@ import static google.registry.util.DomainNameUtils.ACE_PREFIX; import com.google.common.base.CharMatcher; import com.google.common.base.Joiner; import com.google.common.base.Splitter; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; @@ -698,9 +699,6 @@ public class DomainFlowUtils { if (!feeTotal.getCurrencyUnit().equals(feesAndCredits.getCurrency())) { throw new CurrencyUnitMismatchException(); } - if (!feeTotal.equals(feesAndCredits.getTotalCost())) { - throw new FeesMismatchException(feesAndCredits.getTotalCost()); - } // If more than one fees are required, always validate individual fees. ImmutableMap expectedFeeMap = buildFeeMap(feesAndCredits.getFees(), feesAndCredits.getCurrency()); @@ -708,13 +706,20 @@ public class DomainFlowUtils { ImmutableMap providedFeeMap = buildFeeMap(feeCommand.get().getFees(), feeCommand.get().getCurrency()); for (FeeType type : expectedFeeMap.keySet()) { - Money providedCost = providedFeeMap.get(type); + if (!providedFeeMap.containsKey(type)) { + throw new FeesMismatchException(type); + } Money expectedCost = expectedFeeMap.get(type); - if (!providedCost.isEqual(expectedCost)) { + if (!providedFeeMap.get(type).isEqual(expectedCost)) { throw new FeesMismatchException(type, expectedCost); } } } + // Checking if total amount is expected. Extra fees that we are not expecting may be passed in. + // Or if there is only a single fee type expected. + if (!feeTotal.equals(feesAndCredits.getTotalCost())) { + throw new FeesMismatchException(feesAndCredits.getTotalCost()); + } } private static FeeType getOrParseType(Fee fee) throws ParameterValuePolicyErrorException { @@ -1333,6 +1338,13 @@ public class DomainFlowUtils { correctFee)); } + public FeesMismatchException(FeeType type) { + super( + String.format( + "The fees passed in the transform command do not contain expected fee type \"%s\"", + type)); + } + public FeesMismatchException(FeeType type, Money correctFee) { super( String.format( @@ -1346,9 +1358,12 @@ public class DomainFlowUtils { public static class FeeDescriptionParseException extends ParameterValuePolicyErrorException { public FeeDescriptionParseException(String description) { super( - String.format( - "The fee description \"%s\" passed in the transform command cannot be parsed", - description == null ? "" : description)); + (Strings.isNullOrEmpty(description) + ? "No fee description is present in the command, " + : "The fee description \"" + + description + + "\" passed in the command cannot be parsed, ") + + "please perform a domain check to obtain expected fee descriptions."); } } diff --git a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java index bd130c958..cf564ce83 100644 --- a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java @@ -2245,6 +2245,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase() + .put("FEE_VERSION", "0.6") + .put("DESCRIPTION_1", "create") + .put("FEE_1", "26") + .put("DESCRIPTION_2", "Early Access Period") + .put("FEE_2", "100") + .put("DESCRIPTION_3", "renew") + .put("FEE_3", "55") + .build()); + persistContactsAndHosts(); + persistResource( + Registry.get("tld") + .asBuilder() + .setEapFeeSchedule( + ImmutableSortedMap.of( + START_OF_TIME, + Money.of(USD, 0), + clock.nowUtc().minusDays(1), + Money.of(USD, 100), + clock.nowUtc().plusDays(1), + Money.of(USD, 0))) + .build()); + EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow); + assertThat(thrown).hasMessageThat().contains("expected total of USD 126.00"); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + public void testSuccess_eapFee_multipleEAPfees_doNotAddToExpectedValue() throws Exception { + setEppInput( + "domain_create_extra_fees.xml", + new ImmutableMap.Builder() + .put("FEE_VERSION", "0.6") + .put("DESCRIPTION_1", "create") + .put("FEE_1", "26") + .put("DESCRIPTION_2", "Early Access Period") + .put("FEE_2", "55") + .put("DESCRIPTION_3", "Early Access Period") + .put("FEE_3", "55") + .build()); + persistContactsAndHosts(); + persistResource( + Registry.get("tld") + .asBuilder() + .setEapFeeSchedule( + ImmutableSortedMap.of( + START_OF_TIME, + Money.of(USD, 0), + clock.nowUtc().minusDays(1), + Money.of(USD, 100), + clock.nowUtc().plusDays(1), + Money.of(USD, 0))) + .build()); + EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow); + assertThat(thrown).hasMessageThat().contains("expected fee of USD 100.00"); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + public void testSuccess_eapFee_multipleEAPfees_addToExpectedValue() throws Exception { + setEppInput( + "domain_create_extra_fees.xml", + new ImmutableMap.Builder() + .put("FEE_VERSION", "0.6") + .put("DESCRIPTION_1", "create") + .put("FEE_1", "26") + .put("DESCRIPTION_2", "Early Access Period") + .put("FEE_2", "55") + .put("DESCRIPTION_3", "Early Access Period") + .put("FEE_3", "45") + .build()); + persistContactsAndHosts(); + persistResource( + Registry.get("tld") + .asBuilder() + .setEapFeeSchedule( + ImmutableSortedMap.of( + START_OF_TIME, + Money.of(USD, 0), + clock.nowUtc().minusDays(1), + Money.of(USD, 100), + clock.nowUtc().plusDays(1), + Money.of(USD, 0))) + .build()); + doSuccessfulTest( + "tld", "domain_create_response_eap_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6")); + } + @Test public void testSuccess_eapFee_fullDescription_includingArbitraryExpiryTime() throws Exception { setEppInput( diff --git a/javatests/google/registry/flows/domain/testdata/domain_create_extra_fees.xml b/javatests/google/registry/flows/domain/testdata/domain_create_extra_fees.xml new file mode 100644 index 000000000..d66de57d4 --- /dev/null +++ b/javatests/google/registry/flows/domain/testdata/domain_create_extra_fees.xml @@ -0,0 +1,30 @@ + + + + + example.tld + 2 + + ns1.example.net + ns2.example.net + + jd1234 + sh8013 + sh8013 + + 2fooBAR + + + + + + USD + %FEE_1% + %FEE_2% + %FEE_3% + + + ABC-12345 + +