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, getVersion
hasSameIdAs, toResourceIdentifier
String 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 WithKey
CustomerByKeyGet
@Nullable String getCustomerNumber()
SetCustomerNumber
String getEmail()
ChangeEmail
default String getLowercaseEmail()
@Nullable String getFirstName()
ChangeName
,
SetFirstName
@Nullable String getLastName()
ChangeName
,
SetLastName
String 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()
SetCustomerGroup
default CustomerName getName()
@Nullable String getCompanyName()
SetCompanyName
@Nullable String getVatId()
SetVatId
@Nullable LocalDate getDateOfBirth()
SetDateOfBirth
@Nullable AuthenticationMode getAuthenticationMode()
default Reference<Customer> toReference()
Referenceable
toReference
in interface Referenceable<Customer>
toReference
in interface Resource<Customer>
static String resourceTypeId()
CustomFields
.TypeDraft.getResourceTypeIds()
,
Custom
static 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()