@sails-pay/bachs 0.0.2 → 0.0.4
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/adapter.js +1 -0
- package/helpers/connect.js +86 -0
- package/helpers/payloads.js +48 -19
- package/helpers/validate-checkout-items.js +177 -0
- package/machines/checkout.js +15 -5
- package/machines/connect/account/create.js +77 -0
- package/machines/connect/account/get.js +49 -0
- package/machines/connect/account/link.js +71 -0
- package/machines/connect/balance/get.js +47 -0
- package/machines/connect/payout/create.js +114 -0
- package/machines/connect/transfer/create.js +71 -0
- package/machines/index.js +16 -0
- package/package.json +1 -1
- package/test/checkout.test.js +271 -6
- package/test/connect.test.js +390 -0
- package/test/payloads.test.js +171 -2
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const fetch = require('../../../helpers/fetch')
|
|
2
|
+
const parameters = require('../../../helpers/parameters')
|
|
3
|
+
const { toPayout } = require('../../../helpers/connect')
|
|
4
|
+
|
|
5
|
+
module.exports = require('machine').build({
|
|
6
|
+
friendlyName: 'Create connected account payout',
|
|
7
|
+
description:
|
|
8
|
+
"Withdraws from a connected account's balance to one of its payout destinations, defaulting to the account's default destination for the currency.",
|
|
9
|
+
moreInfoUrl: 'https://docs.bachs.io/connect/payouts',
|
|
10
|
+
inputs: {
|
|
11
|
+
apiKey: parameters.BACHS_API_KEY,
|
|
12
|
+
baseUrl: parameters.BACHS_BASE_URL,
|
|
13
|
+
account: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
required: true,
|
|
16
|
+
description: 'The connected account withdrawing.'
|
|
17
|
+
},
|
|
18
|
+
amount: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
required: true,
|
|
21
|
+
description: 'Decimal amount the destination should receive.'
|
|
22
|
+
},
|
|
23
|
+
currency: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description:
|
|
26
|
+
'ISO 4217 currency. Required when destination is omitted, so the default destination can be found.'
|
|
27
|
+
},
|
|
28
|
+
destination: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'A payout destination ID. Omit to use the default one.'
|
|
31
|
+
},
|
|
32
|
+
reference: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
maxLength: 128,
|
|
35
|
+
description: 'Your reference for the payout.'
|
|
36
|
+
},
|
|
37
|
+
idempotencyKey: {
|
|
38
|
+
type: 'string',
|
|
39
|
+
description: 'Prevents a retry from paying out twice.'
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
exits: {
|
|
43
|
+
success: {
|
|
44
|
+
description: 'The payout accepted for delivery.',
|
|
45
|
+
outputVariableName: 'payout',
|
|
46
|
+
outputType: 'ref'
|
|
47
|
+
},
|
|
48
|
+
noDestination: {
|
|
49
|
+
description:
|
|
50
|
+
'No destination was given and the account has no usable destination for the currency.',
|
|
51
|
+
outputVariableName: 'error',
|
|
52
|
+
outputType: 'ref'
|
|
53
|
+
},
|
|
54
|
+
couldNotCreatePayout: {
|
|
55
|
+
description: 'The payout could not be created.',
|
|
56
|
+
outputVariableName: 'error',
|
|
57
|
+
outputType: 'ref'
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
fn: async function (inputs, exits) {
|
|
61
|
+
const adapterConfig = require('../../../adapter').config
|
|
62
|
+
const request = {
|
|
63
|
+
apiKey: inputs.apiKey || adapterConfig.apiKey,
|
|
64
|
+
baseUrl: inputs.baseUrl || adapterConfig.baseUrl,
|
|
65
|
+
headers: { 'X-Account-Id': inputs.account }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let destination = inputs.destination
|
|
69
|
+
if (!destination) {
|
|
70
|
+
if (!inputs.currency) {
|
|
71
|
+
return exits.noDestination({
|
|
72
|
+
message: 'Pass a destination, or a currency to use the default one.'
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const { destinations = [] } = await fetch(
|
|
78
|
+
`/payouts/destinations?currency=${encodeURIComponent(
|
|
79
|
+
inputs.currency
|
|
80
|
+
)}`,
|
|
81
|
+
{ method: 'GET', ...request }
|
|
82
|
+
)
|
|
83
|
+
const usable = destinations.filter((candidate) => candidate.is_usable)
|
|
84
|
+
const chosen =
|
|
85
|
+
usable.find((candidate) => candidate.is_default) || usable[0]
|
|
86
|
+
if (!chosen) {
|
|
87
|
+
return exits.noDestination({
|
|
88
|
+
message: `The account has no usable ${inputs.currency} payout destination.`
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
destination = chosen.id
|
|
92
|
+
} catch (error) {
|
|
93
|
+
return exits.couldNotCreatePayout(error.bachs || error)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const payout = await fetch('/payouts', {
|
|
99
|
+
method: 'POST',
|
|
100
|
+
...request,
|
|
101
|
+
idempotencyKey: inputs.idempotencyKey || inputs.reference,
|
|
102
|
+
body: {
|
|
103
|
+
destination,
|
|
104
|
+
amount: inputs.amount,
|
|
105
|
+
...(inputs.reference && { reference: inputs.reference })
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
return exits.success(toPayout(payout, { account: inputs.account }))
|
|
110
|
+
} catch (error) {
|
|
111
|
+
return exits.couldNotCreatePayout(error.bachs || error)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
})
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const fetch = require('../../../helpers/fetch')
|
|
2
|
+
const parameters = require('../../../helpers/parameters')
|
|
3
|
+
const { toTransfer } = require('../../../helpers/connect')
|
|
4
|
+
|
|
5
|
+
module.exports = require('machine').build({
|
|
6
|
+
friendlyName: 'Create transfer',
|
|
7
|
+
description:
|
|
8
|
+
"Moves funds from the platform balance into a connected account's balance.",
|
|
9
|
+
moreInfoUrl: 'https://docs.bachs.io/connect/transfers',
|
|
10
|
+
inputs: {
|
|
11
|
+
apiKey: parameters.BACHS_API_KEY,
|
|
12
|
+
baseUrl: parameters.BACHS_BASE_URL,
|
|
13
|
+
account: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
required: true,
|
|
16
|
+
description: 'The connected account receiving the funds.'
|
|
17
|
+
},
|
|
18
|
+
amount: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
required: true,
|
|
21
|
+
description: 'Decimal amount, e.g. "10000.00".'
|
|
22
|
+
},
|
|
23
|
+
currency: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
required: true,
|
|
26
|
+
description: 'ISO 4217 currency, e.g. "NGN".'
|
|
27
|
+
},
|
|
28
|
+
group: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'Groups related transfers, e.g. one payrun.'
|
|
31
|
+
},
|
|
32
|
+
idempotencyKey: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
description: 'Prevents a retry from transferring twice.'
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
exits: {
|
|
38
|
+
success: {
|
|
39
|
+
description: 'The created transfer.',
|
|
40
|
+
outputVariableName: 'transfer',
|
|
41
|
+
outputType: 'ref'
|
|
42
|
+
},
|
|
43
|
+
couldNotCreateTransfer: {
|
|
44
|
+
description: 'The transfer could not be created.',
|
|
45
|
+
outputVariableName: 'error',
|
|
46
|
+
outputType: 'ref'
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
fn: async function (inputs, exits) {
|
|
50
|
+
const adapterConfig = require('../../../adapter').config
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const transfer = await fetch('/transfers', {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
apiKey: inputs.apiKey || adapterConfig.apiKey,
|
|
56
|
+
baseUrl: inputs.baseUrl || adapterConfig.baseUrl,
|
|
57
|
+
idempotencyKey: inputs.idempotencyKey,
|
|
58
|
+
body: {
|
|
59
|
+
destination: inputs.account,
|
|
60
|
+
amount: inputs.amount,
|
|
61
|
+
currency: inputs.currency,
|
|
62
|
+
...(inputs.group && { transfer_group: inputs.group })
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
return exits.success(toTransfer(transfer))
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return exits.couldNotCreateTransfer(error.bachs || error)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
})
|
package/machines/index.js
CHANGED
|
@@ -4,6 +4,22 @@ checkout.get = require('./checkout/get')
|
|
|
4
4
|
|
|
5
5
|
module.exports = {
|
|
6
6
|
checkout,
|
|
7
|
+
connect: {
|
|
8
|
+
account: {
|
|
9
|
+
create: require('./connect/account/create'),
|
|
10
|
+
get: require('./connect/account/get'),
|
|
11
|
+
link: require('./connect/account/link')
|
|
12
|
+
},
|
|
13
|
+
transfer: {
|
|
14
|
+
create: require('./connect/transfer/create')
|
|
15
|
+
},
|
|
16
|
+
balance: {
|
|
17
|
+
get: require('./connect/balance/get')
|
|
18
|
+
},
|
|
19
|
+
payout: {
|
|
20
|
+
create: require('./connect/payout/create')
|
|
21
|
+
}
|
|
22
|
+
},
|
|
7
23
|
customer: {
|
|
8
24
|
portal: require('./customer/portal')
|
|
9
25
|
},
|
package/package.json
CHANGED
package/test/checkout.test.js
CHANGED
|
@@ -4,6 +4,11 @@ const adapter = require('../adapter')
|
|
|
4
4
|
const checkout = require('../machines/checkout')
|
|
5
5
|
const fetch = require('../helpers/fetch')
|
|
6
6
|
|
|
7
|
+
test.afterEach(() => {
|
|
8
|
+
fetch.resetFetchImplementation()
|
|
9
|
+
adapter.config = {}
|
|
10
|
+
})
|
|
11
|
+
|
|
7
12
|
test('checkout creates a Bachs checkout session from camelCase inputs', async () => {
|
|
8
13
|
const calls = []
|
|
9
14
|
|
|
@@ -24,7 +29,7 @@ test('checkout creates a Bachs checkout session from camelCase inputs', async ()
|
|
|
24
29
|
|
|
25
30
|
const checkoutUrl = await checkout({
|
|
26
31
|
apiKey: 'sk_sandbox_123',
|
|
27
|
-
items: [{ product: 'prod_abc123'
|
|
32
|
+
items: [{ product: 'prod_abc123' }],
|
|
28
33
|
customer: {
|
|
29
34
|
email: 'customer@example.com',
|
|
30
35
|
name: 'Jane Doe'
|
|
@@ -47,18 +52,280 @@ test('checkout creates a Bachs checkout session from camelCase inputs', async ()
|
|
|
47
52
|
},
|
|
48
53
|
product_cart: [
|
|
49
54
|
{
|
|
50
|
-
product_id: 'prod_abc123'
|
|
51
|
-
quantity: 1
|
|
55
|
+
product_id: 'prod_abc123'
|
|
52
56
|
}
|
|
53
57
|
],
|
|
54
58
|
return_url: 'https://example.com/return',
|
|
55
59
|
cancel_url: 'https://example.com/cancel',
|
|
56
60
|
reference: 'order_123'
|
|
57
61
|
})
|
|
62
|
+
})
|
|
58
63
|
|
|
59
|
-
|
|
64
|
+
test('checkout sends custom pricing and the buyer-selected amount', async () => {
|
|
65
|
+
const calls = []
|
|
66
|
+
|
|
67
|
+
fetch.setFetchImplementation(async (url, options) => {
|
|
68
|
+
calls.push({ url, options })
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
ok: true,
|
|
72
|
+
status: 201,
|
|
73
|
+
statusText: 'Created',
|
|
74
|
+
text: async () =>
|
|
75
|
+
JSON.stringify({
|
|
76
|
+
checkout_url: 'https://pay.bachs.io/c/custom'
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const checkoutUrl = await checkout({
|
|
82
|
+
apiKey: 'sk_sandbox_123',
|
|
83
|
+
items: [
|
|
84
|
+
{
|
|
85
|
+
product: 'prod_custom',
|
|
86
|
+
pricing: {
|
|
87
|
+
type: 'custom',
|
|
88
|
+
presetAmount: '10.00',
|
|
89
|
+
minimumAmount: '5.00',
|
|
90
|
+
maximumAmount: '100.00'
|
|
91
|
+
},
|
|
92
|
+
chosenAmount: '12.00'
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
assert.equal(checkoutUrl, 'https://pay.bachs.io/c/custom')
|
|
98
|
+
assert.deepEqual(JSON.parse(calls[0].options.body), {
|
|
99
|
+
customer: {},
|
|
100
|
+
product_cart: [
|
|
101
|
+
{
|
|
102
|
+
product_id: 'prod_custom',
|
|
103
|
+
pricing: {
|
|
104
|
+
price_type: 'custom',
|
|
105
|
+
preset_amount: '10.00',
|
|
106
|
+
minimum_amount: '5.00',
|
|
107
|
+
maximum_amount: '100.00'
|
|
108
|
+
},
|
|
109
|
+
amount: '12.00'
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('checkout preserves pure checkout behavior', async () => {
|
|
116
|
+
const calls = []
|
|
117
|
+
|
|
118
|
+
fetch.setFetchImplementation(async (url, options) => {
|
|
119
|
+
calls.push({ url, options })
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
ok: true,
|
|
123
|
+
status: 201,
|
|
124
|
+
statusText: 'Created',
|
|
125
|
+
text: async () =>
|
|
126
|
+
JSON.stringify({
|
|
127
|
+
checkout_url: 'https://pay.bachs.io/c/pure'
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const checkoutUrl = await checkout({
|
|
133
|
+
apiKey: 'sk_sandbox_123',
|
|
134
|
+
amount: '42.00',
|
|
135
|
+
currency: 'USD',
|
|
136
|
+
reference: 'pure_123'
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
assert.equal(checkoutUrl, 'https://pay.bachs.io/c/pure')
|
|
140
|
+
assert.equal(calls[0].url, 'https://sandbox-api.bachs.io/v1/checkouts')
|
|
141
|
+
assert.equal(calls[0].options.headers['Idempotency-Key'], 'pure_123')
|
|
142
|
+
assert.deepEqual(JSON.parse(calls[0].options.body), {
|
|
143
|
+
pricing: {
|
|
144
|
+
currency: 'USD',
|
|
145
|
+
amount: '42.00'
|
|
146
|
+
},
|
|
147
|
+
reference: 'pure_123'
|
|
148
|
+
})
|
|
60
149
|
})
|
|
61
150
|
|
|
151
|
+
const invalidItemCases = [
|
|
152
|
+
{
|
|
153
|
+
name: 'amount with explicit pricing',
|
|
154
|
+
item: {
|
|
155
|
+
product: 'prod_123',
|
|
156
|
+
amount: '19.00',
|
|
157
|
+
pricing: { type: 'fixed', amount: '19.00' }
|
|
158
|
+
},
|
|
159
|
+
field: 'items[0]',
|
|
160
|
+
message: /both amount and pricing/
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'an unsupported pricing type',
|
|
164
|
+
item: {
|
|
165
|
+
product: 'prod_123',
|
|
166
|
+
pricing: { type: 'metered' }
|
|
167
|
+
},
|
|
168
|
+
field: 'items[0].pricing.type',
|
|
169
|
+
message: /fixed, custom, or free/
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'fixed pricing without an amount',
|
|
173
|
+
item: {
|
|
174
|
+
product: 'prod_123',
|
|
175
|
+
pricing: { type: 'fixed' }
|
|
176
|
+
},
|
|
177
|
+
field: 'items[0].pricing.amount',
|
|
178
|
+
message: /required for fixed pricing/
|
|
179
|
+
},
|
|
180
|
+
...['presetAmount', 'minimumAmount', 'maximumAmount'].map((field) => ({
|
|
181
|
+
name: `fixed pricing with ${field}`,
|
|
182
|
+
item: {
|
|
183
|
+
product: 'prod_123',
|
|
184
|
+
pricing: {
|
|
185
|
+
type: 'fixed',
|
|
186
|
+
amount: '19.00',
|
|
187
|
+
[field]: '10.00'
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
field: `items[0].pricing.${field}`,
|
|
191
|
+
message: /not allowed with fixed pricing/
|
|
192
|
+
})),
|
|
193
|
+
{
|
|
194
|
+
name: 'custom pricing with a fixed amount',
|
|
195
|
+
item: {
|
|
196
|
+
product: 'prod_123',
|
|
197
|
+
pricing: {
|
|
198
|
+
type: 'custom',
|
|
199
|
+
amount: '19.00'
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
field: 'items[0].pricing.amount',
|
|
203
|
+
message: /not allowed with custom pricing/
|
|
204
|
+
},
|
|
205
|
+
...['amount', 'presetAmount', 'minimumAmount', 'maximumAmount'].map(
|
|
206
|
+
(field) => ({
|
|
207
|
+
name: `free pricing with ${field}`,
|
|
208
|
+
item: {
|
|
209
|
+
product: 'prod_123',
|
|
210
|
+
pricing: {
|
|
211
|
+
type: 'free',
|
|
212
|
+
[field]: '10.00'
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
field: `items[0].pricing.${field}`,
|
|
216
|
+
message: /not allowed with free pricing/
|
|
217
|
+
})
|
|
218
|
+
),
|
|
219
|
+
{
|
|
220
|
+
name: 'free pricing with chosenAmount',
|
|
221
|
+
item: {
|
|
222
|
+
product: 'prod_123',
|
|
223
|
+
pricing: { type: 'free' },
|
|
224
|
+
chosenAmount: '10.00'
|
|
225
|
+
},
|
|
226
|
+
field: 'items[0].chosenAmount',
|
|
227
|
+
message: /not allowed with free pricing/
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: 'fixed amount shorthand with chosenAmount',
|
|
231
|
+
item: {
|
|
232
|
+
product: 'prod_123',
|
|
233
|
+
amount: '19.00',
|
|
234
|
+
chosenAmount: '10.00'
|
|
235
|
+
},
|
|
236
|
+
field: 'items[0].chosenAmount',
|
|
237
|
+
message: /catalog custom pricing or ad-hoc custom pricing/
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: 'explicit fixed pricing with chosenAmount',
|
|
241
|
+
item: {
|
|
242
|
+
product: 'prod_123',
|
|
243
|
+
pricing: { type: 'fixed', amount: '19.00' },
|
|
244
|
+
chosenAmount: '10.00'
|
|
245
|
+
},
|
|
246
|
+
field: 'items[0].chosenAmount',
|
|
247
|
+
message: /catalog custom pricing or ad-hoc custom pricing/
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: 'a numeric amount shorthand',
|
|
251
|
+
item: {
|
|
252
|
+
product: 'prod_123',
|
|
253
|
+
amount: 1900
|
|
254
|
+
},
|
|
255
|
+
field: 'items[0].amount',
|
|
256
|
+
message: /decimal string/
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: 'a numeric chosenAmount',
|
|
260
|
+
item: {
|
|
261
|
+
product: 'prod_123',
|
|
262
|
+
chosenAmount: 1200
|
|
263
|
+
},
|
|
264
|
+
field: 'items[0].chosenAmount',
|
|
265
|
+
message: /decimal string/
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: 'a numeric fixed pricing amount',
|
|
269
|
+
item: {
|
|
270
|
+
product: 'prod_123',
|
|
271
|
+
pricing: { type: 'fixed', amount: 1900 }
|
|
272
|
+
},
|
|
273
|
+
field: 'items[0].pricing.amount',
|
|
274
|
+
message: /decimal string/
|
|
275
|
+
},
|
|
276
|
+
...['presetAmount', 'minimumAmount', 'maximumAmount'].map((field) => ({
|
|
277
|
+
name: `a numeric custom pricing ${field}`,
|
|
278
|
+
item: {
|
|
279
|
+
product: 'prod_123',
|
|
280
|
+
pricing: {
|
|
281
|
+
type: 'custom',
|
|
282
|
+
[field]: 1000
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
field: `items[0].pricing.${field}`,
|
|
286
|
+
message: /decimal string/
|
|
287
|
+
})),
|
|
288
|
+
...[
|
|
289
|
+
['zero', 0],
|
|
290
|
+
['a fraction', 1.5],
|
|
291
|
+
['a string', '2']
|
|
292
|
+
].map(([description, quantity]) => ({
|
|
293
|
+
name: `${description} quantity`,
|
|
294
|
+
item: {
|
|
295
|
+
product: 'prod_123',
|
|
296
|
+
quantity
|
|
297
|
+
},
|
|
298
|
+
field: 'items[0].quantity',
|
|
299
|
+
message: /integer of at least 1/
|
|
300
|
+
}))
|
|
301
|
+
]
|
|
302
|
+
|
|
303
|
+
for (const invalidCase of invalidItemCases) {
|
|
304
|
+
test(`checkout rejects ${invalidCase.name} before calling Bachs`, async () => {
|
|
305
|
+
let fetchCalls = 0
|
|
306
|
+
|
|
307
|
+
fetch.setFetchImplementation(async () => {
|
|
308
|
+
fetchCalls += 1
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
await assert.rejects(
|
|
312
|
+
() =>
|
|
313
|
+
checkout({
|
|
314
|
+
apiKey: 'sk_sandbox_123',
|
|
315
|
+
items: [invalidCase.item]
|
|
316
|
+
}),
|
|
317
|
+
(error) => {
|
|
318
|
+
assert.equal(error.exit, 'invalidRequest')
|
|
319
|
+
assert.equal(error.raw.field, invalidCase.field)
|
|
320
|
+
assert.match(error.raw.message, invalidCase.message)
|
|
321
|
+
return true
|
|
322
|
+
}
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
assert.equal(fetchCalls, 0)
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
|
|
62
329
|
test('adapter exposes checkout.get as the uniform checkout lookup API', async () => {
|
|
63
330
|
const calls = []
|
|
64
331
|
|
|
@@ -95,6 +362,4 @@ test('adapter exposes checkout.get as the uniform checkout lookup API', async ()
|
|
|
95
362
|
'https://sandbox-api.bachs.io/v1/checkouts/chk_123'
|
|
96
363
|
)
|
|
97
364
|
assert.equal(calls[0].options.method, 'GET')
|
|
98
|
-
|
|
99
|
-
fetch.resetFetchImplementation()
|
|
100
365
|
})
|