convex-flutterwave 0.0.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.
- package/LICENSE +201 -0
- package/README.md +504 -0
- package/dist/client/_generated/_ignore.d.ts +1 -0
- package/dist/client/_generated/_ignore.d.ts.map +1 -0
- package/dist/client/_generated/_ignore.js +3 -0
- package/dist/client/_generated/_ignore.js.map +1 -0
- package/dist/client/index.d.ts +192 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +364 -0
- package/dist/client/index.js.map +1 -0
- package/dist/component/_generated/api.d.ts +34 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +141 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +133 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +80 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +4 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/lib.d.ts +117 -0
- package/dist/component/lib.d.ts.map +1 -0
- package/dist/component/lib.js +223 -0
- package/dist/component/lib.js.map +1 -0
- package/dist/component/schema.d.ts +73 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +43 -0
- package/dist/component/schema.js.map +1 -0
- package/package.json +106 -0
- package/src/client/_generated/_ignore.ts +1 -0
- package/src/client/index.ts +565 -0
- package/src/client/setup.test.ts +26 -0
- package/src/component/_generated/api.ts +50 -0
- package/src/component/_generated/component.ts +183 -0
- package/src/component/_generated/dataModel.ts +60 -0
- package/src/component/_generated/server.ts +169 -0
- package/src/component/convex.config.ts +5 -0
- package/src/component/lib.test.ts +110 -0
- package/src/component/lib.ts +251 -0
- package/src/component/schema.ts +50 -0
- package/src/component/setup.test.ts +11 -0
- package/src/test.ts +18 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { httpActionGeneric } from "convex/server";
|
|
2
|
+
import type { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
3
|
+
import type { ComponentApi } from "../component/_generated/component.js";
|
|
4
|
+
export type FlutterwaveOptions = {
|
|
5
|
+
secretKey: string;
|
|
6
|
+
webhookSecretHash: string;
|
|
7
|
+
};
|
|
8
|
+
export type FlutterwavePaymentOption = "card" | "account" | "banktransfer" | "ussd" | "nqr" | "mpesa" | "mobilemoneyghana" | "mobilemoneyuganda" | "mobilemoneyrwanda" | "mobilemoneyzambia" | "barter" | "credit" | "opay" | "fawrypay";
|
|
9
|
+
export type InitializeTransactionArgs = {
|
|
10
|
+
email: string;
|
|
11
|
+
amount: number;
|
|
12
|
+
currency?: string;
|
|
13
|
+
redirectUrl: string;
|
|
14
|
+
txRef?: string;
|
|
15
|
+
customerName?: string;
|
|
16
|
+
customerPhoneNumber?: string;
|
|
17
|
+
/** Restricts which payment methods Flutterwave's hosted page offers. Omit to offer everything enabled on your account. */
|
|
18
|
+
paymentOptions?: FlutterwavePaymentOption[];
|
|
19
|
+
/** Links this checkout to a payment plan, turning it into a subscription. See createPaymentPlan(). */
|
|
20
|
+
paymentPlan?: string;
|
|
21
|
+
metadata?: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
export type InitializeTransactionResult = {
|
|
24
|
+
paymentLink: string;
|
|
25
|
+
txRef: string;
|
|
26
|
+
};
|
|
27
|
+
export type VerifyTransactionResult = {
|
|
28
|
+
status: string;
|
|
29
|
+
txRef: string;
|
|
30
|
+
flwRef?: string;
|
|
31
|
+
transactionId: string;
|
|
32
|
+
amount: number;
|
|
33
|
+
currency: string;
|
|
34
|
+
paymentType?: string;
|
|
35
|
+
narration?: string;
|
|
36
|
+
paidAt?: number;
|
|
37
|
+
customerEmail: string;
|
|
38
|
+
};
|
|
39
|
+
export type CreatePaymentPlanArgs = {
|
|
40
|
+
name: string;
|
|
41
|
+
amount: number;
|
|
42
|
+
interval: "hourly" | "daily" | "weekly" | "monthly" | "quarterly" | "yearly" | "bi-annually";
|
|
43
|
+
currency?: string;
|
|
44
|
+
duration?: number;
|
|
45
|
+
};
|
|
46
|
+
export type PaymentPlanResult = {
|
|
47
|
+
planId: string;
|
|
48
|
+
name: string;
|
|
49
|
+
amount: number;
|
|
50
|
+
interval: string;
|
|
51
|
+
currency: string;
|
|
52
|
+
duration?: number;
|
|
53
|
+
status: string;
|
|
54
|
+
};
|
|
55
|
+
export declare class Flutterwave {
|
|
56
|
+
private component;
|
|
57
|
+
private options;
|
|
58
|
+
webhookHandler: ReturnType<typeof httpActionGeneric>;
|
|
59
|
+
constructor(component: ComponentApi, options: FlutterwaveOptions);
|
|
60
|
+
initializeTransaction(ctx: GenericActionCtx<GenericDataModel>, args: InitializeTransactionArgs): Promise<InitializeTransactionResult>;
|
|
61
|
+
verifyTransaction(ctx: GenericActionCtx<GenericDataModel>, args: {
|
|
62
|
+
transactionId: string;
|
|
63
|
+
}): Promise<VerifyTransactionResult>;
|
|
64
|
+
cancelSubscription(ctx: GenericActionCtx<GenericDataModel>, args: {
|
|
65
|
+
subscriptionId: string;
|
|
66
|
+
customerEmail: string;
|
|
67
|
+
}): Promise<void>;
|
|
68
|
+
enableSubscription(ctx: GenericActionCtx<GenericDataModel>, args: {
|
|
69
|
+
subscriptionId: string;
|
|
70
|
+
customerEmail: string;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
createPaymentPlan(ctx: GenericActionCtx<GenericDataModel>, args: CreatePaymentPlanArgs): Promise<PaymentPlanResult>;
|
|
73
|
+
listPaymentPlans(_ctx: GenericActionCtx<GenericDataModel>): Promise<PaymentPlanResult[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Flutterwave has no "subscription created" webhook — a subscription is
|
|
76
|
+
* created implicitly the first time a customer pays through a checkout
|
|
77
|
+
* initialized with `paymentPlan`, and that charge webhook doesn't carry
|
|
78
|
+
* the subscription's own id (only the plan id). This reads the customer's
|
|
79
|
+
* subscriptions straight from Flutterwave's Subscriptions API and upserts
|
|
80
|
+
* them locally — call it after a plan-linked checkout returns, or from a
|
|
81
|
+
* manual "sync" action, as a reliable way to populate subscription state.
|
|
82
|
+
*/
|
|
83
|
+
private fetchFlutterwaveSubscriptions;
|
|
84
|
+
syncCustomerSubscriptions(ctx: GenericActionCtx<GenericDataModel>, args: {
|
|
85
|
+
email: string;
|
|
86
|
+
}): Promise<number>;
|
|
87
|
+
/**
|
|
88
|
+
* Attributes every subscription on a given plan to one email, regardless
|
|
89
|
+
* of what Flutterwave itself has on file as that subscription's customer.
|
|
90
|
+
* This is unsafe to reach for by default — a real plan can have many
|
|
91
|
+
* subscribers — but it's exactly what's needed when Flutterwave's
|
|
92
|
+
* test-mode sandbox has substituted its own fixed customer identity for
|
|
93
|
+
* every subscription (see the README's Subscriptions section), making
|
|
94
|
+
* email-based sync unable to find anything at all. Reach for it only
|
|
95
|
+
* where you already know (or, in a single-developer test/demo context,
|
|
96
|
+
* can safely assume) there's one subscriber to claim — the example app
|
|
97
|
+
* uses it as a fallback for exactly that reason.
|
|
98
|
+
*/
|
|
99
|
+
syncSubscriptionsByPlan(ctx: GenericActionCtx<GenericDataModel>, args: {
|
|
100
|
+
planId: string;
|
|
101
|
+
email: string;
|
|
102
|
+
}): Promise<number>;
|
|
103
|
+
getTransaction(ctx: RunQueryCtx, args: {
|
|
104
|
+
txRef: string;
|
|
105
|
+
}): Promise<{
|
|
106
|
+
_creationTime: number;
|
|
107
|
+
_id: string;
|
|
108
|
+
amount: number;
|
|
109
|
+
createdAt: number;
|
|
110
|
+
currency: string;
|
|
111
|
+
customerEmail: string;
|
|
112
|
+
flwRef?: string;
|
|
113
|
+
metadata?: string;
|
|
114
|
+
narration?: string;
|
|
115
|
+
paidAt?: number;
|
|
116
|
+
paymentType?: string;
|
|
117
|
+
status: "pending" | "successful" | "failed" | "cancelled";
|
|
118
|
+
transactionId?: string;
|
|
119
|
+
txRef: string;
|
|
120
|
+
updatedAt: number;
|
|
121
|
+
} | null>;
|
|
122
|
+
listTransactions(ctx: RunQueryCtx, args: {
|
|
123
|
+
customerEmail: string;
|
|
124
|
+
limit?: number;
|
|
125
|
+
}): Promise<{
|
|
126
|
+
_creationTime: number;
|
|
127
|
+
_id: string;
|
|
128
|
+
amount: number;
|
|
129
|
+
createdAt: number;
|
|
130
|
+
currency: string;
|
|
131
|
+
customerEmail: string;
|
|
132
|
+
flwRef?: string;
|
|
133
|
+
metadata?: string;
|
|
134
|
+
narration?: string;
|
|
135
|
+
paidAt?: number;
|
|
136
|
+
paymentType?: string;
|
|
137
|
+
status: "pending" | "successful" | "failed" | "cancelled";
|
|
138
|
+
transactionId?: string;
|
|
139
|
+
txRef: string;
|
|
140
|
+
updatedAt: number;
|
|
141
|
+
}[]>;
|
|
142
|
+
getSubscription(ctx: RunQueryCtx, args: {
|
|
143
|
+
subscriptionId: string;
|
|
144
|
+
}): Promise<{
|
|
145
|
+
_creationTime: number;
|
|
146
|
+
_id: string;
|
|
147
|
+
amount?: number;
|
|
148
|
+
createdAt: number;
|
|
149
|
+
customerEmail: string;
|
|
150
|
+
planId?: string;
|
|
151
|
+
status: "active" | "cancelled";
|
|
152
|
+
subscriptionId: string;
|
|
153
|
+
updatedAt: number;
|
|
154
|
+
} | null>;
|
|
155
|
+
listSubscriptions(ctx: RunQueryCtx, args: {
|
|
156
|
+
customerEmail: string;
|
|
157
|
+
}): Promise<{
|
|
158
|
+
_creationTime: number;
|
|
159
|
+
_id: string;
|
|
160
|
+
amount?: number;
|
|
161
|
+
createdAt: number;
|
|
162
|
+
customerEmail: string;
|
|
163
|
+
planId?: string;
|
|
164
|
+
status: "active" | "cancelled";
|
|
165
|
+
subscriptionId: string;
|
|
166
|
+
updatedAt: number;
|
|
167
|
+
}[]>;
|
|
168
|
+
hasActiveSubscription(ctx: RunQueryCtx, args: {
|
|
169
|
+
customerEmail: string;
|
|
170
|
+
}): Promise<boolean>;
|
|
171
|
+
listRecentEvents(ctx: RunQueryCtx, args?: {
|
|
172
|
+
limit?: number;
|
|
173
|
+
}): Promise<{
|
|
174
|
+
_creationTime: number;
|
|
175
|
+
_id: string;
|
|
176
|
+
eventId: string;
|
|
177
|
+
eventType: string;
|
|
178
|
+
payload: string;
|
|
179
|
+
receivedAt: number;
|
|
180
|
+
txRef?: string;
|
|
181
|
+
}[]>;
|
|
182
|
+
getStats(ctx: RunQueryCtx): Promise<{
|
|
183
|
+
events: number;
|
|
184
|
+
subscriptions: number;
|
|
185
|
+
transactions: number;
|
|
186
|
+
}>;
|
|
187
|
+
}
|
|
188
|
+
type RunQueryCtx = {
|
|
189
|
+
runQuery: GenericActionCtx<GenericDataModel>["runQuery"];
|
|
190
|
+
};
|
|
191
|
+
export {};
|
|
192
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { httpActionGeneric } from "convex/server";
|
|
2
|
+
const FLUTTERWAVE_API_BASE = "https://api.flutterwave.com/v3";
|
|
3
|
+
// Flutterwave does not sign webhook payloads. Instead, it echoes back the
|
|
4
|
+
// secret hash you configured in the Dashboard, verbatim, in a `verif-hash`
|
|
5
|
+
// header — verification is a direct (constant-time) string comparison, not
|
|
6
|
+
// an HMAC digest of the request body. See:
|
|
7
|
+
// https://developer.flutterwave.com/docs/integration-guides/webhooks
|
|
8
|
+
function timingSafeEqual(a, b) {
|
|
9
|
+
if (a.length !== b.length)
|
|
10
|
+
return false;
|
|
11
|
+
let mismatch = 0;
|
|
12
|
+
for (let i = 0; i < a.length; i++) {
|
|
13
|
+
mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
14
|
+
}
|
|
15
|
+
return mismatch === 0;
|
|
16
|
+
}
|
|
17
|
+
export class Flutterwave {
|
|
18
|
+
component;
|
|
19
|
+
options;
|
|
20
|
+
webhookHandler;
|
|
21
|
+
constructor(component, options) {
|
|
22
|
+
this.component = component;
|
|
23
|
+
this.options = options;
|
|
24
|
+
const component_ = component;
|
|
25
|
+
const webhookSecretHash = options.webhookSecretHash;
|
|
26
|
+
this.webhookHandler = httpActionGeneric(async (ctx, request) => {
|
|
27
|
+
const rawBody = await request.text();
|
|
28
|
+
const signature = request.headers.get("verif-hash");
|
|
29
|
+
if (!signature) {
|
|
30
|
+
return new Response(JSON.stringify({ error: "Missing signature" }), {
|
|
31
|
+
status: 400,
|
|
32
|
+
headers: { "Content-Type": "application/json" },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (!timingSafeEqual(webhookSecretHash, signature)) {
|
|
36
|
+
console.error("convex-flutterwave: webhook signature mismatch");
|
|
37
|
+
return new Response(JSON.stringify({ error: "Invalid signature" }), {
|
|
38
|
+
status: 401,
|
|
39
|
+
headers: { "Content-Type": "application/json" },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
let event;
|
|
43
|
+
try {
|
|
44
|
+
event = JSON.parse(rawBody);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return new Response(JSON.stringify({ error: "Invalid JSON" }), {
|
|
48
|
+
status: 400,
|
|
49
|
+
headers: { "Content-Type": "application/json" },
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const data = event.data ?? {};
|
|
53
|
+
const eventId = data.id !== undefined
|
|
54
|
+
? `${event.event}:${data.id}`
|
|
55
|
+
: `${event.event}:${data.tx_ref ?? crypto.randomUUID()}`;
|
|
56
|
+
const { alreadyProcessed } = await ctx.runMutation(component_.lib.checkAndRecordEvent, {
|
|
57
|
+
eventId,
|
|
58
|
+
eventType: event.event,
|
|
59
|
+
txRef: data.tx_ref ?? undefined,
|
|
60
|
+
payload: rawBody,
|
|
61
|
+
});
|
|
62
|
+
if (alreadyProcessed) {
|
|
63
|
+
return new Response(JSON.stringify({ success: true, duplicate: true }), {
|
|
64
|
+
status: 200,
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
switch (event.event) {
|
|
69
|
+
case "charge.completed": {
|
|
70
|
+
const customer = data.customer;
|
|
71
|
+
const status = data.status === "successful" ? "successful" : "failed";
|
|
72
|
+
await ctx.runMutation(component_.lib.recordTransaction, {
|
|
73
|
+
txRef: data.tx_ref,
|
|
74
|
+
flwRef: data.flw_ref ?? undefined,
|
|
75
|
+
transactionId: data.id !== undefined ? String(data.id) : undefined,
|
|
76
|
+
customerEmail: customer?.email ?? "",
|
|
77
|
+
amount: data.amount,
|
|
78
|
+
currency: data.currency ?? "NGN",
|
|
79
|
+
status,
|
|
80
|
+
paymentType: data.payment_type ?? undefined,
|
|
81
|
+
narration: data.narration ?? undefined,
|
|
82
|
+
paidAt: data.created_at ? new Date(data.created_at).getTime() : undefined,
|
|
83
|
+
metadata: data.meta ? JSON.stringify(data.meta) : undefined,
|
|
84
|
+
});
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case "subscription.cancelled": {
|
|
88
|
+
const planId = data.plan ?? undefined;
|
|
89
|
+
const customer = data.customer;
|
|
90
|
+
if (data.id !== undefined) {
|
|
91
|
+
await ctx.runMutation(component_.lib.recordSubscriptionEvent, {
|
|
92
|
+
subscriptionId: String(data.id),
|
|
93
|
+
customerEmail: customer?.email ?? "",
|
|
94
|
+
planId,
|
|
95
|
+
amount: data.amount ?? undefined,
|
|
96
|
+
status: "cancelled",
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
return new Response(JSON.stringify({ success: true }), {
|
|
105
|
+
status: 200,
|
|
106
|
+
headers: { "Content-Type": "application/json" },
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
async initializeTransaction(ctx, args) {
|
|
111
|
+
const txRef = args.txRef ?? crypto.randomUUID();
|
|
112
|
+
const res = await fetch(`${FLUTTERWAVE_API_BASE}/payments`, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
headers: {
|
|
115
|
+
Authorization: `Bearer ${this.options.secretKey}`,
|
|
116
|
+
"Content-Type": "application/json",
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify({
|
|
119
|
+
tx_ref: txRef,
|
|
120
|
+
amount: args.amount,
|
|
121
|
+
currency: args.currency ?? "NGN",
|
|
122
|
+
redirect_url: args.redirectUrl,
|
|
123
|
+
// Flutterwave requires payment_plan as a numeric id, not a string —
|
|
124
|
+
// this component's own PaymentPlanResult.planId is a string (for
|
|
125
|
+
// consistency with every other id in this API), so it's converted
|
|
126
|
+
// here. Sending it as a string doesn't error; Flutterwave just
|
|
127
|
+
// silently processes the charge as a normal one-time payment
|
|
128
|
+
// instead of linking it to the plan, so no subscription is created.
|
|
129
|
+
payment_plan: args.paymentPlan !== undefined ? Number(args.paymentPlan) : undefined,
|
|
130
|
+
payment_options: args.paymentOptions?.join(", "),
|
|
131
|
+
customer: {
|
|
132
|
+
email: args.email,
|
|
133
|
+
name: args.customerName,
|
|
134
|
+
phonenumber: args.customerPhoneNumber,
|
|
135
|
+
},
|
|
136
|
+
meta: args.metadata,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
const json = (await res.json());
|
|
140
|
+
if (json.status !== "success") {
|
|
141
|
+
throw new Error(json.message ?? "Failed to initialize Flutterwave transaction");
|
|
142
|
+
}
|
|
143
|
+
await ctx.runMutation(this.component.lib.recordTransaction, {
|
|
144
|
+
txRef,
|
|
145
|
+
customerEmail: args.email,
|
|
146
|
+
amount: args.amount,
|
|
147
|
+
currency: args.currency ?? "NGN",
|
|
148
|
+
status: "pending",
|
|
149
|
+
metadata: args.metadata ? JSON.stringify(args.metadata) : undefined,
|
|
150
|
+
});
|
|
151
|
+
return { paymentLink: json.data.link, txRef };
|
|
152
|
+
}
|
|
153
|
+
async verifyTransaction(ctx, args) {
|
|
154
|
+
const res = await fetch(`${FLUTTERWAVE_API_BASE}/transactions/${encodeURIComponent(args.transactionId)}/verify`, { headers: { Authorization: `Bearer ${this.options.secretKey}` } });
|
|
155
|
+
const json = (await res.json());
|
|
156
|
+
if (json.status !== "success") {
|
|
157
|
+
throw new Error(json.message ?? "Failed to verify Flutterwave transaction");
|
|
158
|
+
}
|
|
159
|
+
const data = json.data;
|
|
160
|
+
const status = data.status === "successful" ? "successful" : "failed";
|
|
161
|
+
await ctx.runMutation(this.component.lib.recordTransaction, {
|
|
162
|
+
txRef: data.tx_ref,
|
|
163
|
+
flwRef: data.flw_ref ?? undefined,
|
|
164
|
+
transactionId: String(data.id),
|
|
165
|
+
customerEmail: data.customer?.email ?? "",
|
|
166
|
+
amount: data.amount,
|
|
167
|
+
currency: data.currency,
|
|
168
|
+
status,
|
|
169
|
+
paymentType: data.payment_type ?? undefined,
|
|
170
|
+
narration: data.narration ?? undefined,
|
|
171
|
+
paidAt: data.created_at ? new Date(data.created_at).getTime() : undefined,
|
|
172
|
+
});
|
|
173
|
+
// recordTransaction keeps the email the transaction was first created
|
|
174
|
+
// under rather than whatever Flutterwave just echoed back (see its
|
|
175
|
+
// comment — test mode rewrites it). Read that back so callers — and
|
|
176
|
+
// anything they render, like a result screen — see the real address
|
|
177
|
+
// too, not just what's in the database.
|
|
178
|
+
const stored = await ctx.runQuery(this.component.lib.getTransaction, { txRef: data.tx_ref });
|
|
179
|
+
return {
|
|
180
|
+
status: data.status,
|
|
181
|
+
txRef: data.tx_ref,
|
|
182
|
+
flwRef: data.flw_ref ?? undefined,
|
|
183
|
+
transactionId: String(data.id),
|
|
184
|
+
amount: data.amount,
|
|
185
|
+
currency: data.currency,
|
|
186
|
+
paymentType: data.payment_type ?? undefined,
|
|
187
|
+
narration: data.narration ?? undefined,
|
|
188
|
+
paidAt: data.created_at ? new Date(data.created_at).getTime() : undefined,
|
|
189
|
+
customerEmail: stored?.customerEmail ?? data.customer?.email ?? "",
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
async cancelSubscription(ctx, args) {
|
|
193
|
+
const res = await fetch(`${FLUTTERWAVE_API_BASE}/subscriptions/${encodeURIComponent(args.subscriptionId)}/cancel`, { method: "PUT", headers: { Authorization: `Bearer ${this.options.secretKey}` } });
|
|
194
|
+
const json = (await res.json());
|
|
195
|
+
if (json.status !== "success") {
|
|
196
|
+
throw new Error(json.message ?? "Failed to cancel Flutterwave subscription");
|
|
197
|
+
}
|
|
198
|
+
await ctx.runMutation(this.component.lib.recordSubscriptionEvent, {
|
|
199
|
+
subscriptionId: args.subscriptionId,
|
|
200
|
+
customerEmail: args.customerEmail,
|
|
201
|
+
status: "cancelled",
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async enableSubscription(ctx, args) {
|
|
205
|
+
const res = await fetch(`${FLUTTERWAVE_API_BASE}/subscriptions/${encodeURIComponent(args.subscriptionId)}/activate`, { method: "PUT", headers: { Authorization: `Bearer ${this.options.secretKey}` } });
|
|
206
|
+
const json = (await res.json());
|
|
207
|
+
if (json.status !== "success") {
|
|
208
|
+
throw new Error(json.message ?? "Failed to activate Flutterwave subscription");
|
|
209
|
+
}
|
|
210
|
+
await ctx.runMutation(this.component.lib.recordSubscriptionEvent, {
|
|
211
|
+
subscriptionId: args.subscriptionId,
|
|
212
|
+
customerEmail: args.customerEmail,
|
|
213
|
+
status: "active",
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
async createPaymentPlan(ctx, args) {
|
|
217
|
+
const res = await fetch(`${FLUTTERWAVE_API_BASE}/payment-plans`, {
|
|
218
|
+
method: "POST",
|
|
219
|
+
headers: {
|
|
220
|
+
Authorization: `Bearer ${this.options.secretKey}`,
|
|
221
|
+
"Content-Type": "application/json",
|
|
222
|
+
},
|
|
223
|
+
body: JSON.stringify({
|
|
224
|
+
name: args.name,
|
|
225
|
+
amount: args.amount,
|
|
226
|
+
interval: args.interval,
|
|
227
|
+
currency: args.currency ?? "NGN",
|
|
228
|
+
duration: args.duration,
|
|
229
|
+
}),
|
|
230
|
+
});
|
|
231
|
+
const json = (await res.json());
|
|
232
|
+
if (json.status !== "success") {
|
|
233
|
+
throw new Error(json.message ?? "Failed to create Flutterwave payment plan");
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
planId: String(json.data.id),
|
|
237
|
+
name: json.data.name,
|
|
238
|
+
amount: json.data.amount,
|
|
239
|
+
interval: json.data.interval,
|
|
240
|
+
currency: json.data.currency,
|
|
241
|
+
duration: json.data.duration,
|
|
242
|
+
status: json.data.status,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async listPaymentPlans(_ctx) {
|
|
246
|
+
const res = await fetch(`${FLUTTERWAVE_API_BASE}/payment-plans`, {
|
|
247
|
+
headers: { Authorization: `Bearer ${this.options.secretKey}` },
|
|
248
|
+
});
|
|
249
|
+
const json = (await res.json());
|
|
250
|
+
if (json.status !== "success") {
|
|
251
|
+
throw new Error(json.message ?? "Failed to list Flutterwave payment plans");
|
|
252
|
+
}
|
|
253
|
+
return json.data.map((plan) => ({
|
|
254
|
+
planId: String(plan.id),
|
|
255
|
+
name: plan.name,
|
|
256
|
+
amount: plan.amount,
|
|
257
|
+
interval: plan.interval,
|
|
258
|
+
currency: plan.currency,
|
|
259
|
+
duration: plan.duration,
|
|
260
|
+
status: plan.status,
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Flutterwave has no "subscription created" webhook — a subscription is
|
|
265
|
+
* created implicitly the first time a customer pays through a checkout
|
|
266
|
+
* initialized with `paymentPlan`, and that charge webhook doesn't carry
|
|
267
|
+
* the subscription's own id (only the plan id). This reads the customer's
|
|
268
|
+
* subscriptions straight from Flutterwave's Subscriptions API and upserts
|
|
269
|
+
* them locally — call it after a plan-linked checkout returns, or from a
|
|
270
|
+
* manual "sync" action, as a reliable way to populate subscription state.
|
|
271
|
+
*/
|
|
272
|
+
async fetchFlutterwaveSubscriptions(email) {
|
|
273
|
+
const url = email
|
|
274
|
+
? `${FLUTTERWAVE_API_BASE}/subscriptions?email=${encodeURIComponent(email)}`
|
|
275
|
+
: `${FLUTTERWAVE_API_BASE}/subscriptions`;
|
|
276
|
+
const res = await fetch(url, { headers: { Authorization: `Bearer ${this.options.secretKey}` } });
|
|
277
|
+
return await res.json();
|
|
278
|
+
}
|
|
279
|
+
async syncCustomerSubscriptions(ctx, args) {
|
|
280
|
+
const json = await this.fetchFlutterwaveSubscriptions(args.email);
|
|
281
|
+
if (json.status !== "success") {
|
|
282
|
+
throw new Error(json.message ?? "Failed to fetch Flutterwave subscriptions");
|
|
283
|
+
}
|
|
284
|
+
let subscriptions = json.data ?? [];
|
|
285
|
+
// Flutterwave's ?email= filter matches against whatever email it has on
|
|
286
|
+
// file for the subscription — in test mode that's the same "ravesb_
|
|
287
|
+
// <hash>_" rewritten address seen elsewhere, not the real one, so
|
|
288
|
+
// filtering by the real email can come back empty even when a matching
|
|
289
|
+
// subscription exists. Fall back to an unfiltered list and match after
|
|
290
|
+
// stripping that rewrite, rather than trusting the filter alone.
|
|
291
|
+
if (subscriptions.length === 0) {
|
|
292
|
+
const all = await this.fetchFlutterwaveSubscriptions();
|
|
293
|
+
if (all.status === "success") {
|
|
294
|
+
subscriptions = (all.data ?? []).filter((sub) => sub.customer?.customer_email?.replace(/^ravesb_[0-9a-f]+_/i, "") === args.email);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
for (const sub of subscriptions) {
|
|
298
|
+
await ctx.runMutation(this.component.lib.recordSubscriptionEvent, {
|
|
299
|
+
subscriptionId: String(sub.id),
|
|
300
|
+
// Use the email the caller queried by, not Flutterwave's own
|
|
301
|
+
// customer_email field — in test mode Flutterwave rewrites it (e.g.
|
|
302
|
+
// "ravesb_<hash>_real@email.com"), which would make the record
|
|
303
|
+
// unfindable by the email a merchant actually knows the customer as.
|
|
304
|
+
customerEmail: args.email,
|
|
305
|
+
planId: sub.plan !== undefined ? String(sub.plan) : undefined,
|
|
306
|
+
amount: sub.amount ?? undefined,
|
|
307
|
+
status: sub.status === "active" ? "active" : "cancelled",
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return subscriptions.length;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Attributes every subscription on a given plan to one email, regardless
|
|
314
|
+
* of what Flutterwave itself has on file as that subscription's customer.
|
|
315
|
+
* This is unsafe to reach for by default — a real plan can have many
|
|
316
|
+
* subscribers — but it's exactly what's needed when Flutterwave's
|
|
317
|
+
* test-mode sandbox has substituted its own fixed customer identity for
|
|
318
|
+
* every subscription (see the README's Subscriptions section), making
|
|
319
|
+
* email-based sync unable to find anything at all. Reach for it only
|
|
320
|
+
* where you already know (or, in a single-developer test/demo context,
|
|
321
|
+
* can safely assume) there's one subscriber to claim — the example app
|
|
322
|
+
* uses it as a fallback for exactly that reason.
|
|
323
|
+
*/
|
|
324
|
+
async syncSubscriptionsByPlan(ctx, args) {
|
|
325
|
+
const json = await this.fetchFlutterwaveSubscriptions();
|
|
326
|
+
if (json.status !== "success") {
|
|
327
|
+
throw new Error(json.message ?? "Failed to fetch Flutterwave subscriptions");
|
|
328
|
+
}
|
|
329
|
+
const planId = Number(args.planId);
|
|
330
|
+
const subscriptions = (json.data ?? []).filter((sub) => sub.plan === planId);
|
|
331
|
+
for (const sub of subscriptions) {
|
|
332
|
+
await ctx.runMutation(this.component.lib.recordSubscriptionEvent, {
|
|
333
|
+
subscriptionId: String(sub.id),
|
|
334
|
+
customerEmail: args.email,
|
|
335
|
+
planId: String(planId),
|
|
336
|
+
amount: sub.amount ?? undefined,
|
|
337
|
+
status: sub.status === "active" ? "active" : "cancelled",
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
return subscriptions.length;
|
|
341
|
+
}
|
|
342
|
+
async getTransaction(ctx, args) {
|
|
343
|
+
return await ctx.runQuery(this.component.lib.getTransaction, args);
|
|
344
|
+
}
|
|
345
|
+
async listTransactions(ctx, args) {
|
|
346
|
+
return await ctx.runQuery(this.component.lib.listTransactions, args);
|
|
347
|
+
}
|
|
348
|
+
async getSubscription(ctx, args) {
|
|
349
|
+
return await ctx.runQuery(this.component.lib.getSubscription, args);
|
|
350
|
+
}
|
|
351
|
+
async listSubscriptions(ctx, args) {
|
|
352
|
+
return await ctx.runQuery(this.component.lib.listSubscriptions, args);
|
|
353
|
+
}
|
|
354
|
+
async hasActiveSubscription(ctx, args) {
|
|
355
|
+
return await ctx.runQuery(this.component.lib.hasActiveSubscription, args);
|
|
356
|
+
}
|
|
357
|
+
async listRecentEvents(ctx, args) {
|
|
358
|
+
return await ctx.runQuery(this.component.lib.listRecentEvents, args ?? {});
|
|
359
|
+
}
|
|
360
|
+
async getStats(ctx) {
|
|
361
|
+
return await ctx.runQuery(this.component.lib.getStats, {});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated `api` utility.
|
|
3
|
+
*
|
|
4
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
5
|
+
*
|
|
6
|
+
* To regenerate, run `npx convex dev`.
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type * as lib from "../lib.js";
|
|
10
|
+
import type { ApiFromModules, FilterApi, FunctionReference } from "convex/server";
|
|
11
|
+
declare const fullApi: ApiFromModules<{
|
|
12
|
+
lib: typeof lib;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* A utility for referencing Convex functions in your app's public API.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```js
|
|
19
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const api: FilterApi<typeof fullApi, FunctionReference<any, "public">>;
|
|
23
|
+
/**
|
|
24
|
+
* A utility for referencing Convex functions in your app's internal API.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```js
|
|
28
|
+
* const myFunctionReference = internal.myModule.myFunction;
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const internal: FilterApi<typeof fullApi, FunctionReference<any, "internal">>;
|
|
32
|
+
export declare const components: {};
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAGvB,QAAA,MAAM,OAAO,EAAE,cAAc,CAAC;IAC5B,GAAG,EAAE,OAAO,GAAG,CAAC;CACjB,CAAiB,CAAC;AAEnB;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,EAAE,SAAS,CACzB,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CACjB,CAAC;AAElB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,CAC9B,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,UAAU,CAAC,CACnB,CAAC;AAElB,eAAO,MAAM,UAAU,EAAqC,EAAE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Generated `api` utility.
|
|
4
|
+
*
|
|
5
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
+
*
|
|
7
|
+
* To regenerate, run `npx convex dev`.
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { anyApi, componentsGeneric } from "convex/server";
|
|
11
|
+
const fullApi = anyApi;
|
|
12
|
+
/**
|
|
13
|
+
* A utility for referencing Convex functions in your app's public API.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```js
|
|
17
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const api = anyApi;
|
|
21
|
+
/**
|
|
22
|
+
* A utility for referencing Convex functions in your app's internal API.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* ```js
|
|
26
|
+
* const myFunctionReference = internal.myModule.myFunction;
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const internal = anyApi;
|
|
30
|
+
export const components = componentsGeneric();
|
|
31
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AASH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,OAAO,GAER,MAAa,CAAC;AAEnB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAGZ,MAAa,CAAC;AAElB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAGjB,MAAa,CAAC;AAElB,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,EAAmB,CAAC"}
|