The form classes should not contain any controller logic. Move that into the adapter, or even better, into a new controller class. Figure out how to wrap responses like redirect-iframe.
Thinking out loud:
== GatewayPage ==
* Controller for UI.
* Any reason not to pull in the resultswitcher logic?
* handleRequest
** Reads from POST and SESSION
** Performs UI side-effects.
== GatewayAdapter ==
* Should have processing-specific controller logic, the sequence of API calls to make.
* initiatePayment
** Call validation here?
** Returns PaymentResponse object.
== PaymentResponse ==
Encapsulate and decouple desired UI responseadapter initiatePayment response, can be mapped directly to a UI action to present to the donor.
* recoverableError -> Refresh form, optionally displaying validation errors.
* Refresh form* gatewayInteractionRequired -> Redirect to gateway, optionally displaying validation errorswith GET params.
* Redirect to gateway, with GET paramsgatewayIframeRequired -> IFrame would ideally be handled by template engine simply refreshing and iframeUrl toggles conditional display.
* IFrame would ideally be handled by template engine simply refreshing and iframeUrl toggles condi* unrecoverableError -> redirect to failure page, for example after a credit card transactional display was declined.
* Redirect shortcuts for* success -> redirect to Thank You and failureu pages.