Skip to content

Commit 5b6cb98

Browse files
committed
feat: add payment forms subscription action to PaySG integration
1 parent d16c3ab commit 5b6cb98

File tree

4 files changed

+186
-2
lines changed

4 files changed

+186
-2
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import type { IRawAction } from '@plumber/types'
2+
3+
import { ZodError } from 'zod'
4+
import { fromZodError } from 'zod-validation-error'
5+
6+
import StepError, { GenericSolution } from '@/errors/step'
7+
8+
import { requestSchema } from './schema'
9+
10+
const action: IRawAction = {
11+
name: 'Create payment form submission for subscription',
12+
key: 'createPaymentFormSubmissionSubscription',
13+
description:
14+
'Create a new submission for a payment form, and initiate a subscription',
15+
arguments: [
16+
{
17+
label: 'Payment Form Link',
18+
description: 'This can be found on your PaySG payment services dashboard',
19+
key: 'formId',
20+
type: 'string' as const,
21+
required: true,
22+
placeholder: 'e.g. https://pay.gov.sg/forms/aBC123Def456HijK789LMn',
23+
},
24+
{
25+
label: 'FormSG Form ID',
26+
description: 'Input the variable corresponding to form ID here',
27+
key: 'formsg_form_id',
28+
type: 'string' as const,
29+
required: true,
30+
variables: true,
31+
},
32+
{
33+
label: 'FormSG Submission ID',
34+
key: 'formsg_submission_id',
35+
type: 'string' as const,
36+
required: true,
37+
variables: true,
38+
},
39+
{
40+
label: 'FormSG Reference Field Answer',
41+
key: 'nonce',
42+
type: 'string' as const,
43+
required: true,
44+
variables: true,
45+
},
46+
{
47+
label: 'Payer Name',
48+
key: 'payer_name',
49+
type: 'string' as const,
50+
required: true,
51+
variables: true,
52+
},
53+
{
54+
label: 'Payer Email',
55+
key: 'payer_email',
56+
type: 'string' as const,
57+
required: false,
58+
variables: true,
59+
},
60+
{
61+
label: 'Payer Address',
62+
key: 'payer_address',
63+
type: 'string' as const,
64+
required: false,
65+
variables: true,
66+
},
67+
{
68+
label: 'Payer Identifier',
69+
key: 'payer_identifier',
70+
type: 'string' as const,
71+
required: false,
72+
variables: true,
73+
},
74+
{
75+
label: 'Amount (in cents)',
76+
key: 'amount_in_cents',
77+
type: 'string' as const,
78+
required: true,
79+
variables: true,
80+
},
81+
{
82+
label: 'Frequency',
83+
key: 'frequency',
84+
type: 'dropdown',
85+
options: [
86+
{
87+
label: 'Monthly',
88+
value: 'monthly',
89+
},
90+
],
91+
required: true,
92+
},
93+
{
94+
label: 'Description',
95+
key: 'description',
96+
type: 'string' as const,
97+
required: true,
98+
variables: true,
99+
},
100+
{
101+
label: 'Additional responses',
102+
description: 'These will be included in reports exported from PaySG',
103+
key: 'responses',
104+
type: 'multirow' as const,
105+
required: false,
106+
subFields: [
107+
{
108+
placeholder: 'Question',
109+
key: 'question',
110+
type: 'string' as const,
111+
required: true,
112+
variables: true,
113+
},
114+
{
115+
placeholder: 'Answer',
116+
key: 'answer',
117+
type: 'string' as const,
118+
required: true,
119+
variables: true,
120+
},
121+
],
122+
},
123+
],
124+
125+
async run($) {
126+
const paymentServiceId = $.auth.data.paymentServiceId as string
127+
128+
try {
129+
const { formId, ...body } = requestSchema.parse($.step.parameters)
130+
131+
await $.http.post(
132+
`/v1/payment-services/:paymentServiceId/forms/:formId/subscription-submissions`,
133+
body,
134+
{
135+
urlPathParams: {
136+
paymentServiceId,
137+
formId,
138+
},
139+
},
140+
)
141+
$.setActionItem({ raw: { success: true } })
142+
} catch (error) {
143+
if (error instanceof ZodError) {
144+
const firstError = fromZodError(error).details[0]
145+
146+
throw new StepError(
147+
`${firstError.message} under set up step`,
148+
GenericSolution.ReconfigureInvalidField,
149+
$.step.position,
150+
$.app.name,
151+
)
152+
}
153+
154+
throw error
155+
}
156+
},
157+
}
158+
159+
export default action
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import emailValidator from 'email-validator'
2+
import { z } from 'zod'
3+
4+
import { requestSchema as createPaymentFormSubmissionRequestSchema } from '../create-payment-form-submission/schema'
5+
6+
export const requestSchema = createPaymentFormSubmissionRequestSchema.extend({
7+
description: z
8+
.string({ invalid_type_error: 'Empty description' })
9+
.trim()
10+
.min(1, { message: 'Specify a description' })
11+
.max(500, { message: 'Description cannot be more than 500 characters' }),
12+
frequency: z.literal('monthly'),
13+
payer_address: z
14+
.string()
15+
.trim()
16+
.transform((value) => value || undefined)
17+
.optional(),
18+
payer_identifier: z
19+
.string()
20+
.trim()
21+
.transform((value) => value || undefined)
22+
.optional(),
23+
})

packages/backend/src/apps/paysg/actions/create-payment-form-submission/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import StepError, { GenericSolution } from '@/errors/step'
88
import { requestSchema } from './schema'
99

1010
const action: IRawAction = {
11-
name: 'Create payment form submission',
11+
name: 'Create payment form submission for one-time payment',
1212
key: 'createPaymentFormSubmission',
1313
description:
14-
'Create a new submission for a payment form, and initiate a payment request',
14+
'Create a new submission for a payment form, and initiate a one-time payment',
1515
arguments: [
1616
{
1717
label: 'Payment Form Link',

packages/backend/src/apps/paysg/actions/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import createPayment from './create-payment'
22
import createPaymentFormSubmission from './create-payment-form-submission'
3+
import createPaymentFormSubmissionSubscription from './create-payment-form-submission-subscription'
34
import getPayment from './get-payment'
45
import sendEmail from './send-email'
56

@@ -8,4 +9,5 @@ export default [
89
getPayment,
910
sendEmail,
1011
createPaymentFormSubmission,
12+
createPaymentFormSubmissionSubscription,
1113
]

0 commit comments

Comments
 (0)