ATG Commerce provides several form handlers to support a checkout process that uses any number or type of shipping group and payment group. If your site has this type of complex checkout process, then you should use the form handlers described in this section instead of ExpressCheckoutFormHandler
. (For more information on ExpressCheckoutFormHandler
, see Preparing a Simple Order for Checkout.)
The form handlers described in this section manage different subprocesses in the pre-checkout process, which makes it easier for you to extend them when necessary. Separate form handlers exist to support the following tasks:
Creating Shipping Groups
ATG Commerce provides two implementations of the CreateShippingGroupFormHandler
interface to support the form-driven creation of hard good and electronic shipping groups. These form handler classes create the ShippingGroups
and optionally add them to the ShippingGroupMapContainer
. Once the shipping groups are added to the ShippingGroupMapContainer
, the user can then select from among them for use in the current Order
.
The two default implementations of CreateShippingGroupFormHandler
are:
CreateHardgoodShippingGroupFormHandler
This form handler class creates a
HardgoodShippingGroup
and exposes it via agetHardgoodShippingGroup()
method, which makes it possible for users to edit its properties directly via JSP forms. ATG Commerce provides an instance ofatg.commerce.order.purchase.CreateHardgoodShippingGroupFormHandler
; it is located in Nucleus at/atg/commerce/order/purchase/CreateHardgoodShippingGroupFormHandler
.To create the
HardgoodShippingGroup
, thehandleNewHardgoodShippingGroup()
method invokes thecreateHardgoodShippingGroup()
method, which actually creates the shipping group. The form handler’shardgoodShippingGroupType
property determines the type of shipping group to create; by default, this property is set tohardgoodShippingGroup
. The form handler’shardgoodShippingGroupName
property determines the name of the new shipping group, as referenced in theShippingGroupMapContainer
.CreateHardgoodShippingGroupFormHandler
is configured to use/atg/commerce/util/AddressValidator
to validate the shipping address before creating the shipping group. The default configuration is:validateFirstName=true
validateLastName=true
validateAddress1=true
validateCity=true
validateCounty=false
validateState=true
validatePostalCode=true
validateCountry=true
validateEmail=false
validatePhoneNumber=false
validateFaxNumber=false
This validation can be performed every time the shipping group is updated, via the
UpdateHardgoodShippingGroupFormHandler
class.Finally, the form handler’s
addToContainer
property determines whether the new shipping group is added to theShippingGroupMapContainer
and made the default shipping group; by default, this property is set to True. Once theHardgoodShippingGroup
is added to theShippingGroupMapContainer
, the user can use it when checking out theOrder
.After creating the
HardgoodShippingGroup
, you can use theUpdateHardgoodShippingGroupFormHandler
to handle shipping address changes.UpdateHardgoodShippingGroupFormHandler
can update this information in any or all of three places, based on these properties:updateContainer
—Updates theHardgoodShippingGroup
in theShippingGroupMapContainer
.updateProfile
—Updates the shipping address in the profile.updateOrder
—Updates theHardgoodShippingGroup
in the order.
CreateElectronicShippingGroupFormHandler
This form handler class creates an
ElectronicShippingGroup
and exposes it via agetElectronicShippingGroup()
method, which makes it possible for users to edit its properties directly via JSP forms. ATG Commerce provides an instance ofatg.commerce.order.purchase.CreateElectronicShippingGroupFormHandler
; it is located in Nucleus at/atg/commerce/order/purchase/CreateElectronicShippingGroupFormHandler
.To create the
ElectronicShippingGroup
, thehandleNewElectronicShippingGroup()
method invokes thecreateElectronicShippingGroup()
method, which actually creates the shipping group and sets the shipping group’semailAddress
property. The form handler’selectronicShippingGroupType
property determines the type of shipping group to create; by default, this property is set toelectronicShippingGroup
. The form handler’selectronicShippingGroupName
property determines the name of the new shipping group, as referenced in theShippingGroupMapContainer
. Finally, the form handler’saddToContainer
property determines whether the new shipping group is added to theShippingGroupMapContainer
and made the default shipping group; by default, this property is set to True. Once theElectronicShippingGroup
is added to theShippingGroupMapContainer
, the user can use it when checking out theOrder
.After creating the
ElectronichippingGroup
, you can use theUpdateShippingGroupFormHandler
to handle updates to the shipping group.UpdateShippingGroupFormHandler
can update shipping group information in the container and/or the order, based on these properties:updateContainer
—Updates theElectronicShippingGroup
in theShippingGroupMapContainer
.updateOrder
—Updates theElectronicShippingGroup
in the order.
You can also create Profile
-derived ShippingGroups
and add them to the ShippingGroupMapContainer
by using the ShippingGroupDroplet
servlet bean (class atg.commerce.order.purchase.ShippingGroupDroplet
). The input parameters passed into ShippingGroupDroplet
determine what types of ShippingGroups
are created (hard good, electronic, or both) and whether the ShippingGroupMapContainer
is cleared before they are created. For a detailed list of these input parameters, as well as output parameters, open parameters, and a code example, see the Adding Shipping Information to Shopping Carts section of the Implementing Order Retrieval chapter of the ATG Commerce Guide to Setting Up a Store.
To initialize the ShippingGroup
objects, the service method of ShippingGroupDroplet
calls initializeUsersShippingMethods()
, which initializes one or more ShippingGroups
for the current user and adds them to the ShippingGroupMapContainer
. For each entry in ShippingGroupDroplet.shippingGroupTypes
(which is supplied via an input parameter), its corresponding ShippingGroupInitializer
is obtained from the ServiceMap
in ShippingGroupDroplet.shippingGroupInitializers
(keyed by ShippingGroup
type). The initializeShippingGroups()
method of the ShippingGroupInitializer
is then used to initialize the ShippingGroup
and add it to the ShippingGroupMapContainer
.
Note that ATG Commerce provides two implementations of the ShippingGroupInitializer
interface, namely HardgoodShippingGroupInitializer
and ElectronicShippingGroupInitializer
. The former creates HardgoodShippingGroups
based on their existence in the user’s Profile
, and the latter creates ElectronicShippingGroups
based on the existence of an e-mail address in the user’s Profile
.
To use this framework with a new ShippingGroup
type that you create, first, write a new ShippingGroupInitializer
implementation. Its initializeShippingGroups()
method should gather the user’s ShippingGroups
by type and add them to the ShippingGroupMapContainer
referenced by the ShippingGroupFormHandler
. For example, the ElectronicShippingGroupInitializer
queries the Profile
’s email
property and applies the result to a new ElectronicShippingGroup
, which is subsequently added to the ShippingGroupMapContainer
. Second, register a Nucleus component for the new ShippingGroupInitializer
implementation and add it to the ServiceMap
in ShippingGroupDroplet.shippingGroupInitializers
, which is keyed by ShippingGroup
type. Finally, include the new ShippingGroup
type in the ShippingGroupDroplet.shippingGroupTypes
parameter on those site pages where the new ShippingGroup
type is utilized.
Associating Shipping Groups with an Order and Its Items
When the user has supplied the shipping information for an Order
, the ShippingGroupFormHandler
can be used to create and manage the associations between the ShippingGroups
and the items in the Order
. ATG Commerce provides a request-scoped instance of atg.commerce.order.purchase.ShippingGroupFormHandler
, which is located in Nucleus at /atg/commerce/order/purchase/ShippingGroupFormHandler
.
The ShippingGroupFormHandler
works in conjunction with the ShippingGroupDroplet
to manipulate the relationships between CommerceItems
and ShippingGroups
in the order. Handling Instructions and their relationships to CommerceItems
and ShippingGroups
are also manipulated based on the relationship between each CommerceItem
and the ShippingGroups
.
By default, this form handler invokes the validateShippingInfo
pipeline chain to validate ShippingGroup
information. To skip validation, set the validateShippingGroups
property to false
. To learn more about the pipeline chain, see the validateShippingInfo Pipeline Chain section.
It should be noted that ShippingGroupFormHandler
does not reprice the given Order
. Consequently, if you enable customers to make order changes that affect order price through this form handler, you should then reprice the given Order
using the RepriceOrderDroplet
servlet bean before displaying its price to the customer. For more information on RepriceOrderDroplet
, see Repricing Orders section of the ATG Commerce Guide to Setting Up a Store.
The ShippingGroupFormHandler
is composed of the following containers:
atg.commerce.order.purchase.ShippingGroupMapContainer
, which defines aMap
of user-assignedShippingGroup
names toShippingGroups
. This container stores the user’s potentialShippingGroups
for theOrder
.atg.commerce.order.purchase.CommerceItemShippingInfoContainer
, which defines aMap
ofCommerceItems
toCommerceItemShippingInfo
Lists. This container stores the user’sCommerceItemShippingInfo
objects for theCommerceItems
in theOrder
.
Additionally, the ShippingGroupFormHandler
uses the following helper classes:
atg.commerce.order.purchase.CommerceItemShippingInfo
, which represents the association between aCommerceItem
and its shipping information and includes properties such asquantity
,splitQuantity
, andrelationshipType
. These objects store the information needed to createShippingGroupCommerceItemRelationships
for theOrder
.atg.commerce.order.purchase.HandlingInstructionInfo
, which is used to associate handling instruction information with eachCommerceItemShippingInfo
object. HandlingInstructionInfo
is stored in ahandingInstructionInfos
list property of theCommerceItemShippingInfo
object.atg.commerce.order.purchase.ShippingGroupDroplet
, which contains a reference to both theShippingGroupMapContainer
andCommerceItemShippingInfoContainer
. TheShippingGroupDroplet
servlet bean is used to initializeShippingGroup
objects andCommerceItemShippingInfo
objects for use by theShippingGroupFormHandler
. The resulting collections ofShippingGroups
andCommerceItemShippingInfos
are exposed via the output parameters of the servlet bean. For more information on using theShippingGroupDroplet
to initializeShippingGroup
objects, see the previous section, Creating Shipping Groups. For more information on initializingCommerceItemShippingInfo
objects, see below.atg.commerce.order.purchase.CommerceItemShippingInfoTools
, which contains helper methods for creating, modifying, removing and applying theCommerceItemShippingInfo
andShippingGroup
objects in the CommerceItemShippingInfoContainer andShippingGroupMapContainer
containers respectively.CommerceItemShippingGroupTools
includes theincludeGifts
flag, which determines how gift items are handled when split across shipping groups.
With these helper classes and containers, the ShippingGroupFormHandler
adds the necessary ShippingGroups
to the Order
, establishes their relationships to the CommerceItems
, performs validation, and updates the Order
. The following table describes the handle methods used in these processes:
Method | Description of Functionality |
---|---|
| This handle method splits the quantities of The handle method calls |
| This handle method is used to let the user specify a default Setting the default |
| This handle method adds the The handle method calls The Next, if the form handler’s Then, the handle method calls Finally, the handle method calls |
As previously mentioned, the ShippingGroupDroplet
servlet bean is used to initialize CommerceItemShippingInfo
objects and add them to the CommerceItemShippingInfoContainer
, so they can be used by the ShippingGroupFormHandler
. To initialize the CommerceItemShippingInfo
objects, the service method calls initializeCommerceItemShippingInfos()
which, by default, creates and initializes a CommerceItemShippingInfo
for each CommerceItem
in the Order
and adds them to the CommerceItemShippingInfoContainer
. Each new CommerceItemShippingInfo
references the default ShippingGroup
in the ShippingGroupMapContainer
.
The paragraph above describes the default behavior of the ShippingGroupDroplet
. The droplet, however, has several input parameters that control whether and how CommerceItemShippingInfo
objects are created. An additional parameter controls whether the CommerceItemShippingInfoContainer
is cleared before the objects are created. For a detailed list of these input parameters, as well as ShippingGroupDroplet
output parameters, open parameters, and a code example, see the Adding Shipping Information to Shopping Carts section of the Implementing Order Retrieval chapter of the ATG Commerce Guide to Setting Up a Store.
The HandlingInstructionInfo
class makes it possible to split, merge, and apply handling information along with the CommerceItemShippingInfo
objects with which it is associated. When the ShippingGroupDroplet
initializes a container based on the current contents of an Order
, HandlingInstructionInfo
objects are automatically generated for any handling instructions currently in the Order
. These HandlingInstructionInfo
objects are then associated with the appropriate CommerceItemShippingInfo
objects based on the CommerceItem
referenced in the handling instruction.
Gift items in an order are identified by a special handling instruction (GiftHandlingInstruction
), and therefore the ShippingGroupDroplet
and ShippingGroupFormHandler
automatically handle splitting and merging of gift items in the order.
If the CommerceItemShippingInfoTools
includeGifts
property is set to false
(the default), it has the following effects:
CommerceItemShippingInfo
objects don’t include the quantity of the items designated as gifts. For example, if an item is quantity 3, and 1 is a gift, aCommerceItemShippingInfo
will be created for a quantity of 2.GiftHandlingInstructions
are not included in theHandlingInstructionInfos
associated with theCommerceItemShippingInfos
ShippingGroups
that contain only gifts are not added to theShippingGroupMapContainer
The result is that none of the gift-related objects in the Order
are added to the CommerceItemShippingInfoContainer
and ShippingGroupMapContainer
when initializing based on the Order
, and after applying, they remain unchanged in the Order
.
Creating Payment Groups
ATG Commerce provides two implementations of the CreatePaymentGroupFormHandler
interface to support the form-driven creation of credit card and invoice payment groups. These form handler classes create the payment groups and optionally add them to the PaymentGroupMapContainer
. Once the payment groups are added to the PaymentGroupMapContainer
, the user can then select from among them for use in the current Order
.
The default implementations of the CreatePaymentGroupFormHandler
are:
CreateCreditCardFormHandler
This form handler creates a
CreditCard
payment group and exposes it via agetCreditCard()
method, which makes it possible for users to edit its properties directly via JSP forms. ATG Commerce provides an instance ofatg.commerce.order.purchase.CreateCreditCardFormHandler
; it is located in Nucleus at/atg/commerce/order/purchase/CreateCreditCardFormHandler
.To create the
CreditCard
payment group, thehandleNewCreditCard()
method invokes thecreateCreditCard()
method, which actually creates the payment group. The form handler’screditCardType
property determines the type ofCreditCard
payment group to create; by default, this property is set tocreditCard
. The form handler’screditCardName
property determines the name of the new payment group, as referenced in thePaymentGroupMapContainer
. The form handler’saddToContainer
property determines whether the new payment group is added to thePaymentGroupMapContainer
and made the default payment group; by default, this property is set to True. (Once the payment group is added to thePaymentGroupMapContainer
, the user can use it when checking out theOrder
.)CreateCreditCardFormHandler
can optionally validate credit card information using the credit card’s verification number. To validate credit cards, set thevalidateCreditCard
property totrue
. Finally, the form handler’scopyToProfile
property determines whether the payment group is copied to theProfile
; by default, this property is set totrue
.After creating the credit card information, you can use the
UpdateCreditCardFormHandler
to deal with any changes the user makes to their credit card information.UpdateCreditCardFormHandler
can update this information in any or all of three places, based on these properties:updateContainer
—Update the credit card in thePaymentGroupMapContainer.
updateProfile
—Update the credit card in the profile.updateOrder
—Update the credit card in the order.
CreateInvoiceRequestFormHandler
(ATG Business Commerce only) This form handler creates an
InvoiceRequest
payment group and exposes it via agetInvoiceRequest()
method, which makes it possible for users to edit its properties directly via JSP forms. ATG Business Commerce provides an instance ofatg.b2bcommerce.order.purchase.CreateInvoiceRequestFormHandler
; it is located in Nucleus at/atg/commerce/order/purchase/CreateInvoiceRequestFormHandler
.To create the
InvoiceRequest
payment group, thehandleNewInvoiceRequest()
method first invokes thecheckRequiredProperties()
method. By default, this method checks that apoNumber
for the invoice has been specified and throws an exception if one has not been provided. The handle method then callscreateInvoiceRequest()
, which actually creates the payment group.The form handler’s
invoiceRequestType
property determines the type ofInvoiceRequest
payment group to create; by default, this property is set toinvoiceRequest
. The form handler’saddToContainer
property determines whether the new payment group is added to thePaymentGroupMapContainer
and made the default payment group; by default, this property is set to True. (Once the payment group is added to thePaymentGroupMapContainer
, the user can use it when checking out theOrder
.) The form handler’sbillingAddressPropertyName
determines the billing addressProfile
property to copy into theInvoiceRequest
; by default, this property is set todefaultBillingAddress
. Finally, the form handler’sinvoiceRequestProperties
property determines what additionalProfile
properties to dynamically add to theInvoiceRequest
.
You can also create Profile
-derived PaymentGroups
and add them to the PaymentGroupMapContainer
by using the PaymentGroupDroplet
servlet bean (class atg.commerce.order.purchase.PaymentGroupDroplet
). The input parameters passed into PaymentGroupDroplet
determine what types of PaymentGroups
are created (credit card, store credit, gift certificate) and whether the PaymentGroupMapContainer
is cleared before they are created. For a detailed list of these input parameters, as well as its output parameters, open parameters, and a code example, see the Adding Payment Information to Shopping Carts section of the Implementing Shopping Carts chapter of the ATG Commerce Guide to Setting Up a Store.
To initialize the PaymentGroup
objects, the service method of PaymentGroupDroplet
calls initializeUserPaymentMethods()
, which initializes one or more PaymentGroups
for the current user and adds them to the PaymentGroupMapContainer
. For each entry in PaymentGroupDroplet.paymentGroupTypes
(which is supplied via an input parameter), its corresponding PaymentGroupInitializer
is obtained from the ServiceMap
in PaymentGroupDroplet.paymentGroupInitializers
(keyed by PaymentGroup
type). The initializePaymentGroups()
method of the PaymentGroupInitializer
is then used to initialize the PaymentGroup
and add it to the PaymentGroupMapContainer
.
Note that ATG Commerce provides four implementations of the PaymentGroupInitializer
interface. They are:
CreditCardInitializer
GiftCertificateInitializer
StoreCreditInitializer
InvoiceRequestInitializer
(ATG Business Commerce only)
To use this framework with a new PaymentGroup
type that you create, first, write a new PaymentGroupInitializer
implementation. Its initializePaymentGroups()
method should gather the user’s PaymentGroups
by type and add them to the PaymentGroupMapContainer
referenced by the PaymentGroupFormHandler
. For example, the StoreCreditInitializer
queries the Claimable Repository for the user’s StoreCredit
PaymentGroups
, instantiates objects for them, and then adds them to the PaymentGroupMapContainer
. Second, register a Nucleus component for the new PaymentGroupInitializer
implementation and add it to the ServiceMap
in PaymentGroupDroplet.paymentGroupInitializers
, which is keyed by PaymentGroup
type. Finally, include the new PaymentGroup
type in the PaymentGroupDroplet.paymentGroupTypes
parameter on those site pages where the new PaymentGroup
type is utilized.
Associating Payment Groups with an Order and Its Items
When the user has supplied the payment information for an Order
, the PaymentGroupFormHandler
can used to create and manage the associations between the PaymentGroups
and the various parts of the Order
. Any Order
that has been successfully processed by the PaymentGroupFormHandler
is ready for the next phase of the purchase process, which is typically order confirmation. ATG Commerce provides a request-scoped instance of atg.commerce.order.purchase.PaymentGroupFormHandler
, which is located in Nucleus at /atg/commerce/order/purchase/PaymentGroupFormHandler
.
The PaymentGroupFormHandler
adds the PaymentGroups
to the Order
, adds the CommerceItems
, ShippingGroups
, tax, cost amount and cost remaining information to the PaymentGroups
, validates the PaymentGroup
information, and finally saves the Order
in its present state to the Order Repository. If you’d prefer for items to be priced according to a pricelist rather than the default behavior provided by the pricing engine, set the priceListId
property to the appropriate pricelist. When it is finished, the Order
is ready to proceed to the next step in the purchase process, which typically is Order
checkout. (See Submitting an Order for Checkout.)
The PaymentGroupFormHandler
is composed of the following containers:
atg.commerce.order.purchase.PaymentGroupMapContainer
, which defines aMap
of user-assignedPaymentGroup
names toPaymentGroups
. This container stores the user’ potentialPaymentGroups
for theOrder
.atg.commerce.order.purchase.CommerceIdentifierPaymentInfoContainer
, which defines aMap
ofCommerceIdentifiers
toCommerceIdentifierPaymentInfo
Lists. This container stores the user’sCommerceIdentifierPaymentInfo
objects for theOrder
.
Additionally, the PaymentGroupFormHandler
uses the following helper classes:
atg.commerce.order.purchase.CommerceIdentifierPaymentInfo
, which represents the association between aCommerceIdentifier
and its payment information and includes properties that allow the cost of a given quantity or even a single item to be spread across multiple payment groups. These objects store the information need to create paymentRelationships
for theOrder
.atg.commerce.order.purchase.PaymentGroupDroplet
, which implements both thePaymentGroupMapContainer
andCommerceIdentifierPaymentInfoContainer
interfaces. ThePaymentGroupDroplet
servlet bean is used to initializePaymentGroup
objects andCommerceIdentifierPaymentInfo
objects for use by thePaymentGroupFormHandler
. The resulting collections ofPaymentGroups
andCommerceIdentifierPaymentInfo
objects are exposed via the output parameters of the servlet bean. (For more information on usingPaymentGroupDroplet
to initializePaymentGroup
objects, see Creating Payment Groups. For more information on initializingCommerceIdentifierPaymentInfo
objects, see below in this section.)
With these helper classes and containers, the PaymentGroupFormHandler
adds the necessary PaymentGroups
to the Order
, validates them, and updates the Order
. The following table describes the handle methods used in these processes:
Method | Description of Functionality |
---|---|
| This handle method is used when the user wants to split a particular The handle method calls In a form, the user might request to split $50 of an original |
| This handle method is used to let the user specify a default Setting the default |
| This handle method adds the The handle method calls Next, the Next, if the form handler’s Then, Next, the handle method calls Finally, the handle method calls |
As previously mentioned, the PaymentGroupDroplet
servlet bean is used to initialize CommerceIdentifierPaymentInfo
objects and add them to the CommerceIdentifierPaymentInfoContainer
, so they can be used by the PaymentGroupFormHandler
. To initialize the CommerceIdentifierPaymentInfo
objects, the service method of PaymentGroupDroplet
calls initializePaymentInfos()
, which creates and initializes CommerceIdentifierPaymentInfo
objects for the Order
, as well as the Order
’s CommerceItems
, ShippingGroups
, and tax. These objects are then added to the CommerceIdentifierPaymentInfoContainer
.
The input parameters passed into PaymentGroupDroplet
determine whether the CommerceIdentifierPaymentInfo
objects are created and whether the CommerceIdentifierPaymentInfoContainer
is cleared before they are created. For a detailed list of these input parameters, as well as its output parameters, open parameters, and a code example, see the Adding Payment Information to Shopping Carts section of the Implementing Order Retrieval chapter of the ATG Commerce Guide to Setting Up a Store.
Submitting an Order for Checkout
The CommitOrderFormHandler
(class atg.commerce.order.purchase.CommitOrderFormHandler
) submits the user’s current Order
for checkout. ATG Commerce includes an instance of CommitOrderFormHandler
, which is located in Nucleus at /atg/commerce/order/purchase/CommitOrderFormHandler
.
The form handler’s handleCommitOrder()
method ensures that the user is not trying to double-submit the order by checking if the ID of the current Order
is equal to the ID of the user’s last Order
(in ShoppingCart.last
). If the IDs are not equal, then the current Order
can be submitted. The handle method then calls the OrderManager.processOrder()
method, which executes the processOrder
pipeline. (See Checking Out an Order below.)
If no errors occur during the validation or checkout of the Order
, then handleCommitOrder()
sets the submitted Order
as the user’s last Order
in ShoppingCart.last
, and it constructs a new, empty Order
and sets it as the user’s current Order
in ShoppingCart.current
.