Skip to content

Commit 6d57b52

Browse files
committed
Handles zero-amount payment flows seamlessly
Updates payment processing logic to bypass external API calls for free orders and ensures completion status for zero-amount carts. Improves reliability by supporting free transactions without unnecessary external requests.
1 parent 1946458 commit 6d57b52

File tree

3 files changed

+69
-42
lines changed

3 files changed

+69
-42
lines changed

src/Pay.vue

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ const waitForCompleted = async () => {
156156
const body = await result.json()
157157
const items = body.data as CartItem[]
158158
if (
159+
items.length > 0 &&
159160
items.every((item) => item.status === CartItemStatus.Completed)
160161
) {
161162
clearInterval(polling)
@@ -307,29 +308,31 @@ const clickHandler = async () => {
307308
})
308309
309310
const pay = await whenNotError(paymentKey, (key) =>
310-
new Promise<{}>((resolve, reject) => {
311-
pop.pay(key, {
312-
skipOrderSummary: true,
313-
autoReturn: true,
314-
language: 'en', //'en' | 'ja' | 'zh'
315-
onSuccess: function (result: any) {
316-
console.log('success')
317-
console.log(result)
318-
waitingForCompleted.value = true
319-
return resolve(result as {})
320-
},
321-
onFailure: function (result: any) {
322-
console.log('failure')
323-
console.log(result)
324-
return reject(new Error(`${result.result_code}: ${result.status}`))
325-
},
326-
onIncomplete: function (result: any) {
327-
console.log('incomplete')
328-
console.log(result)
329-
return reject(new Error(`${result.status}`))
330-
},
331-
})
332-
}).catch((err: Error) => err),
311+
whenDefined(key, (_key) =>
312+
new Promise<{}>((resolve, reject) => {
313+
pop.pay(_key, {
314+
skipOrderSummary: true,
315+
autoReturn: true,
316+
language: 'en', //'en' | 'ja' | 'zh'
317+
onSuccess: function (result: any) {
318+
console.log('success')
319+
console.log(result)
320+
waitingForCompleted.value = true
321+
return resolve(result as {})
322+
},
323+
onFailure: function (result: any) {
324+
console.log('failure')
325+
console.log(result)
326+
return reject(new Error(`${result.result_code}: ${result.status}`))
327+
},
328+
onIncomplete: function (result: any) {
329+
console.log('incomplete')
330+
console.log(result)
331+
return reject(new Error(`${result.status}`))
332+
},
333+
})
334+
}).catch((err: Error) => err),
335+
),
333336
)
334337
335338
whenDefined(dialog.value, (dia) => {

src/api/payment-cart-key.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { APIRoute } from 'astro'
2-
import { whenNotError, whenNotErrorAll } from '@devprotocol/util-ts'
2+
import { isNotError, whenNotError, whenNotErrorAll } from '@devprotocol/util-ts'
33
import {
44
bytes32Hex,
55
type ClubsConfiguration,
@@ -12,6 +12,7 @@ import { verify } from '../utils/account'
1212
import { getCart } from '../db/cart'
1313
import { generateFulFillmentCartParamsId } from '../utils/gen-key'
1414
import { randomHash } from '../utils/hash'
15+
import { complete } from '../fixtures/fulfillment/cart'
1516

1617
/**
1718
* This endpoint is expected to be called with the following parameters:
@@ -137,5 +138,14 @@ export const getPaymentKeyByCart: ({
137138

138139
console.log({ options })
139140

140-
return callNRes(options)
141+
const [res] = await Promise.all([
142+
callNRes(options),
143+
isNotError(options) && options.gross_amount === 0
144+
? whenNotErrorAll([eoa, options], ([_eoa, { order_id }]) =>
145+
complete({ scope, eoa: _eoa, order_id, config }),
146+
)
147+
: Promise.resolve(),
148+
])
149+
150+
return res
141151
}

src/api/payment-key.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type { ComposedItem } from '../types'
1414
import {
1515
ErrorOr,
1616
isNotError,
17+
whenDefined,
1718
whenDefinedAll,
1819
whenNotError,
1920
whenNotErrorAll,
@@ -33,14 +34,15 @@ const { POP_SERVER_KEY, REDIS_URL, REDIS_USERNAME, REDIS_PASSWORD } =
3334
export const AUTH_STRING = Buffer.from(`${POP_SERVER_KEY}:`).toString('base64')
3435

3536
export type Success = {
36-
payment_key: string // '28GTzdVOZNeImaHMDeQF1319'
37-
result_code: string //'R000'
37+
payment_key?: string // '28GTzdVOZNeImaHMDeQF1319'
38+
result_code?: string //'R000'
3839
status: 'success'
39-
message: string //'"Payment Key" has been generated successfully'
40-
payment_key_expiry_time: string //'20200401000000'
40+
message?: string //'"Payment Key" has been generated successfully'
41+
payment_key_expiry_time?: string //'20200401000000'
4142
_clubs: {
4243
// Injected by CLUBS
4344
order_id: string // 'ORDER-<UUID>'
45+
gross_amount: number
4446
}
4547
}
4648

@@ -122,24 +124,36 @@ export type PaymentKeyOptions = {
122124
}
123125

124126
export const callNRes = async (options: ErrorOr<PaymentKeyOptions>) => {
125-
const paymentKey = await whenNotError(options, (opts) =>
126-
fetch('https://pay3.veritrans.co.jp/pop/v1/payment-key', {
127-
method: 'POST',
128-
headers: {
129-
'Content-Type': 'application/json; charset=utf-8',
130-
Authorization: `Basic ${AUTH_STRING}`,
131-
},
132-
body: JSON.stringify(opts),
133-
}).catch((err) => new Error(err)),
127+
const isFree = whenNotError(options, (opts) => opts.gross_amount === 0)
128+
const paymentKey = await whenNotErrorAll([options, isFree], ([opts, free]) =>
129+
free
130+
? undefined
131+
: fetch('https://pay3.veritrans.co.jp/pop/v1/payment-key', {
132+
method: 'POST',
133+
headers: {
134+
'Content-Type': 'application/json; charset=utf-8',
135+
Authorization: `Basic ${AUTH_STRING}`,
136+
},
137+
body: JSON.stringify(opts),
138+
}).catch((err) => new Error(err)),
134139
)
135140

136141
const result = await whenNotErrorAll(
137142
[paymentKey, options],
138143
([res, { order_id }]) =>
139-
res
140-
.json()
141-
.then((x) => ({ ...x, _clubs: { order_id } }) as Success)
142-
.catch((err) => new Error(err)),
144+
whenDefined(res, (_res) =>
145+
_res
146+
.json()
147+
.then(
148+
(x) =>
149+
({
150+
...x,
151+
_clubs: { order_id, gross_amount: x.gross_amount },
152+
}) as Success,
153+
)
154+
.catch((err) => new Error(err)),
155+
) ??
156+
({ status: 'success', _clubs: { order_id, gross_amount: 0 } } as Success),
143157
)
144158

145159
return result instanceof Error

0 commit comments

Comments
 (0)