Broadleaf Microservices

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

Requests to Establish Application Context

Two pre-requisites before we continue are to obtain the application context and have a session with an authenticated user. Here’s a brief overview:

  1. Resolve the tenant and application

  2. Send a request to authenticate the user and determine permissions, whether as anonymous or signed-in

Account Details

Let’s take a look at the Account Details. The Account Details are centered around the customer’s login information. Here we can update the customer’s name, email and password. The actions rely on two services, Authentication and Customer. You will be using the SDK packages that reflect those services, which are the auth package (in this case the react specific project), '@broadleaf/auth-react', and the customer SDK package, '@broadleaf/commerce-customer'.

Getting Customer information

When we arrive on the page we notice that the Full Name and Email pages are populated on arrival. These are populated from the Customer that can be fetched with CustomerClient.getCustomer from the Commerce SDK. This method takes a customerId (from the authenticated user) and an accessToken that is passed as the authorization header in the request.

Tip
You will need to get an access token for any API requests for user-specific data such as the Customer DTO or pricing.

In the case of using a React application, we will use the useAuth react hook. This hook will return an AuthContextShape that contains two important properties: The user object that contains customer_id and the getAccessToken method which will get a valid accessToken that will enable us to securely obtain a customers information. The result is a Customer object that contains the properties such as email and fullName;

import { useAuth } from '@broadleaf/auth-react';
import { CustomerClient } from '@broadleaf/commerce-customer';
import { ClientOptions } from '@broadleaf/commerce-core';

async function getCustomer(options: ClientOptions) {
    const { user, getAccessToken } = useAuth();
    const customerId = user?.customer_id;
    const accessToken = await getCustomerToken();
    const client = new CustomerClient(options);
    const customer = await client.getCustomer(customerId, {
      accessToken
    });
    return customer;
}

Endpoint / SDK method to obtain Customer Information

METHOD

URL

SDK

Read Customer by ID

GET

/customers/<CUSTOMER_ID>

getCustomer(customerId, { accessToken })

Customer Example

{
  "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

The values from the inputs both rely on a updateCustomer in which we create an updated customer object with the the updated properties. Updating the password is handled by the method changePasswordWithRedirect which will launch a new page where they will be able to change the password.

Updating Customer Information Example

import { useAuth } from '@broadleaf/auth-react';
import { CustomerClient } from '@broadleaf/commerce-customer';
import { ClientOptions } from '@broadleaf/commerce-core';

async function getCustomer(options: ClientOptions, updatedCustomer: Customer) {
    const { user, getAccessToken } = useAuth();
    const customerId = user?.customer_id;
    const accessToken = await getCustomerToken();
    const client = new CustomerClient(options);
    await client.updateCustomer(customerId, updatedCustomer {
      accessToken
    });
}

Saved Addresses

Now we take a look at the Saved Address Page, which contains the customers address and give the ability to modify the addresses on file. image::maw-1.png[Saved Addresses]

Getting All Addresses Saved

In order to list the addresses on file, we follow similar steps that we used to populate the Account Details Page, which is obtain the current user’s customer_id and accessToken and use the CustomerClient to call listCustomerAddresses to get a list of Address objects.

import { useAuth } from '@broadleaf/auth-react';
import { CustomerClient } from '@broadleaf/commerce-customer';
import { ClientOptions } from '@broadleaf/commerce-core';

async function getAddresses(options: ClientOptions) {
    const { user, getAccessToken } = useAuth();
    const customerId = user?.customer_id;
    const accessToken = await getCustomerToken();
    const client = new CustomerClient(options);
    const addresses = await client.listCustomerAddresses(customerId, {
      accessToken
    });
    return addresses;
}

Endpoint / SDK method to obtain Addresses Information

METHOD

URL

SDK

List Customer Addresses

GET

/customers/<CUSTOMER_ID>/addresses

listCustomerAddresses(customerId, { accessToken })

List of Addresses Example

This is an example of the response for obtaining a list of Address.

{
  "first": "John",
  "last": "Doe",
  "numberOfElements": 0,
  "pageable": { ... },
  "sort": [ ... ],
  "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"
      },
       ....  }
    }
  ]
}

Creating, Read, and Updating Address information

