mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 20:17:51 +02:00
Add EAP fees to domain create flow
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=126411200
This commit is contained in:
parent
d6bd2d56cd
commit
273fc0014d
7 changed files with 118 additions and 18 deletions
|
@ -36,7 +36,6 @@ import static google.registry.model.EppResourceUtils.loadByUniqueId;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.model.registry.Registries.findTldForName;
|
import static google.registry.model.registry.Registries.findTldForName;
|
||||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||||
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
|
|
||||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -66,8 +65,8 @@ import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.registry.Registry.TldState;
|
import google.registry.model.registry.Registry.TldState;
|
||||||
import google.registry.model.smd.SignedMark;
|
import google.registry.model.smd.SignedMark;
|
||||||
import google.registry.model.tmch.ClaimsListShard;
|
import google.registry.model.tmch.ClaimsListShard;
|
||||||
|
import google.registry.pricing.TldSpecificLogicEngine;
|
||||||
import org.joda.money.Money;
|
import google.registry.pricing.TldSpecificLogicEngine.EppCommandOperations;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -89,7 +88,7 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
|
||||||
protected InternetDomainName domainName;
|
protected InternetDomainName domainName;
|
||||||
protected String idnTableName;
|
protected String idnTableName;
|
||||||
protected FeeCreateExtension feeCreate;
|
protected FeeCreateExtension feeCreate;
|
||||||
protected Money createCost;
|
protected EppCommandOperations commandOperations;
|
||||||
protected boolean hasSignedMarks;
|
protected boolean hasSignedMarks;
|
||||||
protected SignedMark signedMark;
|
protected SignedMark signedMark;
|
||||||
protected boolean isAnchorTenantViaReservation;
|
protected boolean isAnchorTenantViaReservation;
|
||||||
|
@ -181,7 +180,8 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
|
||||||
tldState = registry.getTldState(now);
|
tldState = registry.getTldState(now);
|
||||||
checkRegistryStateForTld(tld);
|
checkRegistryStateForTld(tld);
|
||||||
domainLabel = domainName.parts().get(0);
|
domainLabel = domainName.parts().get(0);
|
||||||
createCost = getDomainCreateCost(targetId, now, command.getPeriod().getValue());
|
commandOperations = TldSpecificLogicEngine.getCreatePrice(
|
||||||
|
registry, domainName.toString(), now, command.getPeriod().getValue());
|
||||||
// The TLD should always be the parent of the requested domain name.
|
// The TLD should always be the parent of the requested domain name.
|
||||||
isAnchorTenantViaReservation = matchesAnchorTenantReservation(
|
isAnchorTenantViaReservation = matchesAnchorTenantReservation(
|
||||||
domainLabel, tld, command.getAuthInfo().getPw().getValue());
|
domainLabel, tld, command.getAuthInfo().getPw().getValue());
|
||||||
|
|
|
@ -33,7 +33,6 @@ import google.registry.model.domain.DomainApplication;
|
||||||
import google.registry.model.domain.DomainApplication.Builder;
|
import google.registry.model.domain.DomainApplication.Builder;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.Period;
|
import google.registry.model.domain.Period;
|
||||||
import google.registry.model.domain.fee.Fee;
|
|
||||||
import google.registry.model.domain.fee.FeeCreateExtension;
|
import google.registry.model.domain.fee.FeeCreateExtension;
|
||||||
import google.registry.model.domain.fee.FeeCreateResponseExtension;
|
import google.registry.model.domain.fee.FeeCreateResponseExtension;
|
||||||
import google.registry.model.domain.launch.ApplicationStatus;
|
import google.registry.model.domain.launch.ApplicationStatus;
|
||||||
|
@ -143,7 +142,8 @@ public class DomainApplicationCreateFlow extends BaseDomainCreateFlow<DomainAppl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void verifyDomainCreateIsAllowed() throws EppException {
|
protected void verifyDomainCreateIsAllowed() throws EppException {
|
||||||
validateFeeChallenge(targetId, getTld(), now, feeCreate, createCost);
|
validateFeeChallenge(
|
||||||
|
targetId, getTld(), now, feeCreate, commandOperations.getTotalCost());
|
||||||
if (tldState == TldState.LANDRUSH && !isSuperuser) {
|
if (tldState == TldState.LANDRUSH && !isSuperuser) {
|
||||||
// Prohibit creating a landrush application in LANDRUSH (but not in SUNRUSH) if there is
|
// Prohibit creating a landrush application in LANDRUSH (but not in SUNRUSH) if there is
|
||||||
// exactly one sunrise application for the same name.
|
// exactly one sunrise application for the same name.
|
||||||
|
@ -214,8 +214,8 @@ public class DomainApplicationCreateFlow extends BaseDomainCreateFlow<DomainAppl
|
||||||
.build());
|
.build());
|
||||||
if (feeCreate != null) {
|
if (feeCreate != null) {
|
||||||
responseExtensionsBuilder.add(new FeeCreateResponseExtension.Builder()
|
responseExtensionsBuilder.add(new FeeCreateResponseExtension.Builder()
|
||||||
.setCurrency(createCost.getCurrencyUnit())
|
.setCurrency(commandOperations.getCurrency())
|
||||||
.setFee(ImmutableList.of(Fee.create(createCost.getAmount(), "create")))
|
.setFee(commandOperations.getFees())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
package google.registry.flows.domain;
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
||||||
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
@ -112,7 +111,7 @@ public class DomainCreateFlow extends DomainCreateOrAllocateFlow {
|
||||||
@Override
|
@Override
|
||||||
protected final void verifyDomainCreateIsAllowed() throws EppException {
|
protected final void verifyDomainCreateIsAllowed() throws EppException {
|
||||||
String tld = getTld();
|
String tld = getTld();
|
||||||
validateFeeChallenge(targetId, tld, now, feeCreate, createCost);
|
validateFeeChallenge(targetId, tld, now, feeCreate, commandOperations.getTotalCost());
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
// Prohibit creating a domain if there is an open application for the same name.
|
// Prohibit creating a domain if there is an open application for the same name.
|
||||||
for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) {
|
for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) {
|
||||||
|
@ -151,13 +150,15 @@ public class DomainCreateFlow extends DomainCreateOrAllocateFlow {
|
||||||
@Override
|
@Override
|
||||||
protected final void setDomainCreateOrAllocateProperties(Builder builder) throws EppException {
|
protected final void setDomainCreateOrAllocateProperties(Builder builder) throws EppException {
|
||||||
Registry registry = Registry.get(getTld());
|
Registry registry = Registry.get(getTld());
|
||||||
|
|
||||||
// Bill for the create.
|
// Bill for the create.
|
||||||
BillingEvent.OneTime createEvent = new BillingEvent.OneTime.Builder()
|
BillingEvent.OneTime createEvent = new BillingEvent.OneTime.Builder()
|
||||||
.setReason(Reason.CREATE)
|
.setReason(Reason.CREATE)
|
||||||
.setTargetId(targetId)
|
.setTargetId(targetId)
|
||||||
.setClientId(getClientId())
|
.setClientId(getClientId())
|
||||||
.setPeriodYears(command.getPeriod().getValue())
|
.setPeriodYears(command.getPeriod().getValue())
|
||||||
.setCost(checkNotNull(createCost))
|
// TODO(b/29089413): the EAP fee needs to be a separate billing event.
|
||||||
|
.setCost(commandOperations.getTotalCost())
|
||||||
.setEventTime(now)
|
.setEventTime(now)
|
||||||
.setBillingTime(now.plus(isAnchorTenant()
|
.setBillingTime(now.plus(isAnchorTenant()
|
||||||
? registry.getAnchorTenantAddGracePeriodLength()
|
? registry.getAnchorTenantAddGracePeriodLength()
|
||||||
|
|
|
@ -31,7 +31,6 @@ import google.registry.model.billing.BillingEvent.Reason;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.DomainResource.Builder;
|
import google.registry.model.domain.DomainResource.Builder;
|
||||||
import google.registry.model.domain.Period;
|
import google.registry.model.domain.Period;
|
||||||
import google.registry.model.domain.fee.Fee;
|
|
||||||
import google.registry.model.domain.fee.FeeCreateResponseExtension;
|
import google.registry.model.domain.fee.FeeCreateResponseExtension;
|
||||||
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
import google.registry.model.eppoutput.CreateData.DomainCreateData;
|
||||||
import google.registry.model.eppoutput.EppOutput;
|
import google.registry.model.eppoutput.EppOutput;
|
||||||
|
@ -113,8 +112,8 @@ public abstract class DomainCreateOrAllocateFlow
|
||||||
newResource.getRegistrationExpirationTime()),
|
newResource.getRegistrationExpirationTime()),
|
||||||
(feeCreate == null) ? null : ImmutableList.of(
|
(feeCreate == null) ? null : ImmutableList.of(
|
||||||
new FeeCreateResponseExtension.Builder()
|
new FeeCreateResponseExtension.Builder()
|
||||||
.setCurrency(createCost.getCurrencyUnit())
|
.setCurrency(commandOperations.getCurrency())
|
||||||
.setFee(ImmutableList.of(Fee.create(createCost.getAmount(), "create")))
|
.setFee(commandOperations.getFees())
|
||||||
.build()));
|
.build()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,16 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||||
|
|
||||||
private void assertSuccessfulCreate(String domainTld, boolean isAnchorTenant) throws Exception {
|
private void assertSuccessfulCreate(String domainTld, boolean isAnchorTenant) throws Exception {
|
||||||
DomainResource domain = reloadResourceByUniqueId();
|
DomainResource domain = reloadResourceByUniqueId();
|
||||||
|
|
||||||
|
// Calculate the total cost.
|
||||||
|
Money cost = getPricesForDomainName(getUniqueIdFromCommand(), clock.nowUtc()).isPremium()
|
||||||
|
? Money.of(USD, 200)
|
||||||
|
: Money.of(USD, 26);
|
||||||
|
Money eapFee = Registry.get(domainTld).getEapFeeFor(clock.nowUtc()).getCost();
|
||||||
|
if (!eapFee.isZero()) {
|
||||||
|
cost = Money.total(cost, eapFee);
|
||||||
|
}
|
||||||
|
|
||||||
DateTime billingTime = isAnchorTenant
|
DateTime billingTime = isAnchorTenant
|
||||||
? clock.nowUtc().plus(Registry.get(domainTld).getAnchorTenantAddGracePeriodLength())
|
? clock.nowUtc().plus(Registry.get(domainTld).getAnchorTenantAddGracePeriodLength())
|
||||||
: clock.nowUtc().plus(Registry.get(domainTld).getAddGracePeriodLength());
|
: clock.nowUtc().plus(Registry.get(domainTld).getAddGracePeriodLength());
|
||||||
|
@ -178,9 +188,7 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||||
.setReason(Reason.CREATE)
|
.setReason(Reason.CREATE)
|
||||||
.setTargetId(getUniqueIdFromCommand())
|
.setTargetId(getUniqueIdFromCommand())
|
||||||
.setClientId("TheRegistrar")
|
.setClientId("TheRegistrar")
|
||||||
.setCost(getPricesForDomainName(getUniqueIdFromCommand(), clock.nowUtc()).isPremium()
|
.setCost(cost)
|
||||||
? Money.of(USD, 200)
|
|
||||||
: Money.of(USD, 26))
|
|
||||||
.setPeriodYears(2)
|
.setPeriodYears(2)
|
||||||
.setEventTime(clock.nowUtc())
|
.setEventTime(clock.nowUtc())
|
||||||
.setBillingTime(billingTime)
|
.setBillingTime(billingTime)
|
||||||
|
@ -1280,4 +1288,41 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||||
persistContactsAndHosts();
|
persistContactsAndHosts();
|
||||||
doSuccessfulTest("tld", "domain_create_response.xml");
|
doSuccessfulTest("tld", "domain_create_response.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_eapFeeApplied() throws Exception {
|
||||||
|
setEppInput("domain_create_eap_fee.xml");
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_eapFee_beforeEntireSchedule() throws Exception {
|
||||||
|
persistContactsAndHosts();
|
||||||
|
persistResource(Registry.get("tld").asBuilder()
|
||||||
|
.setEapFeeSchedule(ImmutableSortedMap.of(
|
||||||
|
START_OF_TIME, Money.of(USD, 0),
|
||||||
|
clock.nowUtc().plusDays(1), Money.of(USD, 10),
|
||||||
|
clock.nowUtc().plusDays(2), Money.of(USD, 0)))
|
||||||
|
.build());
|
||||||
|
doSuccessfulTest("tld", "domain_create_response.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_eapFee_afterEntireSchedule() throws Exception {
|
||||||
|
persistContactsAndHosts();
|
||||||
|
persistResource(Registry.get("tld").asBuilder()
|
||||||
|
.setEapFeeSchedule(ImmutableSortedMap.of(
|
||||||
|
START_OF_TIME, Money.of(USD, 0),
|
||||||
|
clock.nowUtc().minusDays(2), Money.of(USD, 100),
|
||||||
|
clock.nowUtc().minusDays(1), Money.of(USD, 0)))
|
||||||
|
.build());
|
||||||
|
doSuccessfulTest("tld", "domain_create_response.xml");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
29
javatests/google/registry/flows/domain/testdata/domain_create_eap_fee.xml
vendored
Normal file
29
javatests/google/registry/flows/domain/testdata/domain_create_eap_fee.xml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||||
|
<command>
|
||||||
|
<create>
|
||||||
|
<domain:create
|
||||||
|
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||||
|
<domain:name>example.tld</domain:name>
|
||||||
|
<domain:period unit="y">2</domain:period>
|
||||||
|
<domain:ns>
|
||||||
|
<domain:hostObj>ns1.example.net</domain:hostObj>
|
||||||
|
<domain:hostObj>ns2.example.net</domain:hostObj>
|
||||||
|
</domain:ns>
|
||||||
|
<domain:registrant>jd1234</domain:registrant>
|
||||||
|
<domain:contact type="admin">sh8013</domain:contact>
|
||||||
|
<domain:contact type="tech">sh8013</domain:contact>
|
||||||
|
<domain:authInfo>
|
||||||
|
<domain:pw>2fooBAR</domain:pw>
|
||||||
|
</domain:authInfo>
|
||||||
|
</domain:create>
|
||||||
|
</create>
|
||||||
|
<extension>
|
||||||
|
<fee:create xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
|
||||||
|
<fee:currency>USD</fee:currency>
|
||||||
|
<fee:fee>26.00</fee:fee>
|
||||||
|
<fee:fee description="Early Access Period">100.00</fee:fee>
|
||||||
|
</fee:create>
|
||||||
|
</extension>
|
||||||
|
<clTRID>ABC-12345</clTRID>
|
||||||
|
</command>
|
||||||
|
</epp>
|
26
javatests/google/registry/flows/domain/testdata/domain_create_response_eap_fee.xml
vendored
Normal file
26
javatests/google/registry/flows/domain/testdata/domain_create_response_eap_fee.xml
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
||||||
|
<response>
|
||||||
|
<result code="1000">
|
||||||
|
<msg>Command completed successfully</msg>
|
||||||
|
</result>
|
||||||
|
<resData>
|
||||||
|
<domain:creData
|
||||||
|
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||||
|
<domain:name>example.tld</domain:name>
|
||||||
|
<domain:crDate>1999-04-03T22:00:00.0Z</domain:crDate>
|
||||||
|
<domain:exDate>2001-04-03T22:00:00.0Z</domain:exDate>
|
||||||
|
</domain:creData>
|
||||||
|
</resData>
|
||||||
|
<extension>
|
||||||
|
<fee:creData xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
|
||||||
|
<fee:currency>USD</fee:currency>
|
||||||
|
<fee:fee description="create">26.00</fee:fee>
|
||||||
|
<fee:fee description="Early Access Period, fee expires: 1999-04-04T22:00:00.000Z">100.00</fee:fee>
|
||||||
|
</fee:creData>
|
||||||
|
</extension>
|
||||||
|
<trID>
|
||||||
|
<clTRID>ABC-12345</clTRID>
|
||||||
|
<svTRID>server-trid</svTRID>
|
||||||
|
</trID>
|
||||||
|
</response>
|
||||||
|
</epp>
|
Loading…
Add table
Reference in a new issue