Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NFDIV-4314] Use payment service requests created by case-api (Part 1) #3911

2 changes: 2 additions & 0 deletions src/main/app/case/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export const formFieldsToCaseMapping: Partial<Record<keyof Case, keyof CaseData>
applicant1CanIntendToSwitchToSoleFo: 'applicant1CanIntendToSwitchToSoleFo',
applicant2CanIntendToSwitchToSoleFo: 'applicant2CanIntendToSwitchToSoleFo',
isFinalOrderOverdue: 'isFinalOrderOverdue',
citizenPaymentCallbackUrl: 'citizenPaymentCallbackUrl',
};

export function formatCase<OutputFormat>(fields: FieldFormats, data: Partial<Case> | CaseData): OutputFormat {
Expand Down Expand Up @@ -397,6 +398,7 @@ export interface Case {
applicant1CanIntendToSwitchToSoleFo: YesOrNo;
applicant2CanIntendToSwitchToSoleFo: YesOrNo;
isFinalOrderOverdue: YesOrNo;
citizenPaymentCallbackUrl: string;
}

export interface CaseWithId extends Case {
Expand Down
1 change: 1 addition & 0 deletions src/main/app/case/definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,7 @@ export interface CaseData {
evidenceHandled: YesOrNo;
generalLetters: ListValue<GeneralLetterDetails>[];
sentNotifications: SentNotifications;
citizenPaymentCallbackUrl: string;
}

export interface CaseDocuments {
Expand Down
6 changes: 1 addition & 5 deletions src/main/app/controller/BasePaymentCallbackGetController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Logger } from '@hmcts/nodejs-logging';
import autobind from 'autobind-decorator';
import config from 'config';
import { Response } from 'express';

import { CaseData, State } from '../case/definition';
Expand All @@ -18,11 +17,8 @@ export default abstract class BasePaymentCallbackGetController {
if (req.session.userCase.state !== this.awaitingPaymentState()) {
return res.redirect(this.noPaymentRequiredUrl(req));
}
const protocol = req.app.locals.developmentMode ? 'http://' : 'https://';
const port = req.app.locals.developmentMode ? `:${config.get('port')}` : '';
const returnUrl = `${protocol}${res.locals.host}${port}${getPaymentCallbackUrl(req)}`;

const paymentClient = new PaymentClient(req.session, returnUrl);
const paymentClient = new PaymentClient(req.session, getPaymentCallbackUrl(req, res));

const payments = new PaymentModel(req.session.userCase[this.paymentsCaseField()] || []);
if (!payments.hasPayment) {
Expand Down
22 changes: 12 additions & 10 deletions src/main/app/controller/BasePaymentPostController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ export default abstract class BasePaymentPostController {
if (req.session.userCase.state !== this.awaitingPaymentState()) {
req.session.userCase = await req.locals.api.triggerEvent(
req.session.userCase.id,
{},
{ citizenPaymentCallbackUrl: getPaymentCallbackUrl(req, res) },
this.awaitingPaymentEvent()
);
}

const payments = new PaymentModel(req.session.userCase[this.paymentsCaseField()] || []);

if (payments.isPaymentInProgress()) {
return this.saveAndRedirect(req, res, getPaymentCallbackUrl(req));
return this.saveAndRedirect(req, res, getPaymentCallbackPath(req));
}

const paymentClient = this.getPaymentClient(req, res);
const paymentClient = this.getPaymentClient(req, getPaymentCallbackUrl(req, res));
const payment = await this.createServiceRefAndTakePayment(req, paymentClient, payments);

this.saveAndRedirect(req, res, payment.next_url);
Expand All @@ -57,12 +57,8 @@ export default abstract class BasePaymentPostController {
});
}

private getPaymentClient(req: AppRequest, res: Response) {
const protocol = req.app.locals.developmentMode ? 'http://' : 'https://';
const port = req.app.locals.developmentMode ? `:${config.get('port')}` : '';
const returnUrl = `${protocol}${res.locals.host}${port}${getPaymentCallbackUrl(req)}`;

return new PaymentClient(req.session, returnUrl);
private getPaymentClient(req: AppRequest, callbackUrl: string) {
return new PaymentClient(req.session, callbackUrl);
}

private async createServiceRefAndTakePayment(
Expand Down Expand Up @@ -115,7 +111,13 @@ export default abstract class BasePaymentPostController {
protected abstract getResponsiblePartyName(req: AppRequest<AnyObject>): string | undefined;
}

export function getPaymentCallbackUrl(req: AppRequest): string {
export function getPaymentCallbackUrl(req: AppRequest, res: Response): string {
const protocol = req.app.locals.developmentMode ? 'http://' : 'https://';
const port = req.app.locals.developmentMode ? `:${config.get('port')}` : '';
return `${protocol}${res.locals.host}${port}${getPaymentCallbackPath(req)}`;
}

export function getPaymentCallbackPath(req: AppRequest): string {
const isRespondent: boolean =
req.session.isApplicant2 && req.session.userCase.applicationType === ApplicationType.SOLE_APPLICATION;

Expand Down
11 changes: 10 additions & 1 deletion src/main/app/controller/PostController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { Response } from 'express';
import { getNextStepUrl } from '../../steps';
import { SAVE_AND_SIGN_OUT } from '../../steps/urls';
import { Case, CaseWithId } from '../case/case';
import { CITIZEN_APPLICANT2_UPDATE, CITIZEN_SAVE_AND_CLOSE, CITIZEN_UPDATE } from '../case/definition';
import { CITIZEN_APPLICANT2_UPDATE, CITIZEN_SAVE_AND_CLOSE, CITIZEN_SUBMIT, CITIZEN_UPDATE } from '../case/definition';
import { Form, FormFields, FormFieldsFn } from '../form/Form';

import { AppRequest } from './AppRequest';
import { getPaymentCallbackUrl } from './BasePaymentPostController';

@autobind
export class PostController<T extends AnyObject> {
Expand Down Expand Up @@ -75,6 +76,8 @@ export class PostController<T extends AnyObject> {

if (req.session.errors.length === 0) {
try {
this.setPaymentCallbackUrlIfPaymentRequired(req, res, formData);

req.session.userCase = await this.save(req, formData, this.getEventName(req));
} catch (err) {
req.locals.logger.error('Error saving', err);
Expand All @@ -96,6 +99,12 @@ export class PostController<T extends AnyObject> {
return CITIZEN_UPDATE;
}
}

private setPaymentCallbackUrlIfPaymentRequired(req: AppRequest<T>, res: Response, formData: Partial<Case>) {
if (this.getEventName(req) === CITIZEN_SUBMIT) {
formData.citizenPaymentCallbackUrl = getPaymentCallbackUrl(req, res);
}
}
}

export type AnyObject = Record<string, unknown>;
2 changes: 2 additions & 0 deletions src/main/steps/applicant1/check-your-answers/post.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('CheckYourAnswersPostController', () => {
applicationType: ApplicationType.SOLE_APPLICATION,
applicant1IConfirmPrayer: Checkbox.Checked,
applicant1StatementOfTruth: Checkbox.Checked,
citizenPaymentCallbackUrl: 'https://undefined/payment-callback',
};
const checkYourAnswerPostController = new CheckYourAnswersPostController(mockFormContent.fields);

Expand Down Expand Up @@ -112,6 +113,7 @@ describe('CheckYourAnswersPostController', () => {
state: State.Draft,
applicant1IConfirmPrayer: Checkbox.Checked,
applicant1StatementOfTruth: Checkbox.Checked,
citizenPaymentCallbackUrl: 'https://undefined/payment-callback',
};
const checkYourAnswerPostController = new CheckYourAnswersPostController(mockFormContent.fields);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ describe('Applicant1ConfirmYourJointApplicationPostController', () => {
const body = {
applicant1IConfirmPrayer: Checkbox.Checked,
applicant1StatementOfTruth: Checkbox.Checked,
citizenPaymentCallbackUrl: 'https://undefined/payment-callback',
};
const mockFormContent = {
fields: {
Expand All @@ -38,6 +39,7 @@ describe('Applicant1ConfirmYourJointApplicationPostController', () => {
const body = {
applicant1IConfirmPrayer: Checkbox.Checked,
applicant1StatementOfTruth: Checkbox.Checked,
citizenPaymentCallbackUrl: 'https://undefined/payment-callback',
};
const mockFormContent = {
fields: {
Expand Down
6 changes: 5 additions & 1 deletion src/main/steps/applicant1/pay-your-fee/post.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ describe('PaymentPostController', () => {

await paymentController.post(req, res);

expect(req.locals.api.triggerEvent).toHaveBeenCalledWith('1234', {}, CITIZEN_SUBMIT);
expect(req.locals.api.triggerEvent).toHaveBeenCalledWith(
'1234',
{ citizenPaymentCallbackUrl: 'https://undefined/payment-callback' },
CITIZEN_SUBMIT
);
});

it('redirects to the check your answers page if last payment is in progress', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ describe('PaymentPostController', () => {

await paymentController.post(req, res);

expect(req.locals.api.triggerEvent).toHaveBeenCalledWith('1234', {}, RESPONDENT_APPLY_FOR_FINAL_ORDER);
expect(req.locals.api.triggerEvent).toHaveBeenCalledWith(
'1234',
{ citizenPaymentCallbackUrl: 'https://undefined/payment-callback' },
RESPONDENT_APPLY_FOR_FINAL_ORDER
);
});

it('redirects to hub page if last payment is in progress', async () => {
Expand Down