Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions src/server/plugins/engine/components/PaymentField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,6 @@ export class PaymentField extends FormComponent {
? (payload[this.name] as unknown as PaymentState)
: undefined

// Use payment state amount if pre-authorized, otherwise use default.
// The page controller overrides this with the resolved conditional amount
// using the full form state (which getViewModel doesn't have access to).
const amount = paymentState?.amount ?? this.options.amount

return {
Expand Down Expand Up @@ -258,7 +255,6 @@ export class PaymentField extends FormComponent {
const reference = state.$$__referenceNumber as string
const resolvedAmount = PaymentField.resolveAmount(options, model, state)

// Zero-amount safety net (page skip should prevent this, but defensive)
if (resolvedAmount === 0) {
return h.redirect(summaryUrl).code(StatusCodes.SEE_OTHER)
}
Expand All @@ -270,9 +266,6 @@ export class PaymentField extends FormComponent {
const payCallbackUrl = `${baseUrl}/payment-callback?uuid=${uuid}`
const paymentPageUrl = args.sourceUrl

// Prepopulate GOV.UK Pay email if emailField is configured.
// The referenced EmailAddressField validates with joi.string().email()
// at input time, so the value in state is already validated.
let prefilledEmail: string | undefined
if (options.emailField) {
const emailValue = state[options.emailField]
Expand Down Expand Up @@ -330,7 +323,6 @@ export class PaymentField extends FormComponent {
_metadata: FormMetadata,
context: FormContext
): Promise<void> {
// Zero-amount bypass — no capture needed
const resolvedAmount = PaymentField.resolveAmount(
this.options,
this.model,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,6 @@ export class QuestionPageController extends PageController {
}
}

// Override payment amount display with resolved conditional amount
// getViewModel() only has the current page's payload, not full form state.
// The full state is available via context.evaluationState.
for (const comp of components) {
if ('amount' in comp.model && 'paymentState' in comp.model) {
const paymentField = this.collection.fields.find(
Expand Down Expand Up @@ -270,9 +267,6 @@ export class QuestionPageController extends PageController {
}
}

// Skip payment pages in the normal page walk.
// Users reach the payment page via "Pay and submit" on CYA,
// not by navigating forward through the form.
if (isPaymentPage(page.pageDef)) {
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ describe('SummaryPageController - Payment (DF-832)', () => {
expect(handleFormSubmitSpy).toHaveBeenCalledTimes(1)
// The GET handler should short-circuit before rendering the view
expect(h.view).not.toHaveBeenCalled()

// GOV.UK Pay callback is a GET so request.payload is undefined.
// Downstream submit code (e.g. outputService) reads
// request.payload.* fields, so the controller must synthesise an
// empty payload before calling handleFormSubmit, otherwise
// request.payload.userConfirmationEmailAddress crashes with
// "Cannot read properties of undefined".
const passedRequest = handleFormSubmitSpy.mock.calls[0][0]
expect(passedRequest.payload).toBeDefined()
expect(passedRequest.payload).toEqual({})
})

it('follows the normal CYA render path when paymentComplete is absent', async () => {
Expand Down
23 changes: 4 additions & 19 deletions src/server/plugins/engine/pageControllers/SummaryPageController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,6 @@ export class SummaryPageController extends QuestionPageController {
declare pageDef: Page
allowSaveAndExit = true

/**
* The controller which is used when Page["controller"] is defined as "./pages/summary.js"
*/

/**
* Finds the PaymentField component across all pages in the model.
* Payment pages are skipped in the normal page walk
*/
private findPaymentField(): PaymentField | undefined {
return this.model.pages
.flatMap((page) => page.collection.fields)
Expand Down Expand Up @@ -183,9 +175,11 @@ export class SummaryPageController extends QuestionPageController {
) => {
const { viewName } = this

// After GOV.UK Pay callback, auto-submit the form instead of
// showing CYA again. The payment is already pre-authorized.
if (request.query.paymentComplete === 'true') {
const requestWithPayload = request as unknown as {
payload: FormRequestPayload['payload']
}
requestWithPayload.payload = {} as FormRequestPayload['payload']
return this.handleFormSubmit(
request as unknown as FormRequestPayload,
context,
Expand All @@ -204,10 +198,6 @@ export class SummaryPageController extends QuestionPageController {
}
}

/**
* Checks if the resolved payment amount has changed since pre-auth
* and invalidates stale payment state if so.
*/
private async reconcilePaymentState(
request: FormRequest,
context: FormContext
Expand Down Expand Up @@ -358,9 +348,6 @@ export class SummaryPageController extends QuestionPageController {
}
}

// Payment page is skipped in the page walk, so proceed() would redirect
// to an earlier page. For PaymentIncomplete, redirect directly to the
// payment page using its href.
if (
error.errorType === PaymentErrorTypes.PaymentIncomplete &&
error.component.page
Expand Down Expand Up @@ -502,8 +489,6 @@ async function finaliseComponents(
context: FormContext,
model: FormModel
) {
// Get fields from relevant pages (normal components)
// plus PaymentField from all pages (payment page is skipped in the page walk)
const allFields = new Set([
...context.relevantPages.flatMap((page) => page.collection.fields),
...model.pages
Expand Down
3 changes: 0 additions & 3 deletions src/server/plugins/engine/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,6 @@ export async function redirectOrMakeHandler(
return proceed(request, h, resumeInRepeaterUrl)
}

// Return handler for relevant pages, payment pages, or preview URL direct access.
// Payment pages are skipped in the normal page walk but must render when the user
// is redirected there from CYA "Pay and submit".
if (
relevantPath.startsWith(page.path) ||
isPaymentPage(page.pageDef) ||
Expand Down
2 changes: 0 additions & 2 deletions src/server/plugins/engine/routes/payment.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ function handlePaymentSuccess(request, h, session, sessionKey, paymentStatus) {
flashComponentState(request, session, paymentStatus)
request.yar.clear(sessionKey)

// Append paymentComplete flag so the summary page auto-submits
// instead of showing CYA again
const separator = session.returnUrl.includes('?') ? '&' : '?'
const returnUrl = `${session.returnUrl}${separator}paymentComplete=true`

Expand Down
1 change: 0 additions & 1 deletion src/server/plugins/payment/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export class PaymentService {
delayed_capture: true
}

// Prepopulate email on GOV.UK Pay if provided
if (email) {
payload.email = email
}
Expand Down
Loading