Broadleaf Microservices
  • v1.0.0-latest-prod

My Account Walkthrough

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.

My Account Page

Prerequisites

Before we continue, we need to establish the application context check if the user is authenticated. We have covered these common prerequisites elsewhere:

  1. Resolve the tenant and application

  2. 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.

Account Details

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.

Reading Customer Information

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.
Table 1. Get Customer Endpoint
Method Path Params SDK

GET

/api/customer/customers/:customerId

customerId: string (path)

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
      });
    };
}
Customer Response
{
  "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 Customer Information

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.

Table 2. Update Customer Endpoint
Method Path Params SDK

PUT

/api/customer/customers/:customerId

customerId: string (path)

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
      });
    }
}
  1. Customer update request.

Customer Saved Addresses

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.

Saved Addresses

Listing All Saved Addresses

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.

Table 3. List Addresses Endpoint
Method Path Params SDK

GET

/api/customer/customers/:customerId/addresses

customerId: string (path)

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
      });
    }
}
List Addresses Response
{
  "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
}

Managing Saved Addresses

CRUD (Create, Read, Update, Delete) Operations on an address are done through these SDK methods: addCustomerAddress, getCustomerAddress, updateCustomerAddress, and deleteCustomerAddress.

Editing Address
Table 4. Manage Addresses Endpoints
Name Method URL SDK Open API

Create Address

POST

/api/customer/customers/:customerId/addresses

Read Address

GET

/api/customer/customers/:customerId/addresses/:addressId

Update Address

PUT

/api/customer/customers/:customerId/addresses/:addressId

Delete Address

DELETE

/api/customer/customers/:customerId/addresses/:addressId

Example 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"
  }
}

Customer Saved Payments

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

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.

Listing All Payments

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.

Table 5. List Payments Endpoint
Method Path Params SDK

GET

/api/customer/customers/:customerId/addresses

customerId: string (path)

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
      });
    }
}
Example List Payments Response
{
    "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
}

Managing Saved Payments

CRUD (Create, Read, Update, Delete) Operations on a payment are done through the Saved Payment SDK methods: addCustomerPaymentAccount, getCustomerPaymentAccount, updateCustomerPaymentAccount, and deleteCustomerPaymentAccount.

Add Payment
Table 6. Manage Payments Endpoints
Name Method URL SDK Open API

Create Payment

POST

/api/customer/customers/:customerId/payments

Read Payment

GET

/api/customer/customers/:customerId/payments/:paymentId

Not Available

Update Payment

PATCH

/api/customer/customers/:customerId/payments/:paymentId

Delete Payment

DELETE

/api/customer/customers/:customerId/payments/:paymentId

Example Saved 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
}