-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathbnpl-arazzo.yaml
260 lines (251 loc) · 10.1 KB
/
bnpl-arazzo.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
arazzo: 1.0.0
info:
title: BNPL Workflow description
description: >-
Describes the steps to secure a loan at checkout from a BNPL platform. It is a multi-step process that requires multiple API calls across several API providers to be completed successfully.
version: 1.0.0
sourceDescriptions:
- name: BnplApi
url: https://raw.githubusercontent.com/OAI/Arazzo-Specification/main/examples/1.0.0/bnpl-openapi.yaml
type: openapi
workflows:
- workflowId: ApplyForLoanAtCheckout
summary: Apply for a loan at checkout using a BNPL platform
description: Describes the steps to secure a loan at checkout from a BNPL platform. It is a multistep process that requires multiple API calls across several API providers to be completed successfully.
inputs:
type: object
required:
- customer
- products
properties:
customer:
description: |
Customer can either be the customer details, which will be used for enrollment, or a link to an existing customer resource as the customer already uses the BNPL platform
oneOf:
- type: object
required:
- firstName
- lastName
- dateOfBirth
- postalCode
properties:
firstName:
description: First name of customer
type: string
minLength: 1
maxLength: 70
lastName:
description: Last name of customer
type: string
minLength: 1
maxLength: 70
dateOfBirth:
description: Customer date of birth
type: string
format: date-time
postalCode:
description: Zip code or postal code of customer
type: string
minLength: 1
maxLength: 70
additionalProperties: false
- type: object
required:
- uri
properties:
uri:
description: URI that points to an existing customer resource, as customer already enrolled on platform
type: string
format: uri
additionalProperties: false
products:
type: array
minItems: 1
items:
type: object
required:
- productCode
- purchaseAmount
properties:
merchantCategoryCode:
description: Merchant category code of merchant. Only required for marketplace ecommerce platforms
type: string
pattern: '^[0-9]{4}$'
productCode:
description: Product code for loan application. Required for eligibility check
type: string
purchaseAmount:
description: Product purchase amount and currency code
type: object
required:
- currency
- amount
properties:
currency:
description: Currency code
type: string
pattern: "^[A-Z]{3}$"
amount:
description: Amount
type: number
steps:
- stepId: checkLoanCanBeProvided
description: |
Call the BNPL API to filter the basket for products qualifying for checkout loans. Pass in the array of products from the workflow input as the payload for the API call.
Act on the response payload:
- If a list of qualifying products is returned then submit customer choices.
- If the list of qualifying products is empty then end the workflow
operationId: findEligibleProducts
requestBody:
contentType: application/json
payload: |
{
"customer": "{$inputs.customer}",
"products": "{$inputs.products}"
}
successCriteria:
- condition: $statusCode == 200
onSuccess:
- name: existingCustomerNotEligible
type: end
criteria:
- condition: $statusCode == 200
- condition: $response.body#/existingCustomerNotEligible == false
- name: qualifyingProductsFound
type: goto
stepId: getCustomerTermsAndConditions
criteria:
- condition: $statusCode == 200
- context: $response.body
type: jsonpath
condition: $[?count(@.products) > 0]
- name: qualifyingProductsNotFound
type: end
criteria:
- condition: $statusCode == 200
- context: $response.body
type: jsonpath
condition: $[?count(@.products) == 0]
outputs:
eligibilityCheckRequired: $response.body#/eligibilityCheckRequired
eligibleProducts: $response.body#/products
totalLoanAmount: $response.body#/totalAmount
- stepId: getCustomerTermsAndConditions
description: |
Get the terms and conditions for the BNPL loans. This is static data and therefore has no arguments.
The data will be displayed to the customer and they'll accept the terms out-of-band.
After this step the flow will need to do a customer eligibility check if required.
operationId: getTermsAndConditions
successCriteria:
- condition: $statusCode == 200
onSuccess:
- name: eligibilityCheckRequired
type: goto
stepId: createCustomer
criteria:
- condition: $steps.checkLoanCanBeProvided.outputs.eligibilityCheckRequired == true
- name: eligibilityCheckNotRequired
type: goto
stepId: initiateBnplTransaction
criteria:
- condition: $steps.checkLoanCanBeProvided.outputs.eligibilityCheckRequired == false
outputs:
termsAndConditions: $response.body
- stepId: createCustomer
description: |
Call the BNPL platform and verify the customer is eligible for the loan, which creates a customer resource. This step is skipped if the customer is already enrolled in the BNPL platform.
Accepting the terms and conditions is set to true as the assumption is they have been accepted when this step is invoked.
If the customer is eligible for the BNPL loan then a customer resource is created
operationId: createCustomer
requestBody:
contentType: application/json
payload: |
{
"firstName": "{$inputs.customer.firstName}",
"lastName": "{$inputs.customer.lastName}",
"dateOfBirth": "{$inputs.customer.dateOfBirth}",
"postalCode": "{$inputs.customer.postalCode}"
"termsAndConditionsAccepted": true
}
successCriteria:
- condition: $statusCode == 200 || $statusCode == 201
onSuccess:
- name: customerIsEligible
type: goto
stepId: initiateBnplTransaction
criteria:
- condition: $statusCode == 201
- name: customerIsNotEligible
type: end
criteria:
- condition: $statusCode == 200
outputs:
customer: $response.body#/links/self
- stepId: initiateBnplTransaction
description: Initiate the BNPL transaction by sending the customer identifier, eligible products, and indicative loan amount to initiate the loan process
operationId: createBnplTransaction
requestBody:
contentType: application/json
payload: |
{
"enrolledCustomer": "{$inputs.customer.uri}",
"newCustomer": "{$steps.createCustomer.outputs.customer}",
"products": "{$steps.checkLoanCanBeProvided.outputs.eligibleProducts}"
}
successCriteria:
- condition: $statusCode == 202
onSuccess:
- name: CustomerAuthorizationRequired
type: goto
stepId: authenticateCustomerAndAuthorizeLoan
criteria:
- condition: $response.body#/redirectAuthToken != null
- name: CustomerAuthorizationNotRequired
type: goto
stepId: retrieveFinalizedPaymentPlan
criteria:
- condition: $response.body#/redirectAuthToken == null
outputs:
redirectAuthToken: $response.body#/redirectAuthToken
loanTransactionResourceUrl: $response.body#/links/self
- stepId: authenticateCustomerAndAuthorizeLoan
description: |
Authenticate the customer and seek authorization for the loan.
Notes:
- Authenticate in this case does not necessarily mean with a valid set of credentials. It could be to prove the identity of the end user, possibly doing an UMA style interaction (which is too complex to tie into this example).
- A redirect is returned for to be sent to the customer. The customer should follow this, but the success of the authorisation is out-of-band.
- This flow mimics OAuth style authorization but is not an exact match as it does not rely on an authorisation code/access token exchange (as this seems somewhat artificial in this context).
operationId: getAuthorization
parameters:
- name: redirectAuthToken
in: query
value: $steps.authenticateCustomerAndAuthorizeLoan.outputs.redirectAuthToken
successCriteria:
- condition: $statusCode == 302
outputs:
redirectUrl: $response.headers.Location
- stepId: retrieveFinalizedPaymentPlan
description: Retrieve finalized payment plan to show to customer once authorization is complete
operationId: retrieveBnplLoanTransaction
parameters:
- name: loanTransactionId
in: path
value: $steps.initiateBnplTransaction.outputs.loanTransactionId
successCriteria:
- condition: $statusCode == 200
outputs:
finalizedPaymentPlan: $response.body
- stepId: updateOrderStatus
description: Send update from eCommerce platform to indicate order fulfilled and loan is therefore active
operationId: updateBnplLoanTransactionStatus
parameters:
- name: loanTransactionId
in: path
value: $steps.initiateBnplTransaction.outputs.loanTransactionId
requestBody:
contentType: application/json
payload: { "loanStatus": "Completed" }
successCriteria:
- condition: $statusCode == 204
outputs:
finalizedPaymentPlan: $steps.retrieveFinalizedPaymentPlan.finalizedPaymentPlan