Now CRUD (Create, Read, Update, Delete) Operations on an address are done through the endpoint /customers/<customerId>/addresses/ which the SDK mirrors through the methods addCustomerAddress, getCustomerAddress, updateCustomerAddress, and deleteCustomerAddress. Note just as we have done for prior actions, we must obtain the customer_id, and accessToken from the Auth.

Editing Address

Address CRUD Operations

METHOD

URL

SDK

Create Address

POST

/customers/<CUSTOMER_ID>/addresses

addCustomerAddress(customerId, address, { accessToken })

Read Address

POST

/customers/<CUSTOMER_ID>/addresses/<ADDRESS_ID>

getCustomerAddress(customerId, customerAddressId, { accessToken })

Update Address

PUT

/customers/<CUSTOMER_ID>/addresses/<ADDRESS_ID>

updateCustomerAddress(customerId, customerAddressId, updatedAddress, { accessToken })

Delete Address

DELETE

/customers/<CUSTOMER_ID>/addresses/<ADDRESS_ID>

deleteCustomerAddress(customerId, customerAddressId, { accessToken })

Addresses Example

This is an example of a Address object.

    {
      "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"
      },
       ....  }
    }

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

Getting All Payments

In order to list the payment accounts on file, we obtain the current user’s customer_id and accessToken and use the CustomerClient to call listCustomerPaymentAccounts to get a list of PaymentAccount objects.

import { useAuth } from '@broadleaf/auth-react';
import { CustomerClient } from '@broadleaf/commerce-customer';
import { ClientOptions } from '@broadleaf/commerce-core';

async function getPaymentAccounts(options: ClientOptions) {
    const { user, getAccessToken } = useAuth();
    const customerId = user?.customer_id;
    const accessToken = await getCustomerToken();
    const client = new CustomerClient(options);
    const accounts = await client.listCustomerPaymentAccounts(customerId, {
      accessToken
    });
    return accounts;
}

Creating, Read, and Updating Payment Account Information

CRUD (Create, Read, Update, Delete) Operations on a payment account are done through the endpoint /customers/<customerId>/payment-accounts/ which the SDK mirrors through the methods addCustomerPaymentAccount, getCustomerPaymentAccount, updateCustomerPaymentAccount, and deleteCustomerPaymentAccount. Note just as we have done for prior actions, we must obtain the customer_id, and accessToken from the Auth.

Add Payment

Address CRUD Operations

METHOD

URL

SDK

Create Payment Account

POST

/customers/<CUSTOMER_ID>/payment-accounts

addCustomerPaymentAccount(customerId, paymentAccount, { accessToken })

Read Payment Account

POST

/customers/<CUSTOMER_ID>/payment-accounts/<PAYMENT_ACCOUNT_ID>

getCustomerPaymentAccount(customerId, paymentAccountId, { accessToken })

Update Payment Account

PUT

/customers/<CUSTOMER_ID>/payment-accounts/<PAYMENT_ACCOUNT_ID>

updateCustomerPaymentAccount(customerId, paymentAccountId, updatedPaymentAccount, { accessToken })

Delete Payment Account

DELETE

/customers/<CUSTOMER_ID>/payment-accounts/<PAYMENT_ACCOUNT_ID>

deleteCustomerPaymentAccount(customerId, paymentAccountId, { accessToken })

Payment Account Example

This is an example of a PaymentAccount object.

{
  "customerRef": {
    "customerId": "12345",
    "username": "john_doe",
    "isRegistered": true
  },
  "displayName": "Chase Card",
  "accountType": "Credit Card",
  "cardType": "VISA",
  "gatewayType": "string",
  "paymentGatewayProperties": { ... },
  "maskedAccountNumber": "1234",
  "nameOnAccount": "John Doe",
  "expirationMonth": 12,
  "expirationYear": 21,
  "fullName": "John Doe",
  "addressLine1": "1234 Main St",
  "addressLine2": "Apt 5",
  "city": "Austin",
  "stateProvinceRegion": "TX",
  "country": "United States",
  "postalCode": "78727",
  "phonePrimary": { ... },
  "lastTransactionDateTime": "2021-07-08T15:55:31.395Z",
  "lastTransactionResultCode": "SUCCESS"
}

Signing Out

In order to sign out, there is just a single method from the Auth SDK, logoutWithRedirect, that will logout the user. image::maw-11.png[Homepage]