@wtfalch/payments 0.1.0 → 0.2.0
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/dist/stripe.js +7 -0
- package/dist/types.d.ts +19 -1
- package/dist/vipps.js +20 -4
- package/package.json +1 -1
package/dist/stripe.js
CHANGED
|
@@ -160,6 +160,13 @@ export function createStripeProvider(options) {
|
|
|
160
160
|
};
|
|
161
161
|
},
|
|
162
162
|
async createRecurringAgreement(input) {
|
|
163
|
+
// Vipps-only: a SetupIntent has no pricing type or cap to declare up
|
|
164
|
+
// front -- it only saves a payment method, and the amount for each
|
|
165
|
+
// later charge is decided at `chargeRecurringAgreement` time. See the
|
|
166
|
+
// `variablePricing` doc comment on `CreateRecurringAgreementInput`.
|
|
167
|
+
if (input.variablePricing) {
|
|
168
|
+
throw new PaymentProviderError('stripe', 'variablePricing is not supported: a Stripe SetupIntent has no pricing type or cap to declare up front');
|
|
169
|
+
}
|
|
163
170
|
const si = await call('/setup_intents', {
|
|
164
171
|
usage: 'off_session',
|
|
165
172
|
'metadata[reference]': input.reference,
|
package/dist/types.d.ts
CHANGED
|
@@ -64,7 +64,10 @@ export interface CreateRecurringAgreementInput {
|
|
|
64
64
|
readonly reference: string;
|
|
65
65
|
/** The periodic charge amount. Stripe's SetupIntent does not itself need
|
|
66
66
|
* one, but it is required here for symmetry with Vipps and because a
|
|
67
|
-
* caller building the agreement already knows it.
|
|
67
|
+
* caller building the agreement already knows it. Under `variablePricing`,
|
|
68
|
+
* Vipps ignores this for the agreement itself (there is no fixed price to
|
|
69
|
+
* declare); it is still required, as an estimate for Stripe's metadata and
|
|
70
|
+
* for a caller that has not yet decided the actual per-charge amounts. */
|
|
68
71
|
readonly amount: Money;
|
|
69
72
|
readonly productName: string;
|
|
70
73
|
/** Where the payer returns after approving the agreement. */
|
|
@@ -76,6 +79,21 @@ export interface CreateRecurringAgreementInput {
|
|
|
76
79
|
readonly unit: 'day' | 'week' | 'month';
|
|
77
80
|
readonly count: number;
|
|
78
81
|
};
|
|
82
|
+
/** Vipps Recurring `pricing.type: 'VARIABLE'`: the agreement has no fixed
|
|
83
|
+
* price, only a `suggestedMaxAmount` shown to the payer when they approve
|
|
84
|
+
* it (the payer may accept a different max, and can change it later).
|
|
85
|
+
* Each `chargeRecurringAgreement` call then charges its own amount --
|
|
86
|
+
* e.g. a plan fee plus that month's metered usage -- as long as it is at
|
|
87
|
+
* or below the max the payer accepted; a charge above it is held `DUE`
|
|
88
|
+
* and fails if the payer has not raised their max by `due` + `retryDays`.
|
|
89
|
+
* Omit for the existing fixed-price ("LEGACY") behaviour, unchanged.
|
|
90
|
+
* Vipps-only: `createStripeProvider` throws `PaymentProviderError` if this
|
|
91
|
+
* is given, since a Stripe SetupIntent has no pricing type or cap to
|
|
92
|
+
* declare up front. Same currency as `amount`.
|
|
93
|
+
* https://developer.vippsmobilepay.com/api/recurring/ */
|
|
94
|
+
readonly variablePricing?: {
|
|
95
|
+
readonly suggestedMaxAmount: number;
|
|
96
|
+
};
|
|
79
97
|
readonly idempotencyKey?: string;
|
|
80
98
|
}
|
|
81
99
|
export interface RecurringAgreementResult {
|
package/dist/vipps.js
CHANGED
|
@@ -187,12 +187,21 @@ export function createVippsProvider(options) {
|
|
|
187
187
|
};
|
|
188
188
|
},
|
|
189
189
|
async createRecurringAgreement(input) {
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
// pricing.type LEGACY (fixed amount) vs VARIABLE (suggestedMaxAmount,
|
|
191
|
+
// no fixed amount): https://developer.vippsmobilepay.com/api/recurring/
|
|
192
|
+
const pricing = input.variablePricing
|
|
193
|
+
? {
|
|
194
|
+
type: 'VARIABLE',
|
|
195
|
+
currency: input.amount.currency.toUpperCase(),
|
|
196
|
+
suggestedMaxAmount: input.variablePricing.suggestedMaxAmount,
|
|
197
|
+
}
|
|
198
|
+
: {
|
|
192
199
|
type: 'LEGACY',
|
|
193
200
|
amount: input.amount.value,
|
|
194
201
|
currency: input.amount.currency.toUpperCase(),
|
|
195
|
-
}
|
|
202
|
+
};
|
|
203
|
+
const agreement = await post('/recurring/v3/agreements', {
|
|
204
|
+
pricing,
|
|
196
205
|
interval: {
|
|
197
206
|
unit: (input.interval?.unit ?? 'month').toUpperCase(),
|
|
198
207
|
count: input.interval?.count ?? 1,
|
|
@@ -212,9 +221,16 @@ export function createVippsProvider(options) {
|
|
|
212
221
|
};
|
|
213
222
|
},
|
|
214
223
|
async chargeRecurringAgreement(agreementReference, input) {
|
|
224
|
+
// No `currency` field here: the charge schema at
|
|
225
|
+
// https://developer.vippsmobilepay.com/api/recurring/ has no such
|
|
226
|
+
// property -- the charge always uses the agreement's own currency, so
|
|
227
|
+
// sending one was a mismatch with the documented request body (fixed
|
|
228
|
+
// here, not merely renamed). For a VARIABLE agreement, Vipps enforces
|
|
229
|
+
// amount <= the payer's accepted max itself: a charge above it is
|
|
230
|
+
// held `DUE`, not rejected synchronously here, so this adapter does
|
|
231
|
+
// not duplicate that check.
|
|
215
232
|
const charge = await post(`/recurring/v3/agreements/${agreementReference}/charges`, {
|
|
216
233
|
amount: input.amount.value,
|
|
217
|
-
currency: input.amount.currency.toUpperCase(),
|
|
218
234
|
transactionType: 'DIRECT_CAPTURE',
|
|
219
235
|
due: input.dueDate ?? tomorrowIsoDate(),
|
|
220
236
|
retryDays: 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wtfalch/payments",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "One PaymentProvider interface -- create a payment, capture, refund, set up and charge a recurring agreement, verify a webhook -- over Stripe and Vipps MobilePay. Holds no card data.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|