In this walkthrough, we’ll be examining how we built the commerce app’s my account page. Primarily, we’ll look at the different sections and what API calls were necessary to fill them out.
Before we continue, we need to establish the application context check if the user is authenticated. We have covered these common prerequisites elsewhere:
Resolve the tenant and application
Send a request to authenticate the user and determine permissions, whether as anonymous or signed-in
We will also be relying on APIs in the following services’s APIs:
Moreover, we will be using the Auth React and Commerce Customer SDKs for interacting with those services, @broadleaf/auth-react
and @broadleaf/commerce-customer
respectively.
Let’s take a look at the Account Details. The Account Details are centered around the customer’s login information. From here we can update the customer’s name, email and password.
In the commerce starter, when we arrive at the My Account dashboard we find the Full Name and Email are populated already.
This information is from Customer
entity fetched using Read Customer Endpoint.
This method takes a customerId
(from the authenticated user) and an accessToken
that is passed as the authorization header in the request.
Important
|
You will need to get an access token for any API requests for user-specific data such as the Customer DTO or pricing.
See Managing Access Tokens in the Authentication Walkthrough.
|
Method | Path | Params | SDK |
---|---|---|---|
|
|
|
To get the customer’s ID, we can use the AuthClient#getIdentityClaims.
With the Auth React SDK, we just need to use the useAuth
hook to get these as the user
property.
import { useAuth } from '@broadleaf/auth-react';
import { useCustomerClient, useGetCustomerAccessToken } from '@app/common/hooks';
export function useGetCustomer(options) { (1)
const { isAuthenticated, user } = useAuth();
const customerClient = useCustomerClient();
const getCustomerAccessToken = useGetCustomerAccessToken();
return async () => {
if (!isAuthenticated) {
return null;
}
const customerId = user?.customer_id;
const accessToken = await getCustomerAccessToken();
return await customerClient.getCustomer(customerId, {
accessToken
});
};
}
{
"firstName": "Alan",
"middleName": "Mathison",
"lastName": "Turning",
"fullName": "Alan Turning",
"username": "alan_turing",
"email": "alan@turning.net",
"externalId": "hl123gh4",
"phone": {
"countryCode": "+1",
"phoneNumber": "555-5555",
"extension": "666"
},
"additionalPhones": [],
"id": "1234",
"contextState": {}
}
Updating the password is handled by the method changePasswordWithRedirect
which will launch a new page where they will be able to change the password.
Otherwise, fields like email and name can be updated on the customer directly using the Replace Customer endpoint.
Method | Path | Params | SDK |
---|---|---|---|
|
|
|
import { useAuth } from '@broadleaf/auth-react';
import { useCustomerClient, useGetCustomerAccessToken } from '@app/common/hooks';
export function useUpdateCustomer(options, updatedCustomer) {
const { isAuthenticated, user } = useAuth();
const customerClient = useCustomerClient();
const getCustomerAccessToken = useGetCustomerAccessToken();
return async () => {
if (!isAuthenticated) {
return null;
}
const customerId = user?.customer_id;
const accessToken = await getCustomerAccessToken();
return await customerClient.updateCustomer(customerId, updatedCustomer, { (1)
accessToken
});
}
}
Customer update request.
Now we can take a look at the Saved Address Page, which contains the customers addresses and gives the ability to modify the addresses on file.
In order to list the addresses on file, we follow similar steps that we used to populate the Account Details Page. We’ll be using the Read Customer Addresses endpoint.
Method | Path | Params | SDK |
---|---|---|---|
|
|
|
import { useAuth } from '@broadleaf/auth-react';
import { useCustomerClient, useGetCustomerAccessToken } from '@app/common/hooks';
export function useGetAddresses(options) {
const { user } = useAuth();
const customerClient = useCustomerClient();
const getCustomerAccessToken = useGetCustomerAccessToken();
return async () => {
const customerId = user?.customer_id;
const accessToken = await getCustomerAccessToken();
return await customerClient.listCustomerAddresses(customerId, {
accessToken
});
}
}
{
"content": [
{
"name": "Home Address",
"defaultShippingAddress": true,
"defaultBillingAddress": true,
"firstName": "John",
"lastName": "Doe",
"fullName": "John Doe",
"emailAddress": "john@doe.com",
"companyName": "Broadleaf LLC",
"addressLine1": "1234 Main St",
"addressLine2": "Apt 1",
"addressLine3": null,
"city": "Austin",
"county": "Travis",
"stateProvinceRegion": "TX",
"country": "United States",
"postalCode": "78727",
"phonePrimary": {},
"phoneSecondary": {},
"phoneFax": {
"countryCode": "string",
"phoneNumber": "string",
"extension": "string"
},
"isActive": true,
"id": "string",
"customer": {
"id": "string",
"username": "string",
"email": "string"
}
}
],
"pageable": {},
"totalElements": 1,
"totalPages": 1,
"last": true,
"first": true,
"numberOfElements": 1,
"size": 50,
"number": 0,
"sort": {},
"empty": false
}
CRUD (Create, Read, Update, Delete) Operations on an address are done through these SDK methods: addCustomerAddress
,
getCustomerAddress
, updateCustomerAddress
, and deleteCustomerAddress
.
Name | Method | URL | SDK | Open API |
---|---|---|---|---|
Create Address |
|
|
||
Read Address |
|
|
||
Update Address |
|
|
||
Delete Address |
|
|
{
"name": "Home Address",
"defaultShippingAddress": true,
"defaultBillingAddress": true,
"firstName": "John",
"lastName": "Doe",
"fullName": "John Doe",
"emailAddress": "john@doe.com",
"companyName": "Broadleaf LLC",
"addressLine1": "1234 Main St",
"addressLine2": "Apt 1",
"addressLine3": null,
"city": "Austin",
"county": "Travis",
"stateProvinceRegion": "TX",
"country": "United States",
"postalCode": "78727",
"phonePrimary": {},
"phoneSecondary": {},
"phoneFax": {
"countryCode": "string",
"phoneNumber": "string",
"extension": "string"
},
"isActive": true,
"id": "string",
"customer": {
"id": "string",
"username": "string",
"email": "string"
}
}
Now we take a look at the Saved Payments Page, which contains the customers payments accounts and gives the ability to modify only the name and address on the payment account on file.
Saved Payments are managed in the Payment Transaction Service rather than in the Customer Service.
Therefore, we will use the SavedPaymentMethodClient
instead of the CustomerClient
to manage them.
As before, to list all of a customer’s payment, we only need their customer ID and an access token. We’ll be using the Read Customer Payments endpoint.
Method | Path | Params | SDK |
---|---|---|---|
|
|
|
import { useAuth } from '@broadleaf/auth-react';
import { useSavedPaymentMethodClient, useGetCustomerAccessToken } from '@app/common/hooks';
export function useGetSavedPayments(options) {
const { user } = useAuth();
const savedPaymentMethodClient = useSavedPaymentMethodClient();
const getCustomerAccessToken = useGetCustomerAccessToken();
return async () => {
const customerId = user?.customer_id;
const accessToken = await getCustomerAccessToken();
return await savedPaymentMethodClient.listSavedPaymentMethods('CUSTOMER', customerId, {
accessToken
});
}
}
{
"content": [
{
"id": "01J8TRHCTNV6BH46HWA7CEQ88G",
"name": "Test",
"status": "AVAILABLE_TO_USE",
"defaultForOwner": false,
"owningUserType": "BLC_CUSTOMER",
"owningUserId": "01J8N1990JJFM7XJV3C8V2JQYD",
"type": "CREDIT_CARD",
"gatewayType": "PASSTHROUGH",
"billingAddress": {
"fullName": "First Last",
"addressLine1": "100 Street St",
"addressLine2": "",
"city": "City",
"stateProvinceRegion": "AL",
"country": "US",
"postalCode": "10100",
"phonePrimary": {
"countryCode": null,
"phoneNumber": "",
"extension": null
},
"default": false,
"active": true,
"name": "Test",
"visibleToChildren": "NO"
},
"attributes": {},
"displayAttributes": {
"creditCardExpDateYear": "2024",
"creditCardType": "VISA",
"creditCardNumber": "****1111",
"creditCardHolder": "First M Last",
"creditCardExpDateMonth": "09"
},
"version": 0
}
],
"pageable": {},
"totalElements": 1,
"totalPages": 1,
"last": true,
"first": true,
"numberOfElements": 1,
"size": 50,
"number": 0,
"sort": {},
"empty": false
}
CRUD (Create, Read, Update, Delete) Operations on a payment are done through the Saved Payment SDK methods: addCustomerPaymentAccount
,
getCustomerPaymentAccount
, updateCustomerPaymentAccount
, and deleteCustomerPaymentAccount
.
Name | Method | URL | SDK | Open API |
---|---|---|---|---|
Create Payment |
|
|
||
Read Payment |
|
|
Not Available |
|
Update Payment |
|
|
||
Delete Payment |
|
|
{
"id": "01J8TRHCTNV6BH46HWA7CEQ88G",
"name": "Test",
"status": "AVAILABLE_TO_USE",
"defaultForOwner": false,
"owningUserType": "BLC_CUSTOMER",
"owningUserId": "01J8N1990JJFM7XJV3C8V2JQYD",
"type": "CREDIT_CARD",
"gatewayType": "PASSTHROUGH",
"billingAddress": {
"fullName": "First Last",
"addressLine1": "100 Street St",
"addressLine2": "",
"city": "City",
"stateProvinceRegion": "AL",
"country": "US",
"postalCode": "10100",
"default": false,
"active": true,
"name": "Test",
"visibleToChildren": "NO"
},
"attributes": {},
"displayAttributes": {
"creditCardExpDateYear": "2024",
"creditCardType": "VISA",
"creditCardNumber": "****1111",
"creditCardHolder": "First M Last",
"creditCardExpDateMonth": "09"
},
"version": 0
}