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 adapter initiatePayment response, can be mapped directly to a UI action to present to the donor.
* recoverableError -> Refresh form, optionally displaying validation errors.
* gatewayInteractionRequired -> Redirect to gateway, with GET params.
* gatewayIframeRequired -> IFrame would ideally be handled by template engine simply refreshing and iframeUrl toggles conditional display.
* unrecoverableError -> redirect to failure page, for example after a credit card transaction was declined.
* success -> redirect to Thank You page
== Notes ==
K4-713 reminds us to not short-circuit the orphan slayer, which relies on an existing mechanism to capture success status, etc.