@queelabs/connectors-whop 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.
@@ -0,0 +1,7 @@
1
+ import type { MppPaymentAdapter } from "@queelabs/core";
2
+ /**
3
+ * Whop adapter (MPP-shaped): maps Whop checkout / embedded purchase flows
4
+ * to Quee payment challenges and receipts.
5
+ */
6
+ export declare function createWhopMppConnector(): MppPaymentAdapter;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,iBAAiB,EAGlB,MAAM,gBAAgB,CAAC;AAuBxB;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,iBAAiB,CAqH1D"}
package/dist/index.js ADDED
@@ -0,0 +1,113 @@
1
+ function readRecord(source, key) {
2
+ const value = source[key];
3
+ if (!value || typeof value !== "object" || Array.isArray(value))
4
+ return null;
5
+ return value;
6
+ }
7
+ function readString(source, key) {
8
+ const value = source[key];
9
+ return typeof value === "string" && value.length > 0 ? value : null;
10
+ }
11
+ /**
12
+ * Whop adapter (MPP-shaped): maps Whop checkout / embedded purchase flows
13
+ * to Quee payment challenges and receipts.
14
+ */
15
+ export function createWhopMppConnector() {
16
+ return {
17
+ async createPurchaseChallenge(input) {
18
+ const apiKey = process.env.WHOP_API_KEY;
19
+ if (!apiKey) {
20
+ throw new Error("WHOP_API_KEY is not set");
21
+ }
22
+ const rawCheckoutBaseUrl = process.env.QUEE_CHECKOUT_BASE_URL;
23
+ if (!rawCheckoutBaseUrl) {
24
+ throw new Error("QUEE_CHECKOUT_BASE_URL is not set");
25
+ }
26
+ const checkoutBaseUrl = rawCheckoutBaseUrl.replace(/\/+$/, "");
27
+ const planId = process.env.WHOP_DEFAULT_PLAN_ID;
28
+ if (!planId) {
29
+ throw new Error("WHOP_DEFAULT_PLAN_ID is not set");
30
+ }
31
+ const response = await fetch("https://api.whop.com/v1/checkouts", {
32
+ method: "POST",
33
+ headers: {
34
+ Authorization: `Bearer ${apiKey}`,
35
+ "Content-Type": "application/json",
36
+ },
37
+ body: JSON.stringify({
38
+ plan_id: planId,
39
+ redirect_url: `${checkoutBaseUrl}/pay/${input.orderId}/success`,
40
+ metadata: {
41
+ orderId: input.orderId,
42
+ marketplaceId: input.marketplaceId,
43
+ },
44
+ }),
45
+ });
46
+ const data = (await response.json());
47
+ if (!response.ok) {
48
+ throw new Error(`Whop checkout creation failed (${response.status}): ${JSON.stringify(data)}`);
49
+ }
50
+ if (!data.url || !data.id) {
51
+ throw new Error("Whop checkout creation failed: missing checkout payload");
52
+ }
53
+ return {
54
+ challengeId: `whop_ch_${input.orderId}`,
55
+ rail: "whop",
56
+ payload: {
57
+ type: "whop_checkout_challenge",
58
+ version: "0.1",
59
+ orderId: input.orderId,
60
+ amountMinor: input.amountMinor,
61
+ currency: input.currency,
62
+ whop: {
63
+ checkoutUrl: data.url,
64
+ checkoutId: data.id,
65
+ },
66
+ },
67
+ };
68
+ },
69
+ async verifyPurchase(input) {
70
+ const apiKey = process.env.WHOP_API_KEY;
71
+ if (!apiKey) {
72
+ throw new Error("WHOP_API_KEY is not set");
73
+ }
74
+ const expectedCheckoutId = readString(readRecord(input.challengePayload, "whop") ?? {}, "checkoutId");
75
+ const checkoutId = typeof input.proof.whopCheckoutId === "string"
76
+ ? input.proof.whopCheckoutId
77
+ : null;
78
+ if (!expectedCheckoutId || !checkoutId || checkoutId !== expectedCheckoutId) {
79
+ throw new Error("whop proof does not match stored challenge");
80
+ }
81
+ const response = await fetch(`https://api.whop.com/v1/checkouts/${encodeURIComponent(checkoutId)}`, {
82
+ headers: {
83
+ Authorization: `Bearer ${apiKey}`,
84
+ },
85
+ });
86
+ const data = (await response.json());
87
+ if (!response.ok) {
88
+ throw new Error(`Whop checkout lookup failed (${response.status}): ${JSON.stringify(data)}`);
89
+ }
90
+ if (data.status !== "completed") {
91
+ throw new Error(`Whop checkout not completed: ${data.status}`);
92
+ }
93
+ if (!data.id) {
94
+ throw new Error("Whop checkout lookup failed: missing checkout id");
95
+ }
96
+ if (data.id !== expectedCheckoutId) {
97
+ throw new Error("Whop checkout does not match stored challenge");
98
+ }
99
+ return {
100
+ receiptPayload: {
101
+ verified: true,
102
+ challengeId: input.challengeId,
103
+ orderId: input.orderId,
104
+ settledVia: "whop",
105
+ proof: input.proof,
106
+ providerReference: data.id,
107
+ },
108
+ verifiedAt: new Date(),
109
+ };
110
+ },
111
+ };
112
+ }
113
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@queelabs/connectors-whop",
3
+ "version": "0.0.1",
4
+ "license": "UNLICENSED",
5
+ "description": "Whop payment connector for Quee",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/quee-protocol/quee.git",
18
+ "directory": "connectors/whop"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "import": "./dist/index.js",
23
+ "types": "./dist/index.d.ts"
24
+ }
25
+ },
26
+ "dependencies": {
27
+ "@queelabs/core": "0.0.1"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.10.2",
31
+ "typescript": "^5.7.2"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "lint": "echo ok"
36
+ }
37
+ }