@profullstack/coinpay 0.6.3 → 0.6.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/package.json +5 -1
- package/src/card-payments.js +298 -0
- package/src/client.js +163 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/coinpay",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "CoinPay SDK & CLI — Accept cryptocurrency payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet and swap support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"import": "./src/payments.js",
|
|
18
18
|
"types": "./src/payments.d.ts"
|
|
19
19
|
},
|
|
20
|
+
"./card-payments": {
|
|
21
|
+
"import": "./src/card-payments.js",
|
|
22
|
+
"types": "./src/card-payments.d.ts"
|
|
23
|
+
},
|
|
20
24
|
"./webhooks": {
|
|
21
25
|
"import": "./src/webhooks.js",
|
|
22
26
|
"types": "./src/webhooks.d.ts"
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CoinPay Card Payments - Convenience functions for Stripe integration
|
|
3
|
+
*
|
|
4
|
+
* This module provides high-level convenience functions for working with
|
|
5
|
+
* card payments through Stripe Connect, similar to the payments.js module.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Quick card payment creation with sensible defaults
|
|
10
|
+
*
|
|
11
|
+
* @param {import('./client.js').CoinPayClient} client - CoinPay client instance
|
|
12
|
+
* @param {string} businessId - Business ID
|
|
13
|
+
* @param {number} amountUSD - Amount in USD (will be converted to cents)
|
|
14
|
+
* @param {string} description - Payment description
|
|
15
|
+
* @param {Object} [options] - Additional options
|
|
16
|
+
* @param {Object} [options.metadata] - Custom metadata
|
|
17
|
+
* @param {string} [options.successUrl] - Success redirect URL
|
|
18
|
+
* @param {string} [options.cancelUrl] - Cancel redirect URL
|
|
19
|
+
* @param {boolean} [options.escrowMode=false] - Enable escrow mode
|
|
20
|
+
* @returns {Promise<Object>} Payment session with checkout URL
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* import { createQuickCardPayment } from '@profullstack/coinpay/card-payments';
|
|
24
|
+
*
|
|
25
|
+
* const payment = await createQuickCardPayment(client, 'business-id', 50, 'Order #123', {
|
|
26
|
+
* metadata: { orderId: '123' },
|
|
27
|
+
* escrowMode: true
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Redirect customer to: payment.checkout_url
|
|
31
|
+
*/
|
|
32
|
+
export async function createQuickCardPayment(client, businessId, amountUSD, description, options = {}) {
|
|
33
|
+
const {
|
|
34
|
+
metadata = {},
|
|
35
|
+
successUrl,
|
|
36
|
+
cancelUrl,
|
|
37
|
+
escrowMode = false,
|
|
38
|
+
} = options;
|
|
39
|
+
|
|
40
|
+
// Convert USD to cents
|
|
41
|
+
const amountCents = Math.round(amountUSD * 100);
|
|
42
|
+
|
|
43
|
+
return client.createCardPayment({
|
|
44
|
+
businessId,
|
|
45
|
+
amount: amountCents,
|
|
46
|
+
currency: 'usd',
|
|
47
|
+
description,
|
|
48
|
+
metadata,
|
|
49
|
+
successUrl,
|
|
50
|
+
cancelUrl,
|
|
51
|
+
escrowMode,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Wait for merchant to complete Stripe onboarding
|
|
57
|
+
*
|
|
58
|
+
* Polls the Stripe account status until onboarding is complete.
|
|
59
|
+
* Useful for integration flows where you need to wait for merchant setup.
|
|
60
|
+
*
|
|
61
|
+
* @param {import('./client.js').CoinPayClient} client - CoinPay client instance
|
|
62
|
+
* @param {string} businessId - Business ID
|
|
63
|
+
* @param {Object} [options] - Polling options
|
|
64
|
+
* @param {number} [options.intervalMs=5000] - Polling interval in ms
|
|
65
|
+
* @param {number} [options.timeoutMs=300000] - Timeout in ms (default: 5 minutes)
|
|
66
|
+
* @param {Function} [options.onStatusChange] - Callback for status changes
|
|
67
|
+
* @returns {Promise<Object>} Final account status when onboarding complete
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* const accountStatus = await waitForStripeOnboarding(client, 'business-id', {
|
|
71
|
+
* onStatusChange: (status) => {
|
|
72
|
+
* console.log(`Onboarding status: ${JSON.stringify(status)}`);
|
|
73
|
+
* }
|
|
74
|
+
* });
|
|
75
|
+
*/
|
|
76
|
+
export async function waitForStripeOnboarding(client, businessId, options = {}) {
|
|
77
|
+
const {
|
|
78
|
+
intervalMs = 5000,
|
|
79
|
+
timeoutMs = 300000, // 5 minutes
|
|
80
|
+
onStatusChange,
|
|
81
|
+
} = options;
|
|
82
|
+
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
|
|
85
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
86
|
+
const status = await client.getStripeAccountStatus(businessId);
|
|
87
|
+
|
|
88
|
+
if (onStatusChange) {
|
|
89
|
+
onStatusChange(status);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (status.onboarding_complete) {
|
|
93
|
+
return status;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Wait before next poll
|
|
97
|
+
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw new Error(`Stripe onboarding timeout after ${timeoutMs}ms`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Create payment with automatic merchant onboarding check
|
|
105
|
+
*
|
|
106
|
+
* Checks if merchant has completed Stripe onboarding first, and provides
|
|
107
|
+
* helpful error messages if not. Prevents failed payment attempts.
|
|
108
|
+
*
|
|
109
|
+
* @param {import('./client.js').CoinPayClient} client - CoinPay client instance
|
|
110
|
+
* @param {Object} params - Payment parameters (same as createCardPayment)
|
|
111
|
+
* @returns {Promise<Object>} Payment session or onboarding info if incomplete
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* const result = await createCardPaymentWithOnboardingCheck(client, {
|
|
115
|
+
* businessId: 'business-id',
|
|
116
|
+
* amount: 5000,
|
|
117
|
+
* description: 'Order #123'
|
|
118
|
+
* });
|
|
119
|
+
*
|
|
120
|
+
* if (result.requires_onboarding) {
|
|
121
|
+
* // Redirect merchant to result.onboarding_url
|
|
122
|
+
* } else {
|
|
123
|
+
* // Redirect customer to result.checkout_url
|
|
124
|
+
* }
|
|
125
|
+
*/
|
|
126
|
+
export async function createCardPaymentWithOnboardingCheck(client, params) {
|
|
127
|
+
try {
|
|
128
|
+
// Check onboarding status first
|
|
129
|
+
const status = await client.getStripeAccountStatus(params.businessId);
|
|
130
|
+
|
|
131
|
+
if (!status.onboarding_complete) {
|
|
132
|
+
// Generate onboarding link if needed
|
|
133
|
+
const onboarding = await client.createStripeOnboardingLink(params.businessId);
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
requires_onboarding: true,
|
|
137
|
+
onboarding_url: onboarding.onboarding_url,
|
|
138
|
+
status: status,
|
|
139
|
+
message: 'Merchant must complete Stripe onboarding before accepting card payments',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Onboarding complete, create payment
|
|
144
|
+
const payment = await client.createCardPayment(params);
|
|
145
|
+
return {
|
|
146
|
+
requires_onboarding: false,
|
|
147
|
+
...payment,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (error.status === 404) {
|
|
152
|
+
// No Stripe account exists, need onboarding
|
|
153
|
+
const onboarding = await client.createStripeOnboardingLink(params.businessId);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
requires_onboarding: true,
|
|
157
|
+
onboarding_url: onboarding.onboarding_url,
|
|
158
|
+
status: null,
|
|
159
|
+
message: 'Merchant needs to complete Stripe onboarding',
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get payment method support status
|
|
168
|
+
*
|
|
169
|
+
* Returns which payment methods are available for a merchant.
|
|
170
|
+
* Helps with conditional UI rendering.
|
|
171
|
+
*
|
|
172
|
+
* @param {import('./client.js').CoinPayClient} client - CoinPay client instance
|
|
173
|
+
* @param {string} businessId - Business ID
|
|
174
|
+
* @returns {Promise<Object>} Available payment methods
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* const support = await getPaymentMethodSupport(client, 'business-id');
|
|
178
|
+
* console.log(support);
|
|
179
|
+
* // {
|
|
180
|
+
* // crypto: true,
|
|
181
|
+
* // cards: true,
|
|
182
|
+
* // escrow: true,
|
|
183
|
+
* // stripe_onboarding_complete: true
|
|
184
|
+
* // }
|
|
185
|
+
*/
|
|
186
|
+
export async function getPaymentMethodSupport(client, businessId) {
|
|
187
|
+
try {
|
|
188
|
+
// Check if business exists (crypto payments always work)
|
|
189
|
+
await client.getBusiness(businessId);
|
|
190
|
+
|
|
191
|
+
let cardSupport = false;
|
|
192
|
+
let stripeOnboardingComplete = false;
|
|
193
|
+
|
|
194
|
+
// Check Stripe status
|
|
195
|
+
try {
|
|
196
|
+
const stripeStatus = await client.getStripeAccountStatus(businessId);
|
|
197
|
+
cardSupport = stripeStatus.onboarding_complete;
|
|
198
|
+
stripeOnboardingComplete = stripeStatus.onboarding_complete;
|
|
199
|
+
} catch (error) {
|
|
200
|
+
// No Stripe account = no card support yet
|
|
201
|
+
cardSupport = false;
|
|
202
|
+
stripeOnboardingComplete = false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
crypto: true, // Always available
|
|
207
|
+
cards: cardSupport,
|
|
208
|
+
escrow: cardSupport, // Card escrow requires Stripe
|
|
209
|
+
stripe_onboarding_complete: stripeOnboardingComplete,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
} catch (error) {
|
|
213
|
+
if (error.status === 404) {
|
|
214
|
+
return {
|
|
215
|
+
crypto: false,
|
|
216
|
+
cards: false,
|
|
217
|
+
escrow: false,
|
|
218
|
+
stripe_onboarding_complete: false,
|
|
219
|
+
error: 'Business not found',
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Format amount for display
|
|
228
|
+
*
|
|
229
|
+
* Converts cents to dollar amount with proper formatting.
|
|
230
|
+
*
|
|
231
|
+
* @param {number} amountCents - Amount in cents
|
|
232
|
+
* @param {string} [currency='USD'] - Currency code
|
|
233
|
+
* @returns {string} Formatted amount string
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* formatCardAmount(5000); // "$50.00"
|
|
237
|
+
* formatCardAmount(5050); // "$50.50"
|
|
238
|
+
* formatCardAmount(500, 'EUR'); // "€5.00"
|
|
239
|
+
*/
|
|
240
|
+
export function formatCardAmount(amountCents, currency = 'USD') {
|
|
241
|
+
const amount = amountCents / 100;
|
|
242
|
+
|
|
243
|
+
const formatters = {
|
|
244
|
+
USD: (amt) => `$${amt.toFixed(2)}`,
|
|
245
|
+
EUR: (amt) => `€${amt.toFixed(2)}`,
|
|
246
|
+
GBP: (amt) => `£${amt.toFixed(2)}`,
|
|
247
|
+
CAD: (amt) => `C$${amt.toFixed(2)}`,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const formatter = formatters[currency.toUpperCase()];
|
|
251
|
+
if (formatter) {
|
|
252
|
+
return formatter(amount);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Fallback for unknown currencies
|
|
256
|
+
return `${amount.toFixed(2)} ${currency.toUpperCase()}`;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Calculate platform fees for card payments
|
|
261
|
+
*
|
|
262
|
+
* @param {number} amountCents - Payment amount in cents
|
|
263
|
+
* @param {string} tier - Merchant tier ('free' or 'pro')
|
|
264
|
+
* @returns {Object} Fee breakdown
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* const fees = calculateCardPaymentFees(5000, 'free');
|
|
268
|
+
* console.log(fees);
|
|
269
|
+
* // {
|
|
270
|
+
* // amount: 5000,
|
|
271
|
+
* // platformFee: 50,
|
|
272
|
+
* // platformFeePercent: 1,
|
|
273
|
+
* // merchantReceives: 4950 // before Stripe fees
|
|
274
|
+
* // }
|
|
275
|
+
*/
|
|
276
|
+
export function calculateCardPaymentFees(amountCents, tier = 'free') {
|
|
277
|
+
const platformFeePercent = tier === 'pro' ? 0.5 : 1.0; // 0.5% or 1%
|
|
278
|
+
const platformFeeCents = Math.round(amountCents * (platformFeePercent / 100));
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
amount: amountCents,
|
|
282
|
+
platformFee: platformFeeCents,
|
|
283
|
+
platformFeePercent,
|
|
284
|
+
merchantReceives: amountCents - platformFeeCents, // Before Stripe processing fees
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Default export with all convenience functions
|
|
290
|
+
*/
|
|
291
|
+
export default {
|
|
292
|
+
createQuickCardPayment,
|
|
293
|
+
waitForStripeOnboarding,
|
|
294
|
+
createCardPaymentWithOnboardingCheck,
|
|
295
|
+
getPaymentMethodSupport,
|
|
296
|
+
formatCardAmount,
|
|
297
|
+
calculateCardPaymentFees,
|
|
298
|
+
};
|
package/src/client.js
CHANGED
|
@@ -522,6 +522,169 @@ export class CoinPayClient {
|
|
|
522
522
|
const { authenticateEscrow } = await import('./escrow.js');
|
|
523
523
|
return authenticateEscrow(this, escrowId, token);
|
|
524
524
|
}
|
|
525
|
+
|
|
526
|
+
// ── Stripe Card Payment Methods ────────────────────────
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Create a card payment using Stripe
|
|
530
|
+
*
|
|
531
|
+
* Creates a card payment session through Stripe Connect. Returns a checkout URL
|
|
532
|
+
* that customers can use to pay with their credit/debit card.
|
|
533
|
+
*
|
|
534
|
+
* @param {Object} params - Payment parameters
|
|
535
|
+
* @param {string} params.businessId - Business ID (merchant must have completed Stripe onboarding)
|
|
536
|
+
* @param {number} params.amount - Amount in cents (e.g., 5000 = $50.00)
|
|
537
|
+
* @param {string} [params.currency='usd'] - Currency code (usd, eur, etc.)
|
|
538
|
+
* @param {string} [params.description] - Payment description
|
|
539
|
+
* @param {Object} [params.metadata] - Custom metadata
|
|
540
|
+
* @param {string} [params.successUrl] - URL to redirect on successful payment
|
|
541
|
+
* @param {string} [params.cancelUrl] - URL to redirect on payment cancellation
|
|
542
|
+
* @param {boolean} [params.escrowMode=false] - Whether to use escrow mode (holds funds until release)
|
|
543
|
+
* @returns {Promise<Object>} Payment session with checkout URL
|
|
544
|
+
*
|
|
545
|
+
* @example
|
|
546
|
+
* // Create a $50 card payment
|
|
547
|
+
* const payment = await client.createCardPayment({
|
|
548
|
+
* businessId: 'your-business-id',
|
|
549
|
+
* amount: 5000, // $50.00 in cents
|
|
550
|
+
* currency: 'usd',
|
|
551
|
+
* description: 'Order #12345',
|
|
552
|
+
* metadata: { orderId: '12345' },
|
|
553
|
+
* successUrl: 'https://yourdomain.com/success',
|
|
554
|
+
* cancelUrl: 'https://yourdomain.com/cancel'
|
|
555
|
+
* });
|
|
556
|
+
*
|
|
557
|
+
* // Redirect customer to payment.checkout_url
|
|
558
|
+
*/
|
|
559
|
+
async createCardPayment({
|
|
560
|
+
businessId,
|
|
561
|
+
amount,
|
|
562
|
+
currency = 'usd',
|
|
563
|
+
description,
|
|
564
|
+
metadata,
|
|
565
|
+
successUrl,
|
|
566
|
+
cancelUrl,
|
|
567
|
+
escrowMode = false
|
|
568
|
+
}) {
|
|
569
|
+
return this.request('/stripe/payments/create', {
|
|
570
|
+
method: 'POST',
|
|
571
|
+
body: JSON.stringify({
|
|
572
|
+
businessId,
|
|
573
|
+
amount,
|
|
574
|
+
currency,
|
|
575
|
+
description,
|
|
576
|
+
metadata,
|
|
577
|
+
successUrl,
|
|
578
|
+
cancelUrl,
|
|
579
|
+
escrowMode
|
|
580
|
+
}),
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Get Stripe account onboarding status
|
|
586
|
+
*
|
|
587
|
+
* Checks whether a merchant has completed Stripe Connect onboarding
|
|
588
|
+
* and is able to accept card payments.
|
|
589
|
+
*
|
|
590
|
+
* @param {string} businessId - Business ID
|
|
591
|
+
* @returns {Promise<Object>} Account status and capabilities
|
|
592
|
+
*
|
|
593
|
+
* @example
|
|
594
|
+
* const status = await client.getStripeAccountStatus('business-id');
|
|
595
|
+
* if (status.onboarding_complete) {
|
|
596
|
+
* console.log('Merchant can accept card payments');
|
|
597
|
+
* }
|
|
598
|
+
*/
|
|
599
|
+
async getStripeAccountStatus(businessId) {
|
|
600
|
+
return this.request(`/stripe/connect/status/${businessId}`);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Create Stripe Connect onboarding link
|
|
605
|
+
*
|
|
606
|
+
* Generates a Stripe Express onboarding link for a merchant.
|
|
607
|
+
* The merchant must complete this onboarding before they can accept card payments.
|
|
608
|
+
*
|
|
609
|
+
* @param {string} businessId - Business ID
|
|
610
|
+
* @param {Object} [params] - Optional parameters
|
|
611
|
+
* @param {string} [params.email] - Merchant email (pre-fills onboarding form)
|
|
612
|
+
* @param {string} [params.country='US'] - Country code (US, CA, GB, etc.)
|
|
613
|
+
* @returns {Promise<Object>} Onboarding link and account ID
|
|
614
|
+
*
|
|
615
|
+
* @example
|
|
616
|
+
* const onboarding = await client.createStripeOnboardingLink('business-id', {
|
|
617
|
+
* email: 'merchant@example.com',
|
|
618
|
+
* country: 'US'
|
|
619
|
+
* });
|
|
620
|
+
*
|
|
621
|
+
* // Redirect merchant to onboarding.onboarding_url
|
|
622
|
+
*/
|
|
623
|
+
async createStripeOnboardingLink(businessId, params = {}) {
|
|
624
|
+
return this.request('/stripe/connect/onboard', {
|
|
625
|
+
method: 'POST',
|
|
626
|
+
body: JSON.stringify({
|
|
627
|
+
businessId,
|
|
628
|
+
...params
|
|
629
|
+
}),
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Release card escrow funds to merchant
|
|
635
|
+
*
|
|
636
|
+
* Releases funds held in card escrow mode to the merchant's Stripe account.
|
|
637
|
+
* Only works for payments created with escrowMode: true.
|
|
638
|
+
*
|
|
639
|
+
* @param {string} escrowId - Escrow ID (returned from escrow payment creation)
|
|
640
|
+
* @param {string} [reason] - Reason for release
|
|
641
|
+
* @returns {Promise<Object>} Release confirmation with transfer details
|
|
642
|
+
*
|
|
643
|
+
* @example
|
|
644
|
+
* const release = await client.releaseCardEscrow('escrow-id', 'Work completed');
|
|
645
|
+
* console.log(`Released $${release.amount_transferred / 100} to merchant`);
|
|
646
|
+
*/
|
|
647
|
+
async releaseCardEscrow(escrowId, reason) {
|
|
648
|
+
return this.request('/stripe/escrow/release', {
|
|
649
|
+
method: 'POST',
|
|
650
|
+
body: JSON.stringify({
|
|
651
|
+
escrowId,
|
|
652
|
+
reason
|
|
653
|
+
}),
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Refund a card payment
|
|
659
|
+
*
|
|
660
|
+
* Creates a refund for a card payment. Works for both gateway and escrow mode payments.
|
|
661
|
+
* For escrow payments, refunds from held funds. For gateway payments, refunds from merchant account.
|
|
662
|
+
*
|
|
663
|
+
* @param {string} paymentId - Payment intent ID or escrow ID
|
|
664
|
+
* @param {Object} [params] - Optional parameters
|
|
665
|
+
* @param {number} [params.amount] - Refund amount in cents (partial refund). Omit for full refund.
|
|
666
|
+
* @param {string} [params.reason] - Reason for refund
|
|
667
|
+
* @returns {Promise<Object>} Refund confirmation
|
|
668
|
+
*
|
|
669
|
+
* @example
|
|
670
|
+
* // Full refund
|
|
671
|
+
* const refund = await client.refundCardPayment('payment-id');
|
|
672
|
+
*
|
|
673
|
+
* // Partial refund
|
|
674
|
+
* const partialRefund = await client.refundCardPayment('payment-id', {
|
|
675
|
+
* amount: 2500, // $25.00 refund
|
|
676
|
+
* reason: 'Customer complaint'
|
|
677
|
+
* });
|
|
678
|
+
*/
|
|
679
|
+
async refundCardPayment(paymentId, params = {}) {
|
|
680
|
+
return this.request('/stripe/escrow/refund', {
|
|
681
|
+
method: 'POST',
|
|
682
|
+
body: JSON.stringify({
|
|
683
|
+
escrowId: paymentId, // API expects escrowId param
|
|
684
|
+
...params
|
|
685
|
+
}),
|
|
686
|
+
});
|
|
687
|
+
}
|
|
525
688
|
}
|
|
526
689
|
|
|
527
690
|
export default CoinPayClient;
|