@sikka/aps 0.0.1 → 0.0.3

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 CHANGED
@@ -1,77 +1,75 @@
1
- {
2
- "name": "@sikka/aps",
3
- "version": "0.0.1",
4
- "description": "A Stripe-like developer-friendly SDK for Amazon Payment Services integration. Supports payment links, hosted checkout, tokenization, webhooks, and payment management.",
5
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.mjs",
12
- "require": "./dist/index.js"
13
- },
14
- "./react": {
15
- "types": "./dist/react/index.d.ts",
16
- "import": "./dist/react/index.mjs",
17
- "require": "./dist/react/index.js"
18
- }
19
- },
20
- "files": [
21
- "dist",
22
- "README.md"
23
- ],
24
- "scripts": {
25
- "build": "pnpm build:main && pnpm build:react",
26
- "build:main": "tsup src/index.ts --format cjs,esm --dts --out-dir dist",
27
- "build:react": "tsup src/react/index.ts --format cjs,esm --dts --out-dir dist/react --external react",
28
- "dev": "tsup src/index.ts src/react/index.ts --format cjs,esm --dts --watch",
29
- "typecheck": "tsc --noEmit",
30
- "prepublishOnly": "pnpm build"
31
- },
32
- "keywords": [
33
- "amazon-payment-services",
34
- "aps",
35
- "payfort",
36
- "payment",
37
- "checkout",
38
- "payment-link",
39
- "hosted-checkout",
40
- "tokenization",
41
- "stripe",
42
- "saudi-arabia",
43
- "uae",
44
- "middle-east",
45
- "mada",
46
- "knet",
47
- "naps",
48
- "fawry",
49
- "apple-pay",
50
- "react"
51
- ],
52
- "author": "",
53
- "license": "MIT",
54
- "repository": {
55
- "type": "git",
56
- "url": "https://github.com/sikka-software/amazon-payment-services.git"
57
- },
58
- "bugs": {
59
- "url": "https://github.com/sikka-software/amazon-payment-services/issues"
60
- },
61
- "homepage": "https://github.com/sikka-software/amazon-payment-services#readme",
62
- "devDependencies": {
63
- "@types/node": "^20.19.35",
64
- "@types/react": "^19.0.0",
65
- "crypto-js": "^4.2.0",
66
- "react": "^19.0.0",
67
- "tsup": "^8.5.1",
68
- "typescript": "^5.9.3"
69
- },
70
- "peerDependencies": {
71
- "crypto-js": "^4.2.0",
72
- "react": "^18.0.0 || ^19.0.0"
73
- },
74
- "engines": {
75
- "node": ">=16.0.0"
76
- }
77
- }
1
+ {
2
+ "name": "@sikka/aps",
3
+ "version": "0.0.3",
4
+ "description": "A Stripe-like developer-friendly SDK for Amazon Payment Services integration. Supports payment links, hosted checkout, tokenization, webhooks, and payment management.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./react": {
15
+ "types": "./dist/react/index.d.ts",
16
+ "import": "./dist/react/index.mjs",
17
+ "require": "./dist/react/index.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "pnpm build:main && pnpm build:react",
26
+ "build:main": "tsup src/index.ts --format cjs,esm --dts --out-dir dist",
27
+ "build:react": "tsup src/react/index.ts --format cjs,esm --dts --out-dir dist/react --external react",
28
+ "dev": "tsup src/index.ts src/react/index.ts --format cjs,esm --dts --watch",
29
+ "typecheck": "tsc --noEmit",
30
+ "prepublishOnly": "pnpm build"
31
+ },
32
+ "keywords": [
33
+ "amazon-payment-services",
34
+ "aps",
35
+ "payfort",
36
+ "payment",
37
+ "checkout",
38
+ "payment-link",
39
+ "hosted-checkout",
40
+ "tokenization",
41
+ "stripe",
42
+ "saudi-arabia",
43
+ "uae",
44
+ "middle-east",
45
+ "mada",
46
+ "knet",
47
+ "naps",
48
+ "fawry",
49
+ "apple-pay",
50
+ "react"
51
+ ],
52
+ "author": "",
53
+ "license": "MIT",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "https://github.com/sikka-software/amazon-payment-services.git"
57
+ },
58
+ "bugs": {
59
+ "url": "https://github.com/sikka-software/amazon-payment-services/issues"
60
+ },
61
+ "homepage": "https://github.com/sikka-software/amazon-payment-services#readme",
62
+ "devDependencies": {
63
+ "@types/node": "^20.19.35",
64
+ "@types/react": "^19.0.0",
65
+ "react": "^19.0.0",
66
+ "tsup": "^8.5.1",
67
+ "typescript": "^5.9.3"
68
+ },
69
+ "peerDependencies": {
70
+ "react": "^18.0.0 || ^19.0.0"
71
+ },
72
+ "engines": {
73
+ "node": ">=16.0.0"
74
+ }
75
+ }
@@ -1,408 +0,0 @@
1
- // src/react/TokenizationForm.tsx
2
- import { useState } from "react";
3
- import { jsx, jsxs } from "react/jsx-runtime";
4
- function detectCardBrand(cardNumber) {
5
- const number = cardNumber.replace(/\D/g, "");
6
- if (/^4/.test(number)) return "visa";
7
- if (/^5[1-5]/.test(number)) return "mastercard";
8
- if (/^3[47]/.test(number)) return "amex";
9
- if (/^6(?:011|5)/.test(number)) return "discover";
10
- if (/^(?:2131|1800|35)/.test(number)) return "jcb";
11
- if (/^9792/.test(number)) return "troy";
12
- if (/^50/.test(number) || /^4571/.test(number)) return "mada";
13
- return "unknown";
14
- }
15
- var DefaultIcons = {
16
- visa: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 48 48", className: "w-8 h-8", children: [
17
- /* @__PURE__ */ jsx("rect", { fill: "#1A1F71", rx: "4", width: "48", height: "48" }),
18
- /* @__PURE__ */ jsx(
19
- "path",
20
- {
21
- fill: "#fff",
22
- d: "M19.5 30h-3l1.9-11.5h3L19.5 30zm11.4 0h-2.7l-1.7-8.2c-.2-.9-.4-1.7-.5-2.6-.1 0-.2.1-.3.2-.6.8-1.3 1.6-1.9 2.4L22.5 30h-3l3.1-11.5h2.8l.4 2.1c.7-1 1.5-2 2.3-2.9.9-1.2 2-1.7 3.4-1.7.5 0 1 0 1.5.1l-2.1 13.9zm6.6-11.3c-.8-.3-2.6-.7-4.6-.7-5.1 0-8.7 2.7-8.7 6.5 0 2.9 2.6 4.5 4.6 5.5 2 .9 2.7 1.6 2.7 2.4 0 1.3-1.6 1.9-3 1.9-2 0-3.1-.3-4.8-1l-.7-.3-.7 4.3c1.2.5 3.4 1 5.7 1 5.4 0 8.9-2.7 8.9-6.8 0-2.3-1.4-4-4.4-5.5-1.8-.9-2.9-1.6-2.9-2.5 0-.8.9-1.7 2.8-1.7 1.6 0 2.8.3 3.7.7l.4.2.7-4.2z"
23
- }
24
- )
25
- ] }),
26
- mastercard: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 48 48", className: "w-8 h-8", children: [
27
- /* @__PURE__ */ jsx("rect", { fill: "#000", rx: "4", width: "48", height: "48" }),
28
- /* @__PURE__ */ jsx("circle", { fill: "#EB001B", cx: "18", cy: "24", r: "10" }),
29
- /* @__PURE__ */ jsx("circle", { fill: "#F79E1B", cx: "30", cy: "24", r: "10", opacity: "0.8" })
30
- ] }),
31
- amex: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 48 48", className: "w-8 h-8", children: [
32
- /* @__PURE__ */ jsx("rect", { fill: "#006FCF", rx: "4", width: "48", height: "48" }),
33
- /* @__PURE__ */ jsx(
34
- "path",
35
- {
36
- fill: "#fff",
37
- d: "M10 18h28v12H10V18zm2 2v8h24v-8H12z"
38
- }
39
- )
40
- ] }),
41
- mada: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 48 48", className: "w-8 h-8", children: [
42
- /* @__PURE__ */ jsx("rect", { fill: "#006C35", rx: "4", width: "48", height: "48" }),
43
- /* @__PURE__ */ jsx(
44
- "path",
45
- {
46
- fill: "#fff",
47
- d: "M12 20h24v8H12v-8zm2 2v4h20v-4H14z"
48
- }
49
- )
50
- ] }),
51
- unknown: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 48 48", className: "w-8 h-8", children: [
52
- /* @__PURE__ */ jsx("rect", { fill: "#666", rx: "4", width: "48", height: "48" }),
53
- /* @__PURE__ */ jsx("rect", { fill: "#999", x: "10", y: "18", width: "28", height: "12", rx: "2" })
54
- ] })
55
- };
56
- var defaultStyles = {
57
- container: {
58
- maxWidth: "480px",
59
- margin: "0 auto"
60
- },
61
- form: {
62
- display: "flex",
63
- flexDirection: "column",
64
- gap: "16px"
65
- },
66
- inputGroup: {
67
- display: "flex",
68
- flexDirection: "column",
69
- gap: "4px"
70
- },
71
- label: {
72
- fontSize: "14px",
73
- fontWeight: "500",
74
- color: "#374151"
75
- },
76
- input: {
77
- padding: "12px 16px",
78
- fontSize: "16px",
79
- border: "1px solid #D1D5DB",
80
- borderRadius: "8px",
81
- outline: "none",
82
- transition: "border-color 0.2s"
83
- },
84
- inputError: {
85
- borderColor: "#EF4444"
86
- },
87
- row: {
88
- display: "grid",
89
- gridTemplateColumns: "1fr 1fr",
90
- gap: "12px"
91
- },
92
- button: {
93
- padding: "14px 24px",
94
- fontSize: "16px",
95
- fontWeight: "600",
96
- color: "#fff",
97
- backgroundColor: "#7C3AED",
98
- border: "none",
99
- borderRadius: "8px",
100
- cursor: "pointer",
101
- transition: "background-color 0.2s"
102
- },
103
- buttonDisabled: {
104
- backgroundColor: "#A78BFA",
105
- cursor: "not-allowed"
106
- },
107
- securityNotice: {
108
- padding: "12px",
109
- backgroundColor: "#D1FAE5",
110
- borderRadius: "8px",
111
- fontSize: "13px",
112
- color: "#065F46"
113
- }
114
- };
115
- var TokenizationForm = ({
116
- actionUrl,
117
- formParams,
118
- customerEmail = "",
119
- onSuccess,
120
- onError,
121
- styles = {},
122
- icons = {},
123
- labels = {},
124
- placeholders = {},
125
- disableFormatting = false,
126
- showCardIcons = true,
127
- showSecurityNotice = true,
128
- className = {}
129
- }) => {
130
- const [cardNumber, setCardNumber] = useState("");
131
- const [expiryDate, setExpiryDate] = useState("");
132
- const [cvv, setCvv] = useState("");
133
- const [cardHolderName, setCardHolderName] = useState("");
134
- const [email, setEmail] = useState(customerEmail);
135
- const [loading, setLoading] = useState(false);
136
- const [errors, setErrors] = useState({});
137
- const [cardBrand, setCardBrand] = useState("unknown");
138
- const mergedStyles = {
139
- ...defaultStyles,
140
- ...styles
141
- };
142
- const mergedIcons = {
143
- ...DefaultIcons,
144
- ...icons
145
- };
146
- const mergedLabels = {
147
- cardNumber: "Card Number",
148
- cardHolder: "Card Holder Name",
149
- customerEmail: "Customer Email",
150
- expiryDate: "Expiry Date",
151
- cvv: "CVV",
152
- submitButton: "Secure Payment",
153
- processing: "Processing...",
154
- ...labels
155
- };
156
- const mergedPlaceholders = {
157
- cardNumber: "1234 5678 9012 3456",
158
- cardHolder: "John Doe",
159
- customerEmail: "customer@example.com",
160
- expiryDate: "MM/YY",
161
- cvv: "123",
162
- ...placeholders
163
- };
164
- const formatCardNumber = (value) => {
165
- if (disableFormatting) return value;
166
- const v = value.replace(/\s+/g, "").replace(/[^0-9]/gi, "");
167
- const matches = v.match(/\d{4,16}/g);
168
- const match = matches && matches[0] || "";
169
- const parts = [];
170
- for (let i = 0, len = match.length; i < len; i += 4) {
171
- parts.push(match.substring(i, i + 4));
172
- }
173
- if (parts.length) {
174
- return parts.join(" ");
175
- }
176
- return value;
177
- };
178
- const formatExpiryDate = (value) => {
179
- if (disableFormatting) return value;
180
- const v = value.replace(/\s+/g, "").replace(/[^0-9]/gi, "");
181
- if (v.length >= 2) {
182
- return v.substring(0, 2) + "/" + v.substring(2, 4);
183
- }
184
- return v;
185
- };
186
- const validateForm = () => {
187
- const newErrors = {};
188
- if (!cardNumber || cardNumber.replace(/\s/g, "").length < 13) {
189
- newErrors.cardNumber = "Invalid card number";
190
- }
191
- if (!expiryDate || expiryDate.length !== 5) {
192
- newErrors.expiryDate = "Invalid expiry date";
193
- }
194
- if (!cvv || cvv.length < 3) {
195
- newErrors.cvv = "Invalid CVV";
196
- }
197
- if (!cardHolderName || cardHolderName.length < 2) {
198
- newErrors.cardHolder = "Card holder name is required";
199
- }
200
- if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
201
- newErrors.email = "Invalid email address";
202
- }
203
- setErrors(newErrors);
204
- return Object.keys(newErrors).length === 0;
205
- };
206
- const handleSubmit = (e) => {
207
- e.preventDefault();
208
- if (!validateForm()) {
209
- onError?.("Please fill in all required fields correctly");
210
- return;
211
- }
212
- setLoading(true);
213
- const form = document.createElement("form");
214
- form.method = "POST";
215
- form.action = actionUrl;
216
- form.style.display = "none";
217
- Object.entries(formParams).forEach(([key, value]) => {
218
- const input = document.createElement("input");
219
- input.type = "hidden";
220
- input.name = key;
221
- input.value = value;
222
- form.appendChild(input);
223
- });
224
- const addHiddenInput = (name, value) => {
225
- const input = document.createElement("input");
226
- input.type = "hidden";
227
- input.name = name;
228
- input.value = value;
229
- form.appendChild(input);
230
- };
231
- const cleanCardNumber = cardNumber.replace(/\s/g, "");
232
- const cleanExpiryDate = expiryDate.replace("/", "");
233
- addHiddenInput("card_number", cleanCardNumber);
234
- addHiddenInput("expiry_date", cleanExpiryDate);
235
- addHiddenInput("card_security_code", cvv);
236
- addHiddenInput("card_holder_name", cardHolderName);
237
- document.body.appendChild(form);
238
- form.submit();
239
- setLoading(false);
240
- };
241
- const handleCardNumberChange = (e) => {
242
- const formatted = formatCardNumber(e.target.value);
243
- setCardNumber(formatted);
244
- setCardBrand(detectCardBrand(formatted));
245
- if (errors.cardNumber) {
246
- setErrors({ ...errors, cardNumber: "" });
247
- }
248
- };
249
- const handleExpiryDateChange = (e) => {
250
- const formatted = formatExpiryDate(e.target.value);
251
- setExpiryDate(formatted);
252
- if (errors.expiryDate) {
253
- setErrors({ ...errors, expiryDate: "" });
254
- }
255
- };
256
- const handleCvvChange = (e) => {
257
- const value = e.target.value.replace(/\D/g, "").substring(0, 4);
258
- setCvv(value);
259
- if (errors.cvv) {
260
- setErrors({ ...errors, cvv: "" });
261
- }
262
- };
263
- return /* @__PURE__ */ jsx("div", { style: mergedStyles.container, className: className.container || "", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: mergedStyles.form, className: className.form || "", children: [
264
- /* @__PURE__ */ jsxs("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
265
- /* @__PURE__ */ jsx("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.cardNumber }),
266
- /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
267
- /* @__PURE__ */ jsx(
268
- "input",
269
- {
270
- type: "text",
271
- value: cardNumber,
272
- onChange: handleCardNumberChange,
273
- placeholder: mergedPlaceholders.cardNumber,
274
- maxLength: 19,
275
- required: true,
276
- style: {
277
- ...mergedStyles.input,
278
- ...errors.cardNumber ? mergedStyles.inputError : {},
279
- paddingRight: showCardIcons ? "60px" : "16px"
280
- },
281
- className: className.input || ""
282
- }
283
- ),
284
- showCardIcons && cardBrand !== "unknown" && /* @__PURE__ */ jsx(
285
- "div",
286
- {
287
- style: {
288
- position: "absolute",
289
- right: "12px",
290
- top: "50%",
291
- transform: "translateY(-50%)"
292
- },
293
- children: mergedIcons[cardBrand]
294
- }
295
- )
296
- ] }),
297
- errors.cardNumber && /* @__PURE__ */ jsx("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.cardNumber })
298
- ] }),
299
- /* @__PURE__ */ jsxs("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
300
- /* @__PURE__ */ jsx("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.cardHolder }),
301
- /* @__PURE__ */ jsx(
302
- "input",
303
- {
304
- type: "text",
305
- value: cardHolderName,
306
- onChange: (e) => {
307
- setCardHolderName(e.target.value);
308
- if (errors.cardHolder) {
309
- setErrors({ ...errors, cardHolder: "" });
310
- }
311
- },
312
- placeholder: mergedPlaceholders.cardHolder,
313
- required: true,
314
- style: {
315
- ...mergedStyles.input,
316
- ...errors.cardHolder ? mergedStyles.inputError : {}
317
- },
318
- className: className.input || ""
319
- }
320
- ),
321
- errors.cardHolder && /* @__PURE__ */ jsx("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.cardHolder })
322
- ] }),
323
- /* @__PURE__ */ jsxs("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
324
- /* @__PURE__ */ jsx("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.customerEmail }),
325
- /* @__PURE__ */ jsx(
326
- "input",
327
- {
328
- type: "email",
329
- value: email,
330
- onChange: (e) => {
331
- setEmail(e.target.value);
332
- if (errors.email) {
333
- setErrors({ ...errors, email: "" });
334
- }
335
- },
336
- placeholder: mergedPlaceholders.customerEmail,
337
- style: {
338
- ...mergedStyles.input,
339
- ...errors.email ? mergedStyles.inputError : {}
340
- },
341
- className: className.input || ""
342
- }
343
- ),
344
- errors.email && /* @__PURE__ */ jsx("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.email }),
345
- /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "#6B7280" }, children: "Used to associate the saved card with the customer" })
346
- ] }),
347
- /* @__PURE__ */ jsxs("div", { style: mergedStyles.row, children: [
348
- /* @__PURE__ */ jsxs("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
349
- /* @__PURE__ */ jsx("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.expiryDate }),
350
- /* @__PURE__ */ jsx(
351
- "input",
352
- {
353
- type: "text",
354
- value: expiryDate,
355
- onChange: handleExpiryDateChange,
356
- placeholder: mergedPlaceholders.expiryDate,
357
- maxLength: 5,
358
- required: true,
359
- style: {
360
- ...mergedStyles.input,
361
- ...errors.expiryDate ? mergedStyles.inputError : {}
362
- },
363
- className: className.input || ""
364
- }
365
- ),
366
- errors.expiryDate && /* @__PURE__ */ jsx("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.expiryDate })
367
- ] }),
368
- /* @__PURE__ */ jsxs("div", { style: mergedStyles.inputGroup, className: className.inputGroup || "", children: [
369
- /* @__PURE__ */ jsx("label", { style: mergedStyles.label, className: className.label || "", children: mergedLabels.cvv }),
370
- /* @__PURE__ */ jsx(
371
- "input",
372
- {
373
- type: "text",
374
- value: cvv,
375
- onChange: handleCvvChange,
376
- placeholder: mergedPlaceholders.cvv,
377
- maxLength: 4,
378
- required: true,
379
- style: {
380
- ...mergedStyles.input,
381
- ...errors.cvv ? mergedStyles.inputError : {}
382
- },
383
- className: className.input || ""
384
- }
385
- ),
386
- errors.cvv && /* @__PURE__ */ jsx("span", { style: { color: "#EF4444", fontSize: "12px" }, children: errors.cvv })
387
- ] })
388
- ] }),
389
- showSecurityNotice && /* @__PURE__ */ jsx("div", { style: mergedStyles.securityNotice, children: "\u{1F512} Your card details are securely processed by Amazon Payment Services. We never store your card information." }),
390
- /* @__PURE__ */ jsx(
391
- "button",
392
- {
393
- type: "submit",
394
- disabled: loading,
395
- style: {
396
- ...mergedStyles.button,
397
- ...loading ? mergedStyles.buttonDisabled : {}
398
- },
399
- className: className.button || "",
400
- children: loading ? mergedLabels.processing : mergedLabels.submitButton
401
- }
402
- )
403
- ] }) });
404
- };
405
-
406
- export {
407
- TokenizationForm
408
- };