@sphoq/payments 0.1.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/client.d.ts +23 -0
- package/dist/client.js +92 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.js +10 -0
- package/package.json +24 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SphoqPaymentsOptions, CreateChargeOptions, Charge, GetChargeOptions, CancelChargeOptions, CancelChargeResult, VerifyWebhookOptions } from "./types.js";
|
|
2
|
+
export declare class SphoqPayments {
|
|
3
|
+
private readonly apiKey;
|
|
4
|
+
private readonly baseUrl;
|
|
5
|
+
readonly charges: ChargesClient;
|
|
6
|
+
constructor(options: SphoqPaymentsOptions);
|
|
7
|
+
/**
|
|
8
|
+
* Verify a webhook signature to ensure it came from Sphoq.
|
|
9
|
+
*
|
|
10
|
+
* Works in both Node.js (using crypto module) and edge runtimes (using Web Crypto API).
|
|
11
|
+
*/
|
|
12
|
+
static verifyWebhookSignature(options: VerifyWebhookOptions): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
declare class ChargesClient {
|
|
15
|
+
private readonly apiKey;
|
|
16
|
+
private readonly baseUrl;
|
|
17
|
+
constructor(apiKey: string, baseUrl: string);
|
|
18
|
+
create(options: CreateChargeOptions): Promise<Charge>;
|
|
19
|
+
get(options: GetChargeOptions): Promise<Charge>;
|
|
20
|
+
cancel(options: CancelChargeOptions): Promise<CancelChargeResult>;
|
|
21
|
+
private request;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { SphoqApiError } from "./types.js";
|
|
2
|
+
const DEFAULT_BASE_URL = "https://your-convex-deployment.convex.site";
|
|
3
|
+
export class SphoqPayments {
|
|
4
|
+
apiKey;
|
|
5
|
+
baseUrl;
|
|
6
|
+
charges;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.apiKey = options.apiKey;
|
|
9
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
10
|
+
this.charges = new ChargesClient(this.apiKey, this.baseUrl);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Verify a webhook signature to ensure it came from Sphoq.
|
|
14
|
+
*
|
|
15
|
+
* Works in both Node.js (using crypto module) and edge runtimes (using Web Crypto API).
|
|
16
|
+
*/
|
|
17
|
+
static async verifyWebhookSignature(options) {
|
|
18
|
+
const { payload, signature, secret } = options;
|
|
19
|
+
if (!signature.startsWith("sha256="))
|
|
20
|
+
return false;
|
|
21
|
+
const expectedHex = signature.slice(7);
|
|
22
|
+
// Use Web Crypto API (works in Node 18+, Deno, Cloudflare Workers, Vercel Edge)
|
|
23
|
+
const encoder = new TextEncoder();
|
|
24
|
+
const key = await globalThis.crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
25
|
+
const signatureBuffer = await globalThis.crypto.subtle.sign("HMAC", key, encoder.encode(payload));
|
|
26
|
+
const computedHex = Array.from(new Uint8Array(signatureBuffer))
|
|
27
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
28
|
+
.join("");
|
|
29
|
+
// Constant-time comparison
|
|
30
|
+
if (computedHex.length !== expectedHex.length)
|
|
31
|
+
return false;
|
|
32
|
+
let result = 0;
|
|
33
|
+
for (let i = 0; i < computedHex.length; i++) {
|
|
34
|
+
result |= computedHex.charCodeAt(i) ^ expectedHex.charCodeAt(i);
|
|
35
|
+
}
|
|
36
|
+
return result === 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
class ChargesClient {
|
|
40
|
+
apiKey;
|
|
41
|
+
baseUrl;
|
|
42
|
+
constructor(apiKey, baseUrl) {
|
|
43
|
+
this.apiKey = apiKey;
|
|
44
|
+
this.baseUrl = baseUrl;
|
|
45
|
+
}
|
|
46
|
+
async create(options) {
|
|
47
|
+
const body = {
|
|
48
|
+
amount: options.amount,
|
|
49
|
+
description: options.description,
|
|
50
|
+
};
|
|
51
|
+
if (options.externalId)
|
|
52
|
+
body.externalId = options.externalId;
|
|
53
|
+
if (options.customer)
|
|
54
|
+
body.customer = options.customer;
|
|
55
|
+
if (options.expirationSeconds)
|
|
56
|
+
body.expirationSeconds = options.expirationSeconds;
|
|
57
|
+
if (options.metadata)
|
|
58
|
+
body.metadata = options.metadata;
|
|
59
|
+
return this.request("/v1/charges", body);
|
|
60
|
+
}
|
|
61
|
+
async get(options) {
|
|
62
|
+
if (!options.id && !options.externalId) {
|
|
63
|
+
throw new Error("Either id or externalId is required");
|
|
64
|
+
}
|
|
65
|
+
const body = {};
|
|
66
|
+
if (options.id)
|
|
67
|
+
body.id = options.id;
|
|
68
|
+
if (options.externalId)
|
|
69
|
+
body.externalId = options.externalId;
|
|
70
|
+
return this.request("/v1/charges/get", body);
|
|
71
|
+
}
|
|
72
|
+
async cancel(options) {
|
|
73
|
+
return this.request("/v1/charges/cancel", {
|
|
74
|
+
id: options.id,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async request(path, body) {
|
|
78
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers: {
|
|
81
|
+
"Content-Type": "application/json",
|
|
82
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
83
|
+
},
|
|
84
|
+
body: JSON.stringify(body),
|
|
85
|
+
});
|
|
86
|
+
const data = await response.json();
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
throw new SphoqApiError(data.error ?? "Request failed", response.status, data);
|
|
89
|
+
}
|
|
90
|
+
return data;
|
|
91
|
+
}
|
|
92
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface SphoqPaymentsOptions {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface CreateChargeOptions {
|
|
6
|
+
amount: number;
|
|
7
|
+
description: string;
|
|
8
|
+
externalId?: string;
|
|
9
|
+
customer?: {
|
|
10
|
+
name?: string;
|
|
11
|
+
email?: string;
|
|
12
|
+
cpf?: string;
|
|
13
|
+
};
|
|
14
|
+
expirationSeconds?: number;
|
|
15
|
+
metadata?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface Charge {
|
|
18
|
+
id: string;
|
|
19
|
+
externalId?: string;
|
|
20
|
+
amount: number;
|
|
21
|
+
currency: string;
|
|
22
|
+
description: string;
|
|
23
|
+
status: "pending" | "paid" | "expired" | "cancelled";
|
|
24
|
+
txid: string;
|
|
25
|
+
pixCopiaECola?: string;
|
|
26
|
+
qrCode?: string;
|
|
27
|
+
customerName?: string;
|
|
28
|
+
customerEmail?: string;
|
|
29
|
+
paidAt?: number;
|
|
30
|
+
endToEndId?: string;
|
|
31
|
+
metadata?: Record<string, unknown>;
|
|
32
|
+
createdAt: number;
|
|
33
|
+
expiresAt: number;
|
|
34
|
+
}
|
|
35
|
+
export interface GetChargeOptions {
|
|
36
|
+
id?: string;
|
|
37
|
+
externalId?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CancelChargeOptions {
|
|
40
|
+
id: string;
|
|
41
|
+
}
|
|
42
|
+
export interface CancelChargeResult {
|
|
43
|
+
id: string;
|
|
44
|
+
status: "cancelled";
|
|
45
|
+
}
|
|
46
|
+
export interface WebhookPayload {
|
|
47
|
+
type: "charge.paid" | "charge.expired" | "charge.cancelled";
|
|
48
|
+
data: Charge;
|
|
49
|
+
createdAt: number;
|
|
50
|
+
}
|
|
51
|
+
export interface VerifyWebhookOptions {
|
|
52
|
+
payload: string;
|
|
53
|
+
signature: string;
|
|
54
|
+
secret: string;
|
|
55
|
+
}
|
|
56
|
+
export declare class SphoqApiError extends Error {
|
|
57
|
+
readonly statusCode: number;
|
|
58
|
+
readonly body: unknown;
|
|
59
|
+
constructor(message: string, statusCode: number, body?: unknown);
|
|
60
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sphoq/payments",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Sphoq Payments SDK — integrate PIX payment processing into your app",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "tsc --watch"
|
|
18
|
+
},
|
|
19
|
+
"keywords": ["sphoq", "pix", "payments", "brazil", "efibank", "convex"],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.9.0"
|
|
23
|
+
}
|
|
24
|
+
}
|