public interface Customer extends Resource<Customer>, Custom, WithKey
A Customer can have custom fields.
CustomerCreateCommand
does not directly return a customer but an object (CustomerSignInResult) which has a field "customer" for the Customer
and another field "cart" which can optionally have a cart if in the customer creation the cart id has been used.
An example for creating a customer without a cart:
final CustomerGroup customerGroup = CustomerGroupFixtures.b2cCustomerGroup(client()); final CustomerName name = CustomerName.ofFirstAndLastName("John", "Smith"); final String email = randomEmail(CustomerCreateCommandIntegrationTest.class); final String externalId = randomString(); final String password = "secret"; final LocalDate dateOfBirth = LocalDate.of(1985, 5, 7); final String companyName = "ct"; final String vatId = "123456"; final boolean emailVerified = true; final List<Address> addresses = asList(Address.of(DE), Address.of(GB), Address.of(US), Address.of(FR)); final CustomerDraft draft = CustomerDraftDsl.of(name, email, password) .withLocale(GERMAN) .withExternalId(externalId) .withDateOfBirth(dateOfBirth) .withCompanyName(companyName) .withVatId(vatId) .withEmailVerified(emailVerified) .withCustomerGroup(customerGroup) .withAddresses(addresses) .withDefaultBillingAddress(0) .withDefaultShippingAddress(1) .withShippingAddresses(singletonList(2)) .withBillingAddresses(singletonList(3)); final CustomerCreateCommand sphereRequest = CustomerCreateCommand.of(draft) .withExpansionPaths(m -> m.customer().customerGroup()); final CustomerSignInResult result = client().executeBlocking(sphereRequest); assertThat(result.getCart()) .as("no cart id given in creation, so this field is empty") .isNull(); final Customer customer = result.getCustomer(); final Cart cart = result.getCart(); assertThat(customer.getName()).isEqualTo(name); assertThat(customer.getEmail()).isEqualTo(email); assertThat(customer.getPassword()) .as("password is not stored in clear text") .isNotEqualTo(password); assertThat(customer.getExternalId()).contains(externalId); assertThat(customer.getLocale()).isEqualTo(GERMAN); assertThat(cart).isNull(); assertThat(customer.getDateOfBirth()).isEqualTo(dateOfBirth); assertThat(customer.getCompanyName()).contains(companyName); assertThat(customer.getVatId()).contains(vatId); assertThat(customer.isEmailVerified()).isEqualTo(emailVerified); assertThat(customer.getCustomerGroup()).isEqualTo(customerGroup.toReference()); final List<Address> loadedAddresses = customer.getAddresses(); assertThat(loadedAddresses.stream().map(a -> a.withId(null)).collect(toList())).isEqualTo(addresses); assertThat(customer.getDefaultBillingAddress().withId(null)).isEqualTo(addresses.get(0)); assertThat(customer.findDefaultShippingAddress().get().withId(null)).isEqualTo(addresses.get(1)); assertThat(customer.getBillingAddressIds()) .containsExactly(loadedAddresses.get(0).getId(), loadedAddresses.get(3).getId()); assertThat(customer.getBillingAddresses()).extracting(Address::getCountry).containsExactly(DE, FR); assertThat(customer.getShippingAddressIds()) .containsExactly(loadedAddresses.get(1).getId(), loadedAddresses.get(2).getId()); assertThat(customer.getShippingAddresses()).extracting(Address::getCountry).containsExactly(GB, US); assertThat(customer.getCustomerGroup().getObj()) .as("customer group can be expanded") .isNotNull(); String addressId = loadedAddresses.get(0).getId(); final Address addressById = customer.findAddressById(addressId).get(); assertThat(addressById.equals(loadedAddresses.get(0)));See the test code.
Example for creating a customer with a cart:
final Cart cart = client().executeBlocking(CartCreateCommand.of(CartDraft.of(EUR)));//could of course be filled with products final String email = randomEmail(CustomerCreateCommandIntegrationTest.class); final CustomerDraft draft = CustomerDraftDsl.of(CUSTOMER_NAME, email, PASSWORD).withCart(cart); final CustomerSignInResult result = client().executeBlocking(CustomerCreateCommand.of(draft)); assertThat(result.getCart()).isNotNull(); assertThat(result.getCart().getId()).isEqualTo(cart.getId());See the test code.
isEmailVerified(), which is by default false.
If you don't want the shop to use the email authentication from Composable Commerce and verify the customer email via a different method,
then a customer can be created with this field set to true: CustomerDraftBuilderBase.emailVerified(Boolean).
To verify the customers email address with Composable Commerce, first an email token needs to be created with CustomerCreateEmailTokenCommand.
You can specify a certain time frame so that the token gets invalidated at some point.
The response contains a token CustomerToken.getValue() which needs to be sent to the customer.
commercetools Composable Commerce won't send an email to the customer. The shop must implement this feature.
When the customer receives the token, he/she needs to send it to the shop and then the shop to Composable Commerce with CustomerVerifyEmailCommand.
Example
withUpdateableCustomer(client(), customer -> { assertThat(customer.isEmailVerified()).isFalse(); final int ttlMinutes = 15; final Command<CustomerToken> createTokenCommand = CustomerCreateEmailTokenCommand.ofCustomerId(customer.getId(), ttlMinutes); final CustomerToken customerToken = client().executeBlocking(createTokenCommand); final String tokenValue = customerToken.getValue();//this token needs to be sent via email to the customer final Command<Customer> verifyEmailCommand = CustomerVerifyEmailCommand.ofTokenValue(tokenValue); final Customer loadedCustomer = client().executeBlocking(verifyEmailCommand); assertThat(loadedCustomer.isEmailVerified()).isTrue(); Query<CustomerEmailVerifiedMessage> messageQuery = MessageQuery.of() .withPredicates(m -> m.resource().is(customer)) .withSort(m -> m.createdAt().sort().desc()) .withLimit(1L) .forMessageType(CustomerEmailVerifiedMessage.MESSAGE_HINT); assertEventually(() -> { final PagedQueryResult<CustomerEmailVerifiedMessage> queryResult = client().executeBlocking(messageQuery); assertThat(queryResult.head()).isPresent(); }); return loadedCustomer; });See the test code.
CustomerSignInCommand, the content of the anonymous cart should be in the customer's cart.
If the customer did not have a cart associated to him, then the anonymous cart becomes the customer's cart.
If a customer already had a cart associated to him, then the content of the anonymous cart will be copied to the customer's cart.
If a line item in the anonymous cart matches an existing line item in the customer's cart (same product ID and variant ID),
then the maximum quantity of both line items is used as the new quantity.
For convenience the CustomerCreateCommand which contains the customer
and the optional cart.
Example for a successful sign in:
withCustomer(client(), customer -> { final CustomerSignInResult result = client().executeBlocking(CustomerSignInCommand.of(customer.getEmail(), PASSWORD)); assertThat(result.getCustomer()).isEqualTo(customer); });See the test code.
Example for invalid credentials:
withCustomer(client(), customer -> { assertThatThrownBy(() -> client().executeBlocking(CustomerSignInCommand.of("notpresent@null.europe-west1.gcp.commercetools.com", PASSWORD))) .isInstanceOf(ErrorResponseException.class) .matches(e -> ((ErrorResponseException) e).hasErrorCode(CustomerInvalidCredentials.CODE)); });See the test code.
CustomerCreatePasswordTokenCommand by using the customers email.
This token (CustomerToken.getValue() from the result of CustomerCreatePasswordTokenCommand) needs to be sent to the customers email address by the shop. commercetools Composable Commerce won't send the email.
The customer receives the token and can submit it to the shop including the new password. To change then the password in Composable Commerce, use CustomerPasswordResetCommand.
The result of the command is the updated customer, so if the customer needs to sign in after the password change the command CustomerSignInCommand is required.
withUpdateableCustomer(client(), customer -> { final String email = customer.getEmail(); final CustomerToken token = client().executeBlocking(CustomerCreatePasswordTokenCommand.of(email)); final String tokenValue = token.getValue();//this may need to be sent by email to the customer final String newPassword = "newPassword"; final Customer updatedCustomer = client().executeBlocking(CustomerPasswordResetCommand.ofTokenAndPassword(tokenValue, newPassword)); final CustomerSignInResult signInResult = client().executeBlocking(CustomerSignInCommand.of(email, newPassword)); assertThat(signInResult.getCustomer().getId()) .describedAs("customer can sign in with the new password") .isEqualTo(customer.getId()); return updatedCustomer; });See the test code.
CustomerUpdateCommand.
CustomerDeleteCommand.CustomerChangePasswordCommand,
CustomerCreateCommand,
CustomerCreatePasswordTokenCommand,
CustomerDeleteCommand,
CustomerPasswordResetCommand,
CustomerSignInCommand,
CustomerUpdateCommand,
CustomerVerifyEmailCommand,
CustomerByIdGet,
CustomerQuery,
CustomerGroup,
Cart.getCustomerId(),
Order.getCustomerId(),
Payment.getCustomer(),
SetCustomer,
Review.getCustomer(),
SetCustomer| Modifier and Type | Method and Description |
|---|---|
default Optional<Address> |
findAddressById(String addressId) |
default Optional<Address> |
findDefaultBillingAddress() |
default Optional<Address> |
findDefaultShippingAddress() |
default Address |
getAddressById(String addressId)
Find the address in
getAddresses() by the address id |
List<Address> |
getAddresses()
Addresses related to this customer.
|
AuthenticationMode |
getAuthenticationMode() |
default List<Address> |
getBillingAddresses() |
List<String> |
getBillingAddressIds() |
String |
getCompanyName()
Name of the company this customer belongs to.
|
CustomFields |
getCustom() |
Reference<CustomerGroup> |
getCustomerGroup()
The customer group of the customer.
|
String |
getCustomerNumber()
The customer number can be used to create a more human-readable (in contrast to ID) identifier for the customer.
|
LocalDate |
getDateOfBirth()
The date of birth for this customer.
|
default Address |
getDefaultBillingAddress() |
String |
getDefaultBillingAddressId()
ID of an address in
getAddresses() which contains the standard billing address. |
default Address |
getDefaultShippingAddress() |
String |
getDefaultShippingAddressId()
ID of an address in
getAddresses() which contains the standard shipping address. |
String |
getEmail()
Customer’s email address that must be unique across a project.
|
String |
getExternalId()
ID of an external system for this customer.
|
String |
getFirstName()
First name of the customer.
|
String |
getId()
Gets the ID of this customer.
|
String |
getKey()
User-specific unique identifier for a customer.
|
String |
getLastName()
Last name of the customer.
|
Locale |
getLocale() |
default String |
getLowercaseEmail()
The customer's email address in lowercase.
|
String |
getMiddleName()
Middle name of the customer.
|
default CustomerName |
getName() |
String |
getPassword() |
String |
getSalutation()
Customer’s salutation
|
default List<Address> |
getShippingAddresses() |
List<String> |
getShippingAddressIds() |
List<KeyReference<Store>> |
getStores() |
String |
getTitle()
Title of the customer.
|
String |
getVatId()
Value added tax identification number.
|
Boolean |
isEmailVerified() |
static Reference<Customer> |
referenceOfId(String id)
Creates a reference for one item of this class by a known ID.
|
static String |
referenceTypeId()
A type hint for references which resource type is linked in a reference.
|
static String |
resourceTypeId()
An identifier for this resource which supports
CustomFields. |
default Reference<Customer> |
toReference()
Creates a reference to this resource, the reference may not be filled.
|
static com.fasterxml.jackson.core.type.TypeReference<Customer> |
typeReference()
Creates a container which contains the full Java type information to deserialize this class from JSON.
|
getCreatedAt, getLastModifiedAt, getVersionhasSameIdAs, toResourceIdentifierString getId()
getId in interface Identifiable<Customer>getId in interface Resource<Customer>getId in interface ResourceView<Customer,Customer>getId in interface Versioned<Customer>CustomerByIdGet,
CartByCustomerIdGet@Nullable String getKey()
getKey in interface WithKeyCustomerByKeyGet@Nullable String getCustomerNumber()
SetCustomerNumberString getEmail()
ChangeEmaildefault String getLowercaseEmail()
@Nullable String getFirstName()
ChangeName,
SetFirstName@Nullable String getLastName()
ChangeName,
SetLastNameString getPassword()
@Nullable String getMiddleName()
ChangeName,
SetMiddleName@Nullable String getTitle()
ChangeName,
SetTitle@Nonnull List<Address> getAddresses()
AddAddress,
ChangeAddress,
RemoveAddress,
SetDefaultBillingAddress,
SetDefaultShippingAddress@Nullable String getDefaultShippingAddressId()
getAddresses() which contains the standard shipping address.
Access to the default shipping address is also possible with getDefaultShippingAddress().
SetDefaultShippingAddress@Nullable String getDefaultBillingAddressId()
getAddresses() which contains the standard billing address.
Access to the default billing address is also possible with getDefaultBillingAddress().
SetDefaultBillingAddress@Nullable default Address getAddressById(String addressId)
getAddresses() by the address idaddressId - the Id string of the address to findBoolean isEmailVerified()
@Nullable String getExternalId()
SetExternalId@Nullable Reference<CustomerGroup> getCustomerGroup()
SetCustomerGroupdefault CustomerName getName()
@Nullable String getCompanyName()
SetCompanyName@Nullable String getVatId()
SetVatId@Nullable LocalDate getDateOfBirth()
SetDateOfBirth@Nullable AuthenticationMode getAuthenticationMode()
default Reference<Customer> toReference()
ReferenceabletoReference in interface Referenceable<Customer>toReference in interface Resource<Customer>static String resourceTypeId()
CustomFields.TypeDraft.getResourceTypeIds(),
Customstatic String referenceTypeId()
Reference.getTypeId()static com.fasterxml.jackson.core.type.TypeReference<Customer> typeReference()
static Reference<Customer> referenceOfId(String id)
An example for categories but this applies for other resources, too:
final String categoryIdFromFormOrSession = "84ac4271-0fec-49d0-9fee-55586c565c58"; final Reference<Category> categoryReference = Category.referenceOfId(categoryIdFromFormOrSession); assertThat(categoryReference.getId()).isEqualTo(categoryIdFromFormOrSession);See the test code.
If you already have a resource object, then use toReference() instead:
final Category category = getCategory1(); final Reference<Category> categoryReference = category.toReference(); assertThat(category.getId()).isEqualTo(categoryReference.getId());See the test code.
id - the ID of the resource which should be referenced.@Nullable CustomFields getCustom()
@Nullable String getSalutation()
SetSalutation@Nullable List<KeyReference<Store>> getStores()