@defra/forms-engine-plugin 4.0.43 → 4.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.public/stylesheets/application.min.css +1 -1
- package/.public/stylesheets/application.min.css.map +1 -1
- package/.server/client/stylesheets/_payment-field.scss +8 -0
- package/.server/client/stylesheets/application.scss +2 -0
- package/.server/index.js +3 -1
- package/.server/index.js.map +1 -1
- package/.server/server/constants.d.ts +1 -0
- package/.server/server/constants.js +1 -0
- package/.server/server/constants.js.map +1 -1
- package/.server/server/forms/payment-test.yaml +42 -0
- package/.server/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
- package/.server/server/plugins/engine/components/FormComponent.d.ts +1 -0
- package/.server/server/plugins/engine/components/FormComponent.js +1 -0
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/PaymentField.d.ts +135 -0
- package/.server/server/plugins/engine/components/PaymentField.js +228 -0
- package/.server/server/plugins/engine/components/PaymentField.js.map +1 -0
- package/.server/server/plugins/engine/components/PaymentField.types.d.ts +21 -0
- package/.server/server/plugins/engine/components/PaymentField.types.js +2 -0
- package/.server/server/plugins/engine/components/PaymentField.types.js.map +1 -0
- package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -1
- package/.server/server/plugins/engine/components/UkAddressField.js +3 -1
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
- package/.server/server/plugins/engine/components/helpers/components.js +3 -0
- package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
- package/.server/server/plugins/engine/components/index.d.ts +1 -0
- package/.server/server/plugins/engine/components/index.js +1 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -1
- package/.server/server/plugins/engine/helpers.d.ts +1 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +3 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js +7 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +34 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +22 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +43 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +29 -8
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +2 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +17 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +173 -51
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/errors.d.ts +31 -0
- package/.server/server/plugins/engine/pageControllers/errors.js +59 -2
- package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +27 -0
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js +77 -0
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -0
- package/.server/server/plugins/engine/plugin.js +4 -1
- package/.server/server/plugins/engine/plugin.js.map +1 -1
- package/.server/server/plugins/engine/routes/index.js +8 -4
- package/.server/server/plugins/engine/routes/index.js.map +1 -1
- package/.server/server/plugins/engine/routes/payment-helper.d.ts +14 -0
- package/.server/server/plugins/engine/routes/payment-helper.js +41 -0
- package/.server/server/plugins/engine/routes/payment-helper.js.map +1 -0
- package/.server/server/plugins/engine/routes/payment-helper.test.js +81 -0
- package/.server/server/plugins/engine/routes/payment-helper.test.js.map +1 -0
- package/.server/server/plugins/engine/routes/payment.d.ts +8 -0
- package/.server/server/plugins/engine/routes/payment.js +140 -0
- package/.server/server/plugins/engine/routes/payment.js.map +1 -0
- package/.server/server/plugins/engine/routes/payment.test.js +187 -0
- package/.server/server/plugins/engine/routes/payment.test.js.map +1 -0
- package/.server/server/plugins/engine/services/localFormsService.js +6 -0
- package/.server/server/plugins/engine/services/localFormsService.js.map +1 -1
- package/.server/server/plugins/engine/types/schema.js +7 -0
- package/.server/server/plugins/engine/types/schema.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +19 -1
- package/.server/server/plugins/engine/types.js +4 -0
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/validationHelpers.d.ts +1 -1
- package/.server/server/plugins/engine/validationHelpers.js.map +1 -1
- package/.server/server/plugins/engine/views/components/paymentfield.html +42 -0
- package/.server/server/plugins/engine/views/index.html +9 -1
- package/.server/server/plugins/engine/views/partials/form.html +20 -5
- package/.server/server/plugins/engine/views/summary.html +17 -1
- package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
- package/.server/server/plugins/payment/helper.d.ts +30 -0
- package/.server/server/plugins/payment/helper.js +49 -0
- package/.server/server/plugins/payment/helper.js.map +1 -0
- package/.server/server/plugins/payment/helper.test.js +37 -0
- package/.server/server/plugins/payment/helper.test.js.map +1 -0
- package/.server/server/plugins/payment/service.d.ts +40 -0
- package/.server/server/plugins/payment/service.js +129 -0
- package/.server/server/plugins/payment/service.js.map +1 -0
- package/.server/server/plugins/payment/service.test.js +162 -0
- package/.server/server/plugins/payment/service.test.js.map +1 -0
- package/.server/server/plugins/payment/types.d.ts +172 -0
- package/.server/server/plugins/payment/types.js +78 -0
- package/.server/server/plugins/payment/types.js.map +1 -0
- package/.server/server/types.d.ts +2 -0
- package/.server/server/types.js.map +1 -1
- package/.server/typings/hapi/index.d.js.map +1 -1
- package/README.md +12 -9
- package/package.json +2 -2
- package/src/client/stylesheets/_payment-field.scss +8 -0
- package/src/client/stylesheets/application.scss +2 -0
- package/src/index.ts +5 -1
- package/src/server/constants.js +1 -0
- package/src/server/forms/payment-test.yaml +42 -0
- package/src/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
- package/src/server/plugins/engine/components/FormComponent.ts +1 -0
- package/src/server/plugins/engine/components/PaymentField.test.ts +611 -0
- package/src/server/plugins/engine/components/PaymentField.ts +367 -0
- package/src/server/plugins/engine/components/PaymentField.types.ts +21 -0
- package/src/server/plugins/engine/components/UkAddressField.ts +2 -1
- package/src/server/plugins/engine/components/helpers/components.ts +5 -0
- package/src/server/plugins/engine/components/index.ts +1 -0
- package/src/server/plugins/engine/models/SummaryViewModel.ts +8 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.payment.test.ts +147 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +105 -103
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +61 -2
- package/src/server/plugins/engine/outputFormatters/machine/v2.payment.test.ts +115 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +60 -1
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +32 -6
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +247 -72
- package/src/server/plugins/engine/pageControllers/errors.test.ts +13 -1
- package/src/server/plugins/engine/pageControllers/errors.ts +79 -4
- package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +299 -0
- package/src/server/plugins/engine/pageControllers/helpers/submission.ts +110 -0
- package/src/server/plugins/engine/plugin.ts +11 -6
- package/src/server/plugins/engine/routes/index.ts +17 -16
- package/src/server/plugins/engine/routes/payment-helper.js +39 -0
- package/src/server/plugins/engine/routes/payment-helper.test.js +90 -0
- package/src/server/plugins/engine/routes/payment.js +151 -0
- package/src/server/plugins/engine/routes/payment.test.js +180 -0
- package/src/server/plugins/engine/services/localFormsService.js +7 -0
- package/src/server/plugins/engine/types/schema.ts +9 -0
- package/src/server/plugins/engine/types.ts +24 -1
- package/src/server/plugins/engine/validationHelpers.ts +1 -1
- package/src/server/plugins/engine/views/components/paymentfield.html +42 -0
- package/src/server/plugins/engine/views/index.html +9 -1
- package/src/server/plugins/engine/views/partials/form.html +20 -5
- package/src/server/plugins/engine/views/summary.html +17 -1
- package/src/server/plugins/payment/helper.js +56 -0
- package/src/server/plugins/payment/helper.test.js +52 -0
- package/src/server/plugins/payment/service.js +171 -0
- package/src/server/plugins/payment/service.test.js +205 -0
- package/src/server/plugins/payment/types.js +77 -0
- package/src/server/types.ts +2 -0
- package/src/typings/hapi/index.d.ts +1 -0
package/.server/index.js
CHANGED
|
@@ -17,7 +17,9 @@ const ordnanceSurveyApiKey = config.get('ordnanceSurveyApiKey');
|
|
|
17
17
|
*/
|
|
18
18
|
async function startServer() {
|
|
19
19
|
const server = await createServer({
|
|
20
|
-
ordnanceSurveyApiKey
|
|
20
|
+
ordnanceSurveyApiKey,
|
|
21
|
+
// Enable save and exit for devserver
|
|
22
|
+
saveAndExit: (_request, h) => h.redirect('/')
|
|
21
23
|
});
|
|
22
24
|
await server.start();
|
|
23
25
|
process.send?.('online');
|
package/.server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["getErrorMessage","config","createLogger","createServer","logger","process","on","error","err","info","port","get","ordnanceSurveyApiKey","startServer","server","start","send","catch"],"sources":["../src/index.ts"],"sourcesContent":["import { getErrorMessage } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\nimport { createServer } from '~/src/server/index.js'\n\nconst logger = createLogger()\n\nprocess.on('unhandledRejection', (error) => {\n const err = getErrorMessage(error)\n logger.info('Unhandled rejection')\n logger.error(\n error,\n `[unhandledRejection] Unhandled promise rejection: ${err}`\n )\n throw error\n})\n\nconst port = config.get('port')\nconst ordnanceSurveyApiKey = config.get('ordnanceSurveyApiKey')\n\n/**\n * Main entrypoint to the application.\n */\nasync function startServer() {\n const server = await createServer({
|
|
1
|
+
{"version":3,"file":"index.js","names":["getErrorMessage","config","createLogger","createServer","logger","process","on","error","err","info","port","get","ordnanceSurveyApiKey","startServer","server","saveAndExit","_request","h","redirect","start","send","catch"],"sources":["../src/index.ts"],"sourcesContent":["import { getErrorMessage } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\nimport { createServer } from '~/src/server/index.js'\n\nconst logger = createLogger()\n\nprocess.on('unhandledRejection', (error) => {\n const err = getErrorMessage(error)\n logger.info('Unhandled rejection')\n logger.error(\n error,\n `[unhandledRejection] Unhandled promise rejection: ${err}`\n )\n throw error\n})\n\nconst port = config.get('port')\nconst ordnanceSurveyApiKey = config.get('ordnanceSurveyApiKey')\n\n/**\n * Main entrypoint to the application.\n */\nasync function startServer() {\n const server = await createServer({\n ordnanceSurveyApiKey,\n // Enable save and exit for devserver\n saveAndExit: (_request, h) => h.redirect('/')\n })\n await server.start()\n\n process.send?.('online')\n\n server.logger.info('Server started successfully')\n server.logger.info(`Access your frontend on http://localhost:${port}`)\n}\n\nstartServer().catch((error: unknown) => {\n const err = getErrorMessage(error)\n logger.info('Server failed to start :(')\n logger.error(error, `[serverStartup] Server failed to start: ${err}`)\n throw error\n})\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,oBAAoB;AAEpD,SAASC,MAAM;AACf,SAASC,YAAY;AACrB,SAASC,YAAY;AAErB,MAAMC,MAAM,GAAGF,YAAY,CAAC,CAAC;AAE7BG,OAAO,CAACC,EAAE,CAAC,oBAAoB,EAAGC,KAAK,IAAK;EAC1C,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,qBAAqB,CAAC;EAClCL,MAAM,CAACG,KAAK,CACVA,KAAK,EACL,qDAAqDC,GAAG,EAC1D,CAAC;EACD,MAAMD,KAAK;AACb,CAAC,CAAC;AAEF,MAAMG,IAAI,GAAGT,MAAM,CAACU,GAAG,CAAC,MAAM,CAAC;AAC/B,MAAMC,oBAAoB,GAAGX,MAAM,CAACU,GAAG,CAAC,sBAAsB,CAAC;;AAE/D;AACA;AACA;AACA,eAAeE,WAAWA,CAAA,EAAG;EAC3B,MAAMC,MAAM,GAAG,MAAMX,YAAY,CAAC;IAChCS,oBAAoB;IACpB;IACAG,WAAW,EAAEA,CAACC,QAAQ,EAAEC,CAAC,KAAKA,CAAC,CAACC,QAAQ,CAAC,GAAG;EAC9C,CAAC,CAAC;EACF,MAAMJ,MAAM,CAACK,KAAK,CAAC,CAAC;EAEpBd,OAAO,CAACe,IAAI,GAAG,QAAQ,CAAC;EAExBN,MAAM,CAACV,MAAM,CAACK,IAAI,CAAC,6BAA6B,CAAC;EACjDK,MAAM,CAACV,MAAM,CAACK,IAAI,CAAC,4CAA4CC,IAAI,EAAE,CAAC;AACxE;AAEAG,WAAW,CAAC,CAAC,CAACQ,KAAK,CAAEd,KAAc,IAAK;EACtC,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,2BAA2B,CAAC;EACxCL,MAAM,CAACG,KAAK,CAACA,KAAK,EAAE,2CAA2CC,GAAG,EAAE,CAAC;EACrE,MAAMD,KAAK;AACb,CAAC,CAAC","ignoreList":[]}
|
|
@@ -3,3 +3,4 @@ export const FORM_PREFIX: "";
|
|
|
3
3
|
export const EXTERNAL_STATE_PAYLOAD: "EXTERNAL_STATE_PAYLOAD";
|
|
4
4
|
export const EXTERNAL_STATE_APPENDAGE: "EXTERNAL_STATE_APPENDAGE";
|
|
5
5
|
export const COMPONENT_STATE_ERROR: "COMPONENT_STATE_ERROR";
|
|
6
|
+
export const PAYMENT_EXPIRED_NOTIFICATION: "PAYMENT_EXPIRED_NOTIFICATION";
|
|
@@ -3,4 +3,5 @@ export const FORM_PREFIX = '';
|
|
|
3
3
|
export const EXTERNAL_STATE_PAYLOAD = 'EXTERNAL_STATE_PAYLOAD';
|
|
4
4
|
export const EXTERNAL_STATE_APPENDAGE = 'EXTERNAL_STATE_APPENDAGE';
|
|
5
5
|
export const COMPONENT_STATE_ERROR = 'COMPONENT_STATE_ERROR';
|
|
6
|
+
export const PAYMENT_EXPIRED_NOTIFICATION = 'PAYMENT_EXPIRED_NOTIFICATION';
|
|
6
7
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":["PREVIEW_PATH_PREFIX","FORM_PREFIX","EXTERNAL_STATE_PAYLOAD","EXTERNAL_STATE_APPENDAGE","COMPONENT_STATE_ERROR"],"sources":["../../src/server/constants.js"],"sourcesContent":["export const PREVIEW_PATH_PREFIX = '/preview'\nexport const FORM_PREFIX = ''\nexport const EXTERNAL_STATE_PAYLOAD = 'EXTERNAL_STATE_PAYLOAD'\nexport const EXTERNAL_STATE_APPENDAGE = 'EXTERNAL_STATE_APPENDAGE'\nexport const COMPONENT_STATE_ERROR = 'COMPONENT_STATE_ERROR'\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,UAAU;AAC7C,OAAO,MAAMC,WAAW,GAAG,EAAE;AAC7B,OAAO,MAAMC,sBAAsB,GAAG,wBAAwB;AAC9D,OAAO,MAAMC,wBAAwB,GAAG,0BAA0B;AAClE,OAAO,MAAMC,qBAAqB,GAAG,uBAAuB","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"constants.js","names":["PREVIEW_PATH_PREFIX","FORM_PREFIX","EXTERNAL_STATE_PAYLOAD","EXTERNAL_STATE_APPENDAGE","COMPONENT_STATE_ERROR","PAYMENT_EXPIRED_NOTIFICATION"],"sources":["../../src/server/constants.js"],"sourcesContent":["export const PREVIEW_PATH_PREFIX = '/preview'\nexport const FORM_PREFIX = ''\nexport const EXTERNAL_STATE_PAYLOAD = 'EXTERNAL_STATE_PAYLOAD'\nexport const EXTERNAL_STATE_APPENDAGE = 'EXTERNAL_STATE_APPENDAGE'\nexport const COMPONENT_STATE_ERROR = 'COMPONENT_STATE_ERROR'\nexport const PAYMENT_EXPIRED_NOTIFICATION = 'PAYMENT_EXPIRED_NOTIFICATION'\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,UAAU;AAC7C,OAAO,MAAMC,WAAW,GAAG,EAAE;AAC7B,OAAO,MAAMC,sBAAsB,GAAG,wBAAwB;AAC9D,OAAO,MAAMC,wBAAwB,GAAG,0BAA0B;AAClE,OAAO,MAAMC,qBAAqB,GAAG,uBAAuB;AAC5D,OAAO,MAAMC,4BAA4B,GAAG,8BAA8B","ignoreList":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema: 2
|
|
3
|
+
name: Payment Test Form
|
|
4
|
+
declaration: "<p class=\"govuk-body\">All the answers you have provided are true to the best of your knowledge.</p>"
|
|
5
|
+
pages:
|
|
6
|
+
- title: What is your name?
|
|
7
|
+
path: '/person'
|
|
8
|
+
components:
|
|
9
|
+
- name: personName
|
|
10
|
+
title: What is your name?
|
|
11
|
+
type: TextField
|
|
12
|
+
shortDescription: Your name
|
|
13
|
+
options:
|
|
14
|
+
required: true
|
|
15
|
+
next:
|
|
16
|
+
- path: '/pay-for-your-licence'
|
|
17
|
+
- title: A page title
|
|
18
|
+
path: '/pay-for-your-licence'
|
|
19
|
+
components:
|
|
20
|
+
- name: pageGuidance
|
|
21
|
+
type: Html
|
|
22
|
+
title: Guidance
|
|
23
|
+
content: "<p class=\"govuk-body\">Random guidance</p>"
|
|
24
|
+
options: {}
|
|
25
|
+
- name: licencePayment
|
|
26
|
+
title: Payment details required
|
|
27
|
+
type: PaymentField
|
|
28
|
+
options:
|
|
29
|
+
required: true
|
|
30
|
+
amount: 300
|
|
31
|
+
description: Processing fee for your application.
|
|
32
|
+
next:
|
|
33
|
+
- path: '/summary'
|
|
34
|
+
- title: Summary
|
|
35
|
+
path: '/summary'
|
|
36
|
+
controller: './pages/summary.js'
|
|
37
|
+
components: []
|
|
38
|
+
next: []
|
|
39
|
+
conditions: []
|
|
40
|
+
sections: []
|
|
41
|
+
lists: []
|
|
42
|
+
startPage: '/person'
|
|
@@ -242,6 +242,20 @@ pages:
|
|
|
242
242
|
content: 'Fill in this field'
|
|
243
243
|
options:
|
|
244
244
|
required: false
|
|
245
|
+
next:
|
|
246
|
+
- path: '/pay-for-your-licence'
|
|
247
|
+
- title: Pay for your licence
|
|
248
|
+
path: '/pay-for-your-licence'
|
|
249
|
+
section: section
|
|
250
|
+
components:
|
|
251
|
+
- name: licencePayment
|
|
252
|
+
title: Unicorn breeder licence fee
|
|
253
|
+
type: PaymentField
|
|
254
|
+
hint: You'll be redirected to GOV.UK Pay to complete your payment
|
|
255
|
+
options:
|
|
256
|
+
required: true
|
|
257
|
+
amount: 50
|
|
258
|
+
description: Unicorn breeder annual licence fee
|
|
245
259
|
next:
|
|
246
260
|
- path: '/summary'
|
|
247
261
|
conditions:
|
|
@@ -7,6 +7,7 @@ export declare class FormComponent extends ComponentBase {
|
|
|
7
7
|
hint: FormComponentsDef['hint'];
|
|
8
8
|
label: string;
|
|
9
9
|
isFormComponent: boolean;
|
|
10
|
+
isAppendageStateSingleObject: boolean;
|
|
10
11
|
constructor(def: FormComponentsDef, props: ConstructorParameters<typeof ComponentBase>[1]);
|
|
11
12
|
get keys(): string[];
|
|
12
13
|
getFormDataFromState(state: FormSubmissionState): FormPayload;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormComponent.js","names":["ComponentBase","optionalText","FormComponent","type","hint","label","isFormComponent","constructor","def","props","shortDescription","title","keys","collection","name","fields","map","getFormDataFromState","state","getFormValue","getFormValueFromState","value","isValue","undefined","getStateFromValidForm","payload","getErrors","errors","list","filter","error","path","includes","length","getFirstError","getViewErrors","firstError","getViewModel","options","viewModel","isRequired","required","hideOptional","text","componentErrors","componentError","errorMessage","id","getDisplayStringFromFormValue","toString","getDisplayStringFromState","getContextValueFromFormValue","isState","values","Object","isFormValue","Array","isArray","getContextValueFromState","isFormState","getAllPossibleErrors","baseErrors","advancedSettingsErrors","onSubmit","_request","_metadata","_context","Promise","resolve","isRepeatState","every","isRepeatValue","itemId","isUploadState","isUploadValue","uploadId"],"sources":["../../../../../src/server/plugins/engine/components/FormComponent.ts"],"sourcesContent":["import {\n type FormComponentsDef,\n type FormMetadata,\n type Item\n} from '@defra/forms-model'\n\nimport { ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport {\n type FormContext,\n type FormRequestPayload\n} from '~/src/server/plugins/engine/types/index.js'\nimport {\n type ErrorMessageTemplateList,\n type FileState,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type FormValue,\n type RepeatItemState,\n type RepeatListState,\n type UploadState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class FormComponent extends ComponentBase {\n type: FormComponentsDef['type']\n hint: FormComponentsDef['hint']\n label: string\n\n isFormComponent = true\n\n constructor(\n def: FormComponentsDef,\n props: ConstructorParameters<typeof ComponentBase>[1]\n ) {\n super(def, props)\n\n const { hint, type } = def\n\n this.type = type\n this.hint = hint\n this.label =\n 'shortDescription' in def && def.shortDescription\n ? def.shortDescription\n : def.title\n }\n\n get keys() {\n const { collection, name } = this\n\n if (collection) {\n const { fields } = collection\n return [name, ...fields.map(({ name }) => name)]\n }\n\n return [name]\n }\n\n getFormDataFromState(state: FormSubmissionState): FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormDataFromState(state)\n }\n\n return {\n [name]: this.getFormValue(state[name])\n }\n }\n\n getFormValueFromState(state: FormSubmissionState): FormValue | FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormValueFromState(state)\n }\n\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getStateFromValidForm(payload: FormPayload): FormState {\n const { collection, name } = this\n\n if (collection) {\n return collection.getStateFromValidForm(payload)\n }\n\n return {\n [name]: this.getFormValue(payload[name]) ?? null\n }\n }\n\n getErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined {\n const { name } = this\n\n // Filter component and child errors only\n const list = errors?.filter(\n (error) =>\n error.name === name ||\n error.path.includes(name) ||\n this.keys.includes(error.name)\n )\n\n if (!list?.length) {\n return\n }\n\n return list\n }\n\n getFirstError(\n errors?: FormSubmissionError[]\n ): FormSubmissionError | undefined {\n return this.getErrors(errors)?.[0]\n }\n\n getViewErrors(\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n const firstError = this.getFirstError(errors)\n return firstError && [firstError]\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { hint, name, options = {}, title, viewModel } = this\n\n const isRequired = !('required' in options) || options.required !== false\n const hideOptional = 'optionalText' in options && options.optionalText\n const label = `${title}${!isRequired && !hideOptional ? optionalText : ''}`\n\n if (hint) {\n viewModel.hint = {\n text: hint\n }\n }\n\n // Filter component errors only\n const componentErrors = this.getErrors(errors)\n const componentError = this.getFirstError(componentErrors)\n\n if (componentErrors) {\n viewModel.errors = componentErrors\n }\n\n if (componentError) {\n viewModel.errorMessage = {\n text: componentError.text\n }\n }\n\n return {\n ...viewModel,\n label: {\n text: label\n },\n id: name,\n name,\n value: payload[name]\n }\n }\n\n getDisplayStringFromFormValue(value: FormValue | FormPayload): string {\n // Map selected values to text\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return this.isValue(value) ? value.toString() : ''\n }\n\n getDisplayStringFromState(state: FormSubmissionState): string {\n const value = this.getFormValueFromState(state)\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return this.getDisplayStringFromFormValue(value)\n }\n\n getContextValueFromFormValue(\n value: FormValue | FormPayload\n ): Item['value'] | Item['value'][] | null {\n // Filter object field values\n if (this.isState(value)) {\n const values = Object.values(value).filter(isFormValue)\n return values.length ? values : null\n }\n\n // Filter array field values\n if (this.isValue(value) && Array.isArray(value)) {\n return value.filter(isFormValue)\n }\n\n return this.isValue(value) ? value : null\n }\n\n getContextValueFromState(\n state: FormSubmissionState\n ): Item['value'] | Item['value'][] | null {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n isValue(\n value?: FormStateValue | FormState\n ): value is NonNullable<FormStateValue> {\n return isFormValue(value)\n }\n\n isState(value?: FormStateValue | FormState): value is FormState {\n return isFormState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FormComponent.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [],\n advancedSettingsErrors: []\n }\n }\n\n onSubmit(\n _request: FormRequestPayload,\n _metadata: FormMetadata,\n _context: FormContext\n ): Promise<void> {\n return Promise.resolve()\n }\n}\n\n/**\n * Check for form value\n */\nexport function isFormValue(\n value?: unknown\n): value is string | number | boolean {\n return (\n (typeof value === 'string' && value.length > 0) ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n )\n}\n\n/**\n * Check for form state with nested values\n */\nexport function isFormState(value?: unknown): value is FormState {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n\n // Skip empty objects\n return !!Object.values(value).length\n}\n\n/**\n * Check for repeat list state\n */\nexport function isRepeatState(value?: unknown): value is RepeatListState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isRepeatValue)\n}\n\n/**\n * Check for repeat list value\n */\nexport function isRepeatValue(value?: unknown): value is RepeatItemState {\n return isFormState(value) && typeof value.itemId === 'string'\n}\n\n/**\n * Check for upload state\n */\nexport function isUploadState(value?: unknown): value is UploadState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isUploadValue)\n}\n\n/**\n * Check for upload state value\n */\nexport function isUploadValue(value?: unknown): value is FileState {\n return isFormState(value) && typeof value.uploadId === 'string'\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"FormComponent.js","names":["ComponentBase","optionalText","FormComponent","type","hint","label","isFormComponent","isAppendageStateSingleObject","constructor","def","props","shortDescription","title","keys","collection","name","fields","map","getFormDataFromState","state","getFormValue","getFormValueFromState","value","isValue","undefined","getStateFromValidForm","payload","getErrors","errors","list","filter","error","path","includes","length","getFirstError","getViewErrors","firstError","getViewModel","options","viewModel","isRequired","required","hideOptional","text","componentErrors","componentError","errorMessage","id","getDisplayStringFromFormValue","toString","getDisplayStringFromState","getContextValueFromFormValue","isState","values","Object","isFormValue","Array","isArray","getContextValueFromState","isFormState","getAllPossibleErrors","baseErrors","advancedSettingsErrors","onSubmit","_request","_metadata","_context","Promise","resolve","isRepeatState","every","isRepeatValue","itemId","isUploadState","isUploadValue","uploadId"],"sources":["../../../../../src/server/plugins/engine/components/FormComponent.ts"],"sourcesContent":["import {\n type FormComponentsDef,\n type FormMetadata,\n type Item\n} from '@defra/forms-model'\n\nimport { ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport {\n type FormContext,\n type FormRequestPayload\n} from '~/src/server/plugins/engine/types/index.js'\nimport {\n type ErrorMessageTemplateList,\n type FileState,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type FormValue,\n type RepeatItemState,\n type RepeatListState,\n type UploadState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class FormComponent extends ComponentBase {\n type: FormComponentsDef['type']\n hint: FormComponentsDef['hint']\n label: string\n\n isFormComponent = true\n isAppendageStateSingleObject = false\n\n constructor(\n def: FormComponentsDef,\n props: ConstructorParameters<typeof ComponentBase>[1]\n ) {\n super(def, props)\n\n const { hint, type } = def\n\n this.type = type\n this.hint = hint\n this.label =\n 'shortDescription' in def && def.shortDescription\n ? def.shortDescription\n : def.title\n }\n\n get keys() {\n const { collection, name } = this\n\n if (collection) {\n const { fields } = collection\n return [name, ...fields.map(({ name }) => name)]\n }\n\n return [name]\n }\n\n getFormDataFromState(state: FormSubmissionState): FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormDataFromState(state)\n }\n\n return {\n [name]: this.getFormValue(state[name])\n }\n }\n\n getFormValueFromState(state: FormSubmissionState): FormValue | FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormValueFromState(state)\n }\n\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getStateFromValidForm(payload: FormPayload): FormState {\n const { collection, name } = this\n\n if (collection) {\n return collection.getStateFromValidForm(payload)\n }\n\n return {\n [name]: this.getFormValue(payload[name]) ?? null\n }\n }\n\n getErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined {\n const { name } = this\n\n // Filter component and child errors only\n const list = errors?.filter(\n (error) =>\n error.name === name ||\n error.path.includes(name) ||\n this.keys.includes(error.name)\n )\n\n if (!list?.length) {\n return\n }\n\n return list\n }\n\n getFirstError(\n errors?: FormSubmissionError[]\n ): FormSubmissionError | undefined {\n return this.getErrors(errors)?.[0]\n }\n\n getViewErrors(\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n const firstError = this.getFirstError(errors)\n return firstError && [firstError]\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { hint, name, options = {}, title, viewModel } = this\n\n const isRequired = !('required' in options) || options.required !== false\n const hideOptional = 'optionalText' in options && options.optionalText\n const label = `${title}${!isRequired && !hideOptional ? optionalText : ''}`\n\n if (hint) {\n viewModel.hint = {\n text: hint\n }\n }\n\n // Filter component errors only\n const componentErrors = this.getErrors(errors)\n const componentError = this.getFirstError(componentErrors)\n\n if (componentErrors) {\n viewModel.errors = componentErrors\n }\n\n if (componentError) {\n viewModel.errorMessage = {\n text: componentError.text\n }\n }\n\n return {\n ...viewModel,\n label: {\n text: label\n },\n id: name,\n name,\n value: payload[name]\n }\n }\n\n getDisplayStringFromFormValue(value: FormValue | FormPayload): string {\n // Map selected values to text\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return this.isValue(value) ? value.toString() : ''\n }\n\n getDisplayStringFromState(state: FormSubmissionState): string {\n const value = this.getFormValueFromState(state)\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return this.getDisplayStringFromFormValue(value)\n }\n\n getContextValueFromFormValue(\n value: FormValue | FormPayload\n ): Item['value'] | Item['value'][] | null {\n // Filter object field values\n if (this.isState(value)) {\n const values = Object.values(value).filter(isFormValue)\n return values.length ? values : null\n }\n\n // Filter array field values\n if (this.isValue(value) && Array.isArray(value)) {\n return value.filter(isFormValue)\n }\n\n return this.isValue(value) ? value : null\n }\n\n getContextValueFromState(\n state: FormSubmissionState\n ): Item['value'] | Item['value'][] | null {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n isValue(\n value?: FormStateValue | FormState\n ): value is NonNullable<FormStateValue> {\n return isFormValue(value)\n }\n\n isState(value?: FormStateValue | FormState): value is FormState {\n return isFormState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FormComponent.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [],\n advancedSettingsErrors: []\n }\n }\n\n onSubmit(\n _request: FormRequestPayload,\n _metadata: FormMetadata,\n _context: FormContext\n ): Promise<void> {\n return Promise.resolve()\n }\n}\n\n/**\n * Check for form value\n */\nexport function isFormValue(\n value?: unknown\n): value is string | number | boolean {\n return (\n (typeof value === 'string' && value.length > 0) ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n )\n}\n\n/**\n * Check for form state with nested values\n */\nexport function isFormState(value?: unknown): value is FormState {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n\n // Skip empty objects\n return !!Object.values(value).length\n}\n\n/**\n * Check for repeat list state\n */\nexport function isRepeatState(value?: unknown): value is RepeatListState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isRepeatValue)\n}\n\n/**\n * Check for repeat list value\n */\nexport function isRepeatValue(value?: unknown): value is RepeatItemState {\n return isFormState(value) && typeof value.itemId === 'string'\n}\n\n/**\n * Check for upload state\n */\nexport function isUploadState(value?: unknown): value is UploadState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isUploadValue)\n}\n\n/**\n * Check for upload state value\n */\nexport function isUploadValue(value?: unknown): value is FileState {\n return isFormState(value) && typeof value.uploadId === 'string'\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { type FormMetadata, type PaymentFieldComponent } from '@defra/forms-model';
|
|
2
|
+
import { type ObjectSchema } from 'joi';
|
|
3
|
+
import { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js';
|
|
4
|
+
import { type PaymentState } from '~/src/server/plugins/engine/components/PaymentField.types.js';
|
|
5
|
+
import { type AnyFormRequest, type FormContext, type FormRequestPayload, type FormResponseToolkit } from '~/src/server/plugins/engine/types/index.js';
|
|
6
|
+
import { type ErrorMessageTemplateList, type FormPayload, type FormState, type FormStateValue, type FormSubmissionError, type FormSubmissionState } from '~/src/server/plugins/engine/types.js';
|
|
7
|
+
export declare class PaymentField extends FormComponent {
|
|
8
|
+
options: PaymentFieldComponent['options'];
|
|
9
|
+
formSchema: ObjectSchema;
|
|
10
|
+
stateSchema: ObjectSchema;
|
|
11
|
+
isAppendageStateSingleObject: boolean;
|
|
12
|
+
constructor(def: PaymentFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
|
|
13
|
+
/**
|
|
14
|
+
* Gets the PaymentState from form submission state
|
|
15
|
+
*/
|
|
16
|
+
getPaymentStateFromState(state: FormSubmissionState): PaymentState | undefined;
|
|
17
|
+
getDisplayStringFromState(state: FormSubmissionState): string;
|
|
18
|
+
getViewModel(payload: FormPayload, errors?: FormSubmissionError[]): {
|
|
19
|
+
amount: string;
|
|
20
|
+
description: string;
|
|
21
|
+
paymentState: PaymentState | undefined;
|
|
22
|
+
label: {
|
|
23
|
+
text: string;
|
|
24
|
+
};
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
value: import("~/src/server/plugins/engine/types.js").FormValue;
|
|
28
|
+
type?: string;
|
|
29
|
+
hint?: {
|
|
30
|
+
id?: string;
|
|
31
|
+
text: string;
|
|
32
|
+
};
|
|
33
|
+
prefix?: import("~/src/server/plugins/engine/types/index.js").ComponentText;
|
|
34
|
+
suffix?: import("~/src/server/plugins/engine/types/index.js").ComponentText;
|
|
35
|
+
classes?: string;
|
|
36
|
+
condition?: string;
|
|
37
|
+
errors?: FormSubmissionError[];
|
|
38
|
+
errorMessage?: {
|
|
39
|
+
text: string;
|
|
40
|
+
};
|
|
41
|
+
summaryHtml?: string;
|
|
42
|
+
html?: string;
|
|
43
|
+
attributes: {
|
|
44
|
+
autocomplete?: string;
|
|
45
|
+
maxlength?: number;
|
|
46
|
+
multiple?: string;
|
|
47
|
+
accept?: string;
|
|
48
|
+
inputmode?: string;
|
|
49
|
+
};
|
|
50
|
+
content?: import("~/src/server/plugins/engine/types/index.js").Content | import("~/src/server/plugins/engine/types/index.js").Content[] | string;
|
|
51
|
+
maxlength?: number;
|
|
52
|
+
maxwords?: number;
|
|
53
|
+
rows?: number;
|
|
54
|
+
items?: import("~/src/server/plugins/engine/types/index.js").ListItem[] | import("~/src/server/plugins/engine/types/index.js").DateInputItem[];
|
|
55
|
+
fieldset?: {
|
|
56
|
+
attributes?: string | Record<string, string>;
|
|
57
|
+
legend?: import("~/src/server/plugins/engine/types/index.js").Label;
|
|
58
|
+
};
|
|
59
|
+
formGroup?: {
|
|
60
|
+
classes?: string;
|
|
61
|
+
attributes?: string | Record<string, string>;
|
|
62
|
+
};
|
|
63
|
+
showFieldsetError?: boolean;
|
|
64
|
+
components?: import("~/src/server/plugins/engine/types/index.js").ComponentViewModel[];
|
|
65
|
+
upload?: {
|
|
66
|
+
count: number;
|
|
67
|
+
summaryList: import("~/src/server/plugins/engine/types.js").SummaryList;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Type guard to check if value is PaymentState
|
|
72
|
+
*/
|
|
73
|
+
isPaymentState(value: unknown): value is PaymentState;
|
|
74
|
+
/**
|
|
75
|
+
* Static type guard to check if value is PaymentState
|
|
76
|
+
*/
|
|
77
|
+
static isPaymentState(value: unknown): value is PaymentState;
|
|
78
|
+
/**
|
|
79
|
+
* Override base isState to validate PaymentState
|
|
80
|
+
*/
|
|
81
|
+
isState(value?: FormStateValue | FormState): value is FormState;
|
|
82
|
+
getFormValue(value?: FormStateValue | FormState): NonNullable<FormStateValue> | undefined;
|
|
83
|
+
getContextValueFromState(state: FormSubmissionState): string;
|
|
84
|
+
/**
|
|
85
|
+
* For error preview page that shows all possible errors on a component
|
|
86
|
+
*/
|
|
87
|
+
getAllPossibleErrors(): ErrorMessageTemplateList;
|
|
88
|
+
/**
|
|
89
|
+
* Static version of getAllPossibleErrors that doesn't require a component instance.
|
|
90
|
+
*/
|
|
91
|
+
static getAllPossibleErrors(): ErrorMessageTemplateList;
|
|
92
|
+
/**
|
|
93
|
+
* Dispatcher for external redirect to GOV.UK Pay
|
|
94
|
+
*/
|
|
95
|
+
static dispatcher(request: FormRequestPayload, h: FormResponseToolkit, args: PaymentDispatcherArgs): Promise<unknown>;
|
|
96
|
+
/**
|
|
97
|
+
* Called on form submission to capture the payment
|
|
98
|
+
* @see https://docs.payments.service.gov.uk/delayed_capture/#delay-taking-a-payment
|
|
99
|
+
*/
|
|
100
|
+
onSubmit(request: FormRequestPayload, _metadata: FormMetadata, context: FormContext): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Updates payment state to mark capture as successful
|
|
103
|
+
* This ensures we don't try to re-capture on submission retry
|
|
104
|
+
*/
|
|
105
|
+
private markPaymentCaptured;
|
|
106
|
+
}
|
|
107
|
+
export interface PaymentDispatcherArgs {
|
|
108
|
+
controller: {
|
|
109
|
+
model: {
|
|
110
|
+
formId: string;
|
|
111
|
+
basePath: string;
|
|
112
|
+
name: string;
|
|
113
|
+
};
|
|
114
|
+
getState: (request: AnyFormRequest) => Promise<FormSubmissionState>;
|
|
115
|
+
};
|
|
116
|
+
component: PaymentField;
|
|
117
|
+
sourceUrl: string;
|
|
118
|
+
isLive: boolean;
|
|
119
|
+
isPreview: boolean;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Session data stored when dispatching to GOV.UK Pay
|
|
123
|
+
*/
|
|
124
|
+
export interface PaymentSessionData {
|
|
125
|
+
uuid: string;
|
|
126
|
+
formId: string;
|
|
127
|
+
reference: string;
|
|
128
|
+
amount: number;
|
|
129
|
+
description: string;
|
|
130
|
+
paymentId: string;
|
|
131
|
+
componentName: string;
|
|
132
|
+
returnUrl: string;
|
|
133
|
+
failureUrl: string;
|
|
134
|
+
isLivePayment: boolean;
|
|
135
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { StatusCodes } from 'http-status-codes';
|
|
3
|
+
import joi from 'joi';
|
|
4
|
+
import { FormComponent } from "./FormComponent.js";
|
|
5
|
+
import { getPluginOptions } from "../helpers.js";
|
|
6
|
+
import { PaymentErrorTypes, PaymentPreAuthError, PaymentSubmissionError } from "../pageControllers/errors.js";
|
|
7
|
+
import { createPaymentService } from "../../payment/helper.js";
|
|
8
|
+
export class PaymentField extends FormComponent {
|
|
9
|
+
isAppendageStateSingleObject = true;
|
|
10
|
+
constructor(def, props) {
|
|
11
|
+
super(def, props);
|
|
12
|
+
this.options = def.options;
|
|
13
|
+
const paymentStateSchema = joi.object({
|
|
14
|
+
paymentId: joi.string().required(),
|
|
15
|
+
reference: joi.string().required(),
|
|
16
|
+
amount: joi.number().required(),
|
|
17
|
+
description: joi.string().required(),
|
|
18
|
+
uuid: joi.string().uuid().required(),
|
|
19
|
+
formId: joi.string().required(),
|
|
20
|
+
isLivePayment: joi.boolean().required(),
|
|
21
|
+
preAuth: joi.object({
|
|
22
|
+
status: joi.string().valid('success', 'failed', 'started').required(),
|
|
23
|
+
createdAt: joi.string().isoDate().required()
|
|
24
|
+
}).required()
|
|
25
|
+
}).unknown(true).label(this.label);
|
|
26
|
+
this.formSchema = paymentStateSchema;
|
|
27
|
+
// 'required()' forces the payment page to be invalid until we have valid payment state
|
|
28
|
+
// i.e. the user will automatically be directed back to the payment page
|
|
29
|
+
// if they attempt to access future pages when no payment entered yet
|
|
30
|
+
this.stateSchema = paymentStateSchema.required();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Gets the PaymentState from form submission state
|
|
35
|
+
*/
|
|
36
|
+
getPaymentStateFromState(state) {
|
|
37
|
+
const value = state[this.name];
|
|
38
|
+
return this.isPaymentState(value) ? value : undefined;
|
|
39
|
+
}
|
|
40
|
+
getDisplayStringFromState(state) {
|
|
41
|
+
const value = this.getPaymentStateFromState(state);
|
|
42
|
+
if (!value) {
|
|
43
|
+
return '';
|
|
44
|
+
}
|
|
45
|
+
return `£${value.amount.toFixed(2)} - ${value.description}`;
|
|
46
|
+
}
|
|
47
|
+
getViewModel(payload, errors) {
|
|
48
|
+
const viewModel = super.getViewModel(payload, errors);
|
|
49
|
+
|
|
50
|
+
// Payload is pre-populated from state if a payment has already been made
|
|
51
|
+
const paymentState = this.isPaymentState(payload[this.name]) ? payload[this.name] : undefined;
|
|
52
|
+
|
|
53
|
+
// When user initially visits the payment page, there is no payment state yet so the amount is read form the form definition.
|
|
54
|
+
const amount = paymentState?.amount ?? this.options.amount;
|
|
55
|
+
const formattedAmount = amount.toFixed(2);
|
|
56
|
+
return {
|
|
57
|
+
...viewModel,
|
|
58
|
+
amount: formattedAmount,
|
|
59
|
+
description: this.options.description,
|
|
60
|
+
paymentState
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Type guard to check if value is PaymentState
|
|
66
|
+
*/
|
|
67
|
+
isPaymentState(value) {
|
|
68
|
+
return PaymentField.isPaymentState(value);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Static type guard to check if value is PaymentState
|
|
73
|
+
*/
|
|
74
|
+
static isPaymentState(value) {
|
|
75
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const state = value;
|
|
79
|
+
return typeof state.paymentId === 'string' && typeof state.amount === 'number' && typeof state.description === 'string';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Override base isState to validate PaymentState
|
|
84
|
+
*/
|
|
85
|
+
isState(value) {
|
|
86
|
+
return this.isPaymentState(value);
|
|
87
|
+
}
|
|
88
|
+
getFormValue(value) {
|
|
89
|
+
return this.isPaymentState(value) ? value : undefined;
|
|
90
|
+
}
|
|
91
|
+
getContextValueFromState(state) {
|
|
92
|
+
return this.isPaymentState(state) ? `Reference: ${state.reference}\nAmount: ${state.amount.toFixed(2)}` : '';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* For error preview page that shows all possible errors on a component
|
|
97
|
+
*/
|
|
98
|
+
getAllPossibleErrors() {
|
|
99
|
+
return PaymentField.getAllPossibleErrors();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Static version of getAllPossibleErrors that doesn't require a component instance.
|
|
104
|
+
*/
|
|
105
|
+
static getAllPossibleErrors() {
|
|
106
|
+
return {
|
|
107
|
+
baseErrors: [{
|
|
108
|
+
type: 'paymentRequired',
|
|
109
|
+
template: 'Complete the payment to continue'
|
|
110
|
+
}],
|
|
111
|
+
advancedSettingsErrors: []
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Dispatcher for external redirect to GOV.UK Pay
|
|
117
|
+
*/
|
|
118
|
+
static async dispatcher(request, h, args) {
|
|
119
|
+
const {
|
|
120
|
+
options,
|
|
121
|
+
name: componentName
|
|
122
|
+
} = args.component;
|
|
123
|
+
const {
|
|
124
|
+
model
|
|
125
|
+
} = args.controller;
|
|
126
|
+
const state = await args.controller.getState(request);
|
|
127
|
+
const {
|
|
128
|
+
baseUrl
|
|
129
|
+
} = getPluginOptions(request.server);
|
|
130
|
+
const summaryUrl = `${baseUrl}/${model.basePath}/summary`;
|
|
131
|
+
const existingPaymentState = state[componentName];
|
|
132
|
+
if (PaymentField.isPaymentState(existingPaymentState) && existingPaymentState.preAuth?.status === 'success') {
|
|
133
|
+
return h.redirect(summaryUrl).code(StatusCodes.SEE_OTHER);
|
|
134
|
+
}
|
|
135
|
+
const isLivePayment = args.isLive && !args.isPreview;
|
|
136
|
+
const formId = args.controller.model.formId;
|
|
137
|
+
const paymentService = createPaymentService(isLivePayment, formId);
|
|
138
|
+
const uuid = randomUUID();
|
|
139
|
+
const reference = state.$$__referenceNumber;
|
|
140
|
+
const amount = options.amount;
|
|
141
|
+
const description = options.description;
|
|
142
|
+
const slug = `/${model.basePath}`;
|
|
143
|
+
const payCallbackUrl = `${baseUrl}/payment-callback?uuid=${uuid}`;
|
|
144
|
+
const paymentPageUrl = args.sourceUrl;
|
|
145
|
+
const amountInPence = Math.round(amount * 100);
|
|
146
|
+
const payment = await paymentService.createPayment(amountInPence, description, payCallbackUrl, reference, {
|
|
147
|
+
formId,
|
|
148
|
+
slug
|
|
149
|
+
});
|
|
150
|
+
const sessionData = {
|
|
151
|
+
uuid,
|
|
152
|
+
formId,
|
|
153
|
+
reference,
|
|
154
|
+
amount,
|
|
155
|
+
description,
|
|
156
|
+
paymentId: payment.paymentId,
|
|
157
|
+
componentName,
|
|
158
|
+
returnUrl: summaryUrl,
|
|
159
|
+
failureUrl: paymentPageUrl,
|
|
160
|
+
isLivePayment
|
|
161
|
+
};
|
|
162
|
+
request.yar.set(`payment-${uuid}`, sessionData);
|
|
163
|
+
return h.redirect(payment.paymentUrl).code(StatusCodes.SEE_OTHER);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Called on form submission to capture the payment
|
|
168
|
+
* @see https://docs.payments.service.gov.uk/delayed_capture/#delay-taking-a-payment
|
|
169
|
+
*/
|
|
170
|
+
async onSubmit(request, _metadata, context) {
|
|
171
|
+
const paymentState = this.getPaymentStateFromState(context.state);
|
|
172
|
+
if (!paymentState) {
|
|
173
|
+
throw new PaymentPreAuthError(this, 'Complete the payment to continue', true, PaymentErrorTypes.PaymentIncomplete);
|
|
174
|
+
}
|
|
175
|
+
if (paymentState.capture?.status === 'success') {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const {
|
|
179
|
+
paymentId,
|
|
180
|
+
isLivePayment,
|
|
181
|
+
formId
|
|
182
|
+
} = paymentState;
|
|
183
|
+
const paymentService = createPaymentService(isLivePayment, formId);
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @see https://docs.payments.service.gov.uk/api_reference/#payment-status-lifecycle
|
|
187
|
+
*/
|
|
188
|
+
const status = await paymentService.getPaymentStatus(paymentId);
|
|
189
|
+
PaymentSubmissionError.checkPaymentAmount(status.amount, this.options.amount, this);
|
|
190
|
+
if (status.state.status === 'success') {
|
|
191
|
+
await this.markPaymentCaptured(request, paymentState);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (status.state.status !== 'capturable') {
|
|
195
|
+
throw new PaymentPreAuthError(this, 'Your payment authorisation has expired. Please add your payment details again.', true, PaymentErrorTypes.PaymentExpired);
|
|
196
|
+
}
|
|
197
|
+
const captured = await paymentService.capturePayment(paymentId);
|
|
198
|
+
if (!captured) {
|
|
199
|
+
throw new PaymentPreAuthError(this, 'There was a problem and your form was not submitted. Try submitting the form again.', false);
|
|
200
|
+
}
|
|
201
|
+
await this.markPaymentCaptured(request, paymentState);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Updates payment state to mark capture as successful
|
|
206
|
+
* This ensures we don't try to re-capture on submission retry
|
|
207
|
+
*/
|
|
208
|
+
async markPaymentCaptured(request, paymentState) {
|
|
209
|
+
const updatedState = {
|
|
210
|
+
...paymentState,
|
|
211
|
+
capture: {
|
|
212
|
+
status: 'success',
|
|
213
|
+
createdAt: new Date().toISOString()
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
if (this.page) {
|
|
217
|
+
const currentState = await this.page.getState(request);
|
|
218
|
+
await this.page.mergeState(request, currentState, {
|
|
219
|
+
[this.name]: updatedState
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Session data stored when dispatching to GOV.UK Pay
|
|
227
|
+
*/
|
|
228
|
+
//# sourceMappingURL=PaymentField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PaymentField.js","names":["randomUUID","StatusCodes","joi","FormComponent","getPluginOptions","PaymentErrorTypes","PaymentPreAuthError","PaymentSubmissionError","createPaymentService","PaymentField","isAppendageStateSingleObject","constructor","def","props","options","paymentStateSchema","object","paymentId","string","required","reference","amount","number","description","uuid","formId","isLivePayment","boolean","preAuth","status","valid","createdAt","isoDate","unknown","label","formSchema","stateSchema","getPaymentStateFromState","state","value","name","isPaymentState","undefined","getDisplayStringFromState","toFixed","getViewModel","payload","errors","viewModel","paymentState","formattedAmount","Array","isArray","isState","getFormValue","getContextValueFromState","getAllPossibleErrors","baseErrors","type","template","advancedSettingsErrors","dispatcher","request","h","args","componentName","component","model","controller","getState","baseUrl","server","summaryUrl","basePath","existingPaymentState","redirect","code","SEE_OTHER","isLive","isPreview","paymentService","$$__referenceNumber","slug","payCallbackUrl","paymentPageUrl","sourceUrl","amountInPence","Math","round","payment","createPayment","sessionData","returnUrl","failureUrl","yar","set","paymentUrl","onSubmit","_metadata","context","PaymentIncomplete","capture","getPaymentStatus","checkPaymentAmount","markPaymentCaptured","PaymentExpired","captured","capturePayment","updatedState","Date","toISOString","page","currentState","mergeState"],"sources":["../../../../../src/server/plugins/engine/components/PaymentField.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\n\nimport {\n type FormMetadata,\n type PaymentFieldComponent\n} from '@defra/forms-model'\nimport { StatusCodes } from 'http-status-codes'\nimport joi, { type ObjectSchema } from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type PaymentState } from '~/src/server/plugins/engine/components/PaymentField.types.js'\nimport { getPluginOptions } from '~/src/server/plugins/engine/helpers.js'\nimport {\n PaymentErrorTypes,\n PaymentPreAuthError,\n PaymentSubmissionError\n} from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport {\n type AnyFormRequest,\n type FormContext,\n type FormRequestPayload,\n type FormResponseToolkit\n} from '~/src/server/plugins/engine/types/index.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { createPaymentService } from '~/src/server/plugins/payment/helper.js'\n\nexport class PaymentField extends FormComponent {\n declare options: PaymentFieldComponent['options']\n declare formSchema: ObjectSchema\n declare stateSchema: ObjectSchema\n isAppendageStateSingleObject = true\n\n constructor(\n def: PaymentFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n this.options = def.options\n\n const paymentStateSchema = joi\n .object({\n paymentId: joi.string().required(),\n reference: joi.string().required(),\n amount: joi.number().required(),\n description: joi.string().required(),\n uuid: joi.string().uuid().required(),\n formId: joi.string().required(),\n isLivePayment: joi.boolean().required(),\n preAuth: joi\n .object({\n status: joi\n .string()\n .valid('success', 'failed', 'started')\n .required(),\n createdAt: joi.string().isoDate().required()\n })\n .required()\n })\n .unknown(true)\n .label(this.label)\n\n this.formSchema = paymentStateSchema\n // 'required()' forces the payment page to be invalid until we have valid payment state\n // i.e. the user will automatically be directed back to the payment page\n // if they attempt to access future pages when no payment entered yet\n this.stateSchema = paymentStateSchema.required()\n }\n\n /**\n * Gets the PaymentState from form submission state\n */\n getPaymentStateFromState(\n state: FormSubmissionState\n ): PaymentState | undefined {\n const value = state[this.name]\n return this.isPaymentState(value) ? value : undefined\n }\n\n getDisplayStringFromState(state: FormSubmissionState): string {\n const value = this.getPaymentStateFromState(state)\n\n if (!value) {\n return ''\n }\n\n return `£${value.amount.toFixed(2)} - ${value.description}`\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const viewModel = super.getViewModel(payload, errors)\n\n // Payload is pre-populated from state if a payment has already been made\n const paymentState = this.isPaymentState(payload[this.name] as unknown)\n ? (payload[this.name] as unknown as PaymentState)\n : undefined\n\n // When user initially visits the payment page, there is no payment state yet so the amount is read form the form definition.\n const amount = paymentState?.amount ?? this.options.amount\n\n const formattedAmount = amount.toFixed(2)\n\n return {\n ...viewModel,\n amount: formattedAmount,\n description: this.options.description,\n paymentState\n }\n }\n\n /**\n * Type guard to check if value is PaymentState\n */\n isPaymentState(value: unknown): value is PaymentState {\n return PaymentField.isPaymentState(value)\n }\n\n /**\n * Static type guard to check if value is PaymentState\n */\n static isPaymentState(value: unknown): value is PaymentState {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n\n const state = value as PaymentState\n return (\n typeof state.paymentId === 'string' &&\n typeof state.amount === 'number' &&\n typeof state.description === 'string'\n )\n }\n\n /**\n * Override base isState to validate PaymentState\n */\n isState(value?: FormStateValue | FormState): value is FormState {\n return this.isPaymentState(value)\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isPaymentState(value)\n ? (value as unknown as NonNullable<FormStateValue>)\n : undefined\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n return this.isPaymentState(state)\n ? `Reference: ${state.reference}\\nAmount: ${state.amount.toFixed(2)}`\n : ''\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return PaymentField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n {\n type: 'paymentRequired',\n template: 'Complete the payment to continue'\n }\n ],\n advancedSettingsErrors: []\n }\n }\n\n /**\n * Dispatcher for external redirect to GOV.UK Pay\n */\n static async dispatcher(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n args: PaymentDispatcherArgs\n ): Promise<unknown> {\n const { options, name: componentName } = args.component\n const { model } = args.controller\n\n const state = await args.controller.getState(request)\n const { baseUrl } = getPluginOptions(request.server)\n const summaryUrl = `${baseUrl}/${model.basePath}/summary`\n\n const existingPaymentState = state[componentName]\n if (\n PaymentField.isPaymentState(existingPaymentState) &&\n existingPaymentState.preAuth?.status === 'success'\n ) {\n return h.redirect(summaryUrl).code(StatusCodes.SEE_OTHER)\n }\n\n const isLivePayment = args.isLive && !args.isPreview\n const formId = args.controller.model.formId\n const paymentService = createPaymentService(isLivePayment, formId)\n\n const uuid = randomUUID()\n\n const reference = state.$$__referenceNumber as string\n const amount = options.amount\n\n const description = options.description\n\n const slug = `/${model.basePath}`\n\n const payCallbackUrl = `${baseUrl}/payment-callback?uuid=${uuid}`\n const paymentPageUrl = args.sourceUrl\n\n const amountInPence = Math.round(amount * 100)\n const payment = await paymentService.createPayment(\n amountInPence,\n description,\n payCallbackUrl,\n reference,\n { formId, slug }\n )\n\n const sessionData: PaymentSessionData = {\n uuid,\n formId,\n reference,\n amount,\n description,\n paymentId: payment.paymentId,\n componentName,\n returnUrl: summaryUrl,\n failureUrl: paymentPageUrl,\n isLivePayment\n }\n\n request.yar.set(`payment-${uuid}`, sessionData)\n\n return h.redirect(payment.paymentUrl).code(StatusCodes.SEE_OTHER)\n }\n\n /**\n * Called on form submission to capture the payment\n * @see https://docs.payments.service.gov.uk/delayed_capture/#delay-taking-a-payment\n */\n async onSubmit(\n request: FormRequestPayload,\n _metadata: FormMetadata,\n context: FormContext\n ): Promise<void> {\n const paymentState = this.getPaymentStateFromState(context.state)\n\n if (!paymentState) {\n throw new PaymentPreAuthError(\n this,\n 'Complete the payment to continue',\n true,\n PaymentErrorTypes.PaymentIncomplete\n )\n }\n\n if (paymentState.capture?.status === 'success') {\n return\n }\n\n const { paymentId, isLivePayment, formId } = paymentState\n const paymentService = createPaymentService(isLivePayment, formId)\n\n /**\n * @see https://docs.payments.service.gov.uk/api_reference/#payment-status-lifecycle\n */\n const status = await paymentService.getPaymentStatus(paymentId)\n\n PaymentSubmissionError.checkPaymentAmount(\n status.amount,\n this.options.amount,\n this\n )\n\n if (status.state.status === 'success') {\n await this.markPaymentCaptured(request, paymentState)\n return\n }\n\n if (status.state.status !== 'capturable') {\n throw new PaymentPreAuthError(\n this,\n 'Your payment authorisation has expired. Please add your payment details again.',\n true,\n PaymentErrorTypes.PaymentExpired\n )\n }\n\n const captured = await paymentService.capturePayment(paymentId)\n\n if (!captured) {\n throw new PaymentPreAuthError(\n this,\n 'There was a problem and your form was not submitted. Try submitting the form again.',\n false\n )\n }\n\n await this.markPaymentCaptured(request, paymentState)\n }\n\n /**\n * Updates payment state to mark capture as successful\n * This ensures we don't try to re-capture on submission retry\n */\n private async markPaymentCaptured(\n request: FormRequestPayload,\n paymentState: PaymentState\n ): Promise<void> {\n const updatedState: PaymentState = {\n ...paymentState,\n capture: {\n status: 'success',\n createdAt: new Date().toISOString()\n }\n }\n\n if (this.page) {\n const currentState = await this.page.getState(request)\n await this.page.mergeState(request, currentState, {\n [this.name]: updatedState\n })\n }\n }\n}\n\nexport interface PaymentDispatcherArgs {\n controller: {\n model: {\n formId: string\n basePath: string\n name: string\n }\n getState: (request: AnyFormRequest) => Promise<FormSubmissionState>\n }\n component: PaymentField\n sourceUrl: string\n isLive: boolean\n isPreview: boolean\n}\n\n/**\n * Session data stored when dispatching to GOV.UK Pay\n */\nexport interface PaymentSessionData {\n uuid: string\n formId: string\n reference: string\n amount: number\n description: string\n paymentId: string\n componentName: string\n returnUrl: string\n failureUrl: string\n isLivePayment: boolean\n}\n"],"mappings":"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","ignoreList":[]}
|