payment-kit 1.25.0 → 1.25.1

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.
@@ -255,10 +255,12 @@ export async function isDelegationSufficientForPayment(args: {
255
255
  const address = toDelegateAddress(delegator, wallet.address);
256
256
  const { state } = await client.getDelegateState({ address });
257
257
  if (!state) {
258
+ logger.error('isDelegationSufficientForPayment: no delegation state', { address, delegator });
258
259
  return { sufficient: false, reason: 'NO_DELEGATION' };
259
260
  }
260
261
 
261
262
  if (!state.ops || state.ops?.length === 0) {
263
+ logger.error('isDelegationSufficientForPayment: no delegation ops', { address, delegator });
262
264
  return { sufficient: false, reason: 'NO_DELEGATION' };
263
265
  }
264
266
 
@@ -1012,12 +1012,12 @@ export const handlePayment = async (job: PaymentJob) => {
1012
1012
  logger.error('PaymentIntent capture aborted - insufficient balance/delegation', {
1013
1013
  paymentIntentId: paymentIntent.id,
1014
1014
  invoiceId: paymentIntent.invoice_id,
1015
- failureReason: 'INSUFFICIENT_BALANCE',
1015
+ failureReason: result.reason,
1016
1016
  result,
1017
1017
  queueDelayMs,
1018
1018
  delaySeconds: Math.round(queueDelayMs / 1000),
1019
1019
  });
1020
- throw new CustomError('INSUFFICIENT_BALANCE', 'Payer balance or delegation not sufficient for this payment');
1020
+ throw new CustomError(result.reason, 'Payer balance or delegation not sufficient for this payment');
1021
1021
  }
1022
1022
 
1023
1023
  const signed = await client.signTransferV2Tx({
@@ -3,7 +3,7 @@ import { isRefundReasonSupportedByStripe } from '../libs/refund';
3
3
  import { checkRemainingStake, getSubscriptionStakeAddress } from '../libs/subscription';
4
4
  import { sendErc20ToUser } from '../integrations/ethereum/token';
5
5
  import { wallet } from '../libs/auth';
6
- import CustomError from '../libs/error';
6
+ import CustomError, { NonRetryableError } from '../libs/error';
7
7
  import { events } from '../libs/event';
8
8
  import logger from '../libs/logger';
9
9
  import { getGasPayerExtra, isBalanceSufficientForRefund } from '../libs/payment';
@@ -35,6 +35,21 @@ type Updates = {
35
35
  };
36
36
  };
37
37
 
38
+ const markRefundNonRetryable = async (refund: Refund, code: string, message: string, paymentMethod?: PaymentMethod) => {
39
+ await refund.update({
40
+ status: 'requires_action',
41
+ last_attempt_error: {
42
+ type: 'invalid_request_error',
43
+ code,
44
+ message,
45
+ payment_method_id: paymentMethod?.id,
46
+ payment_method_type: paymentMethod?.type,
47
+ },
48
+ attempt_count: refund.attempt_count + 1,
49
+ attempted: true,
50
+ });
51
+ };
52
+
38
53
  export const handleRefundFailed = (refund: Refund, error: PaymentError) => {
39
54
  const attemptCount = refund.attempt_count + 1;
40
55
  const updates: Updates = {
@@ -94,24 +109,27 @@ export const handleRefund = async (job: RefundJob) => {
94
109
  const paymentCurrency = await PaymentCurrency.findByPk(refund.currency_id);
95
110
  if (!paymentCurrency) {
96
111
  logger.warn(`PaymentCurrency not found: ${refund.currency_id}`);
112
+ await markRefundNonRetryable(refund, 'CURRENCY_NOT_FOUND', 'Payment currency not found');
97
113
  return;
98
114
  }
99
115
  const paymentMethod = await PaymentMethod.findByPk(paymentCurrency.payment_method_id);
100
116
  if (!paymentMethod) {
101
117
  logger.warn(`PaymentMethod not found: ${paymentCurrency.payment_method_id}`);
118
+ await markRefundNonRetryable(refund, 'PAYMENT_METHOD_NOT_FOUND', 'Payment method not found');
102
119
  return;
103
120
  }
104
121
 
105
122
  const customer = await Customer.findByPk(refund.customer_id);
106
123
  if (!customer) {
107
124
  logger.warn(`Customer not found: ${refund.customer_id}`);
125
+ await markRefundNonRetryable(refund, 'CUSTOMER_NOT_FOUND', 'Customer not found', paymentMethod);
108
126
  return;
109
127
  }
110
128
 
111
129
  if (refund?.type === 'stake_return') {
112
- handleStakeReturnJob(job, refund, paymentCurrency, paymentMethod, customer);
130
+ await handleStakeReturnJob(job, refund, paymentCurrency, paymentMethod, customer);
113
131
  } else if (paymentMethod) {
114
- handleRefundJob(job, refund, paymentCurrency, paymentMethod, customer);
132
+ await handleRefundJob(job, refund, paymentCurrency, paymentMethod, customer);
115
133
  }
116
134
  };
117
135
 
@@ -164,18 +182,26 @@ const handleRefundJob = async (
164
182
  const refundSupport = ['arcblock', 'ethereum', 'stripe', 'base'].includes(paymentMethod.type);
165
183
  if (refundSupport === false) {
166
184
  logger.warn(`PaymentMethod does not support auto charge: ${paymentCurrency.payment_method_id}`);
185
+ await markRefundNonRetryable(
186
+ refund,
187
+ 'PAYMENT_METHOD_NOT_SUPPORTED',
188
+ 'Payment method does not support refund',
189
+ paymentMethod
190
+ );
167
191
  return;
168
192
  }
169
193
 
170
194
  // try refund transfer and reschedule on error
171
195
  logger.info('Refund transfer attempt', { id: refund.id, attempt: refund.attempt_count });
172
- let result;
173
- const paymentIntent = await PaymentIntent.findByPk(refund.payment_intent_id);
174
- if (!paymentIntent) {
175
- throw new Error('PaymentIntent not found');
176
- }
177
-
178
196
  try {
197
+ if (!refund.payment_intent_id) {
198
+ throw new NonRetryableError('PAYMENT_INTENT_NOT_FOUND', 'payment_intent_id is missing for refund');
199
+ }
200
+ const paymentIntent = await PaymentIntent.findByPk(refund.payment_intent_id);
201
+ if (!paymentIntent) {
202
+ throw new NonRetryableError('PAYMENT_INTENT_NOT_FOUND', 'PaymentIntent not found');
203
+ }
204
+ let result;
179
205
  if (paymentMethod.type === 'arcblock') {
180
206
  const client = paymentMethod.getOcapClient();
181
207
  // check balance before transfer with transaction
@@ -288,6 +314,12 @@ const handleRefundJob = async (
288
314
  } catch (err) {
289
315
  logger.error('refund transfer failed', { error: err, id: refund.id });
290
316
 
317
+ if (err instanceof NonRetryableError || err?.nonRetryable === true) {
318
+ await markRefundNonRetryable(refund, err.code, err.message, paymentMethod);
319
+ logger.error('refund transfer aborted: non-retryable error', { id: refund.id, code: err.code });
320
+ return;
321
+ }
322
+
291
323
  const error: PaymentError = {
292
324
  type: 'card_error',
293
325
  code: err.code,
package/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.25.0
17
+ version: 1.25.1
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.25.0",
3
+ "version": "1.25.1",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "prelint": "npm run types",
@@ -59,9 +59,9 @@
59
59
  "@blocklet/error": "^0.3.5",
60
60
  "@blocklet/js-sdk": "^1.17.8-beta-20260104-120132-cb5b1914",
61
61
  "@blocklet/logger": "^1.17.8-beta-20260104-120132-cb5b1914",
62
- "@blocklet/payment-broker-client": "1.25.0",
63
- "@blocklet/payment-react": "1.25.0",
64
- "@blocklet/payment-vendor": "1.25.0",
62
+ "@blocklet/payment-broker-client": "1.25.1",
63
+ "@blocklet/payment-react": "1.25.1",
64
+ "@blocklet/payment-vendor": "1.25.1",
65
65
  "@blocklet/sdk": "^1.17.8-beta-20260104-120132-cb5b1914",
66
66
  "@blocklet/ui-react": "^3.4.7",
67
67
  "@blocklet/uploader": "^0.3.19",
@@ -132,7 +132,7 @@
132
132
  "devDependencies": {
133
133
  "@abtnode/types": "^1.17.8-beta-20260104-120132-cb5b1914",
134
134
  "@arcblock/eslint-config-ts": "^0.3.3",
135
- "@blocklet/payment-types": "1.25.0",
135
+ "@blocklet/payment-types": "1.25.1",
136
136
  "@types/cookie-parser": "^1.4.9",
137
137
  "@types/cors": "^2.8.19",
138
138
  "@types/debug": "^4.1.12",
@@ -179,5 +179,5 @@
179
179
  "parser": "typescript"
180
180
  }
181
181
  },
182
- "gitHead": "00a94943fea21487c042a7b484f4649add502bc9"
182
+ "gitHead": "87555132c62024e5c677fd0a39df0d90be06a543"
183
183
  }