@unchainedshop/core-payment 4.5.0 → 4.6.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/README.md +31 -0
- package/lib/module/configurePaymentCredentialsModule.d.ts +8 -2
- package/lib/module/configurePaymentCredentialsModule.js +3 -3
- package/lib/module/configurePaymentModule.d.ts +8 -2
- package/lib/module/configurePaymentProvidersModule.js +2 -2
- package/lib/payment-index.d.ts +2 -0
- package/lib/payment-index.js +2 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -94,6 +94,37 @@ const providers = await paymentModule.findSupported({
|
|
|
94
94
|
| `PAYMENT_PROVIDER_UPDATE` | Provider updated |
|
|
95
95
|
| `PAYMENT_PROVIDER_REMOVE` | Provider deleted |
|
|
96
96
|
|
|
97
|
+
## Security (PCI DSS)
|
|
98
|
+
|
|
99
|
+
This module is designed for **PCI DSS SAQ-A eligibility**:
|
|
100
|
+
|
|
101
|
+
### Tokenization
|
|
102
|
+
|
|
103
|
+
- **No card data storage**: Credit card numbers (PAN) and CVV are never stored
|
|
104
|
+
- **Provider tokens only**: Only payment provider-issued tokens are stored
|
|
105
|
+
- **Secure credentials**: Payment credentials contain references, not card data
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// PaymentCredentials structure - tokens only, no card data
|
|
109
|
+
type PaymentCredentials = {
|
|
110
|
+
paymentProviderId: string;
|
|
111
|
+
userId: string;
|
|
112
|
+
token?: string; // Provider-issued token (NOT card number)
|
|
113
|
+
isPreferred?: boolean;
|
|
114
|
+
meta: any; // Provider-specific metadata
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Payment Flow
|
|
119
|
+
|
|
120
|
+
All payment integrations use tokenization patterns:
|
|
121
|
+
1. Card data collected by payment provider (Stripe, Datatrans, etc.)
|
|
122
|
+
2. Provider returns secure token
|
|
123
|
+
3. Unchained stores only the token reference
|
|
124
|
+
4. Subsequent charges use the token
|
|
125
|
+
|
|
126
|
+
See [SECURITY.md](../../SECURITY.md) for complete PCI DSS compliance documentation.
|
|
127
|
+
|
|
97
128
|
## License
|
|
98
129
|
|
|
99
130
|
EUPL-1.2
|
|
@@ -9,13 +9,19 @@ export declare const configurePaymentCredentialsModule: (PaymentCredentials: mon
|
|
|
9
9
|
credentialsExists: ({ paymentCredentialsId, }: {
|
|
10
10
|
paymentCredentialsId: string;
|
|
11
11
|
}) => Promise<boolean>;
|
|
12
|
-
findPaymentCredential: ({ paymentCredentialsId, userId, paymentProviderId, }: {
|
|
12
|
+
findPaymentCredential: ({ paymentCredentialsId, userId, paymentProviderId, isPreferred, }: {
|
|
13
13
|
paymentCredentialsId?: string;
|
|
14
14
|
userId?: string;
|
|
15
15
|
paymentProviderId?: string;
|
|
16
|
+
isPreferred?: boolean;
|
|
16
17
|
}, options?: mongodb.FindOptions) => Promise<PaymentCredentialsType | null>;
|
|
17
18
|
findPaymentCredentials: (query: mongodb.Filter<PaymentCredentialsType>, options?: mongodb.FindOptions) => Promise<PaymentCredentialsType[]>;
|
|
18
|
-
upsertCredentials: ({ userId, paymentProviderId, _id, token, ...meta }:
|
|
19
|
+
upsertCredentials: ({ userId, paymentProviderId, _id, token, ...meta }: Partial<PaymentCredentialsType> & {
|
|
20
|
+
userId: PaymentCredentialsType["userId"];
|
|
21
|
+
paymentProviderId: PaymentCredentialsType["paymentProviderId"];
|
|
22
|
+
_id?: PaymentCredentialsType["_id"];
|
|
23
|
+
token?: PaymentCredentialsType["token"];
|
|
24
|
+
} & Record<string, any>) => Promise<PaymentCredentialsType>;
|
|
19
25
|
removeCredentials: (paymentCredentialsId: string) => Promise<mongodb.WithId<PaymentCredentialsType> | null>;
|
|
20
26
|
deleteUserPaymentCredentials: (userId: string) => Promise<number>;
|
|
21
27
|
};
|
|
@@ -28,10 +28,10 @@ export const configurePaymentCredentialsModule = (PaymentCredentials) => {
|
|
|
28
28
|
const credentialsCount = await PaymentCredentials.countDocuments(generateDbFilterById(paymentCredentialsId), { limit: 1 });
|
|
29
29
|
return !!credentialsCount;
|
|
30
30
|
},
|
|
31
|
-
findPaymentCredential: async ({ paymentCredentialsId, userId, paymentProviderId, }, options) => {
|
|
31
|
+
findPaymentCredential: async ({ paymentCredentialsId, userId, paymentProviderId, isPreferred, }, options) => {
|
|
32
32
|
return PaymentCredentials.findOne(paymentCredentialsId
|
|
33
|
-
? generateDbFilterById(paymentCredentialsId)
|
|
34
|
-
: { userId, paymentProviderId }, options);
|
|
33
|
+
? generateDbFilterById(paymentCredentialsId, isPreferred ? { isPreferred: true } : {})
|
|
34
|
+
: { userId, paymentProviderId, ...(isPreferred ? { isPreferred: true } : {}) }, options);
|
|
35
35
|
},
|
|
36
36
|
findPaymentCredentials: async (query, options) => {
|
|
37
37
|
const credentials = await PaymentCredentials.find(query, options).toArray();
|
|
@@ -24,13 +24,19 @@ export declare const configurePaymentModule: ({ db, options: paymentOptions, }:
|
|
|
24
24
|
credentialsExists: ({ paymentCredentialsId, }: {
|
|
25
25
|
paymentCredentialsId: string;
|
|
26
26
|
}) => Promise<boolean>;
|
|
27
|
-
findPaymentCredential: ({ paymentCredentialsId, userId, paymentProviderId, }: {
|
|
27
|
+
findPaymentCredential: ({ paymentCredentialsId, userId, paymentProviderId, isPreferred, }: {
|
|
28
28
|
paymentCredentialsId?: string;
|
|
29
29
|
userId?: string;
|
|
30
30
|
paymentProviderId?: string;
|
|
31
|
+
isPreferred?: boolean;
|
|
31
32
|
}, options?: import("mongodb").FindOptions) => Promise<import("../db/PaymentCredentialsCollection.ts").PaymentCredentials | null>;
|
|
32
33
|
findPaymentCredentials: (query: import("mongodb").Filter<import("../db/PaymentCredentialsCollection.ts").PaymentCredentials>, options?: import("mongodb").FindOptions) => Promise<import("../db/PaymentCredentialsCollection.ts").PaymentCredentials[]>;
|
|
33
|
-
upsertCredentials: ({ userId, paymentProviderId, _id, token, ...meta }:
|
|
34
|
+
upsertCredentials: ({ userId, paymentProviderId, _id, token, ...meta }: Partial<import("../db/PaymentCredentialsCollection.ts").PaymentCredentials> & {
|
|
35
|
+
userId: import("../db/PaymentCredentialsCollection.ts").PaymentCredentials["userId"];
|
|
36
|
+
paymentProviderId: import("../db/PaymentCredentialsCollection.ts").PaymentCredentials["paymentProviderId"];
|
|
37
|
+
_id?: import("../db/PaymentCredentialsCollection.ts").PaymentCredentials["_id"];
|
|
38
|
+
token?: import("../db/PaymentCredentialsCollection.ts").PaymentCredentials["token"];
|
|
39
|
+
} & Record<string, any>) => Promise<import("../db/PaymentCredentialsCollection.ts").PaymentCredentials>;
|
|
34
40
|
removeCredentials: (paymentCredentialsId: string) => Promise<import("mongodb").WithId<import("../db/PaymentCredentialsCollection.ts").PaymentCredentials> | null>;
|
|
35
41
|
deleteUserPaymentCredentials: (userId: string) => Promise<number>;
|
|
36
42
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { emit, registerEvents } from '@unchainedshop/events';
|
|
2
|
-
import { generateDbFilterById, generateDbObjectId, mongodb } from '@unchainedshop/mongodb';
|
|
2
|
+
import { generateDbFilterById, generateDbObjectId, mongodb, escapeRegexString, } from '@unchainedshop/mongodb';
|
|
3
3
|
import pMemoize from 'p-memoize';
|
|
4
4
|
import ExpiryMap from 'expiry-map';
|
|
5
5
|
const PAYMENT_PROVIDER_EVENTS = [
|
|
@@ -17,7 +17,7 @@ export const buildFindSelector = ({ includeDeleted = false, queryString, payment
|
|
|
17
17
|
selector.type = type;
|
|
18
18
|
}
|
|
19
19
|
if (queryString) {
|
|
20
|
-
const regex = new RegExp(queryString, 'i');
|
|
20
|
+
const regex = new RegExp(escapeRegexString(queryString), 'i');
|
|
21
21
|
selector.$or = [{ _id: regex }, { adapterKey: regex }];
|
|
22
22
|
}
|
|
23
23
|
return selector;
|
package/lib/payment-index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from './module/configurePaymentModule.ts';
|
|
2
|
+
export * from './module/configurePaymentCredentialsModule.ts';
|
|
3
|
+
export * from './module/configurePaymentProvidersModule.ts';
|
|
2
4
|
export * from './payment-settings.ts';
|
|
3
5
|
export * from './db/PaymentCredentialsCollection.ts';
|
|
4
6
|
export * from './db/PaymentProvidersCollection.ts';
|
package/lib/payment-index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from "./module/configurePaymentModule.js";
|
|
2
|
+
export * from "./module/configurePaymentCredentialsModule.js";
|
|
3
|
+
export * from "./module/configurePaymentProvidersModule.js";
|
|
2
4
|
export * from "./payment-settings.js";
|
|
3
5
|
export * from "./db/PaymentCredentialsCollection.js";
|
|
4
6
|
export * from "./db/PaymentProvidersCollection.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core-payment",
|
|
3
|
-
"
|
|
3
|
+
"description": "Payment provider management module for the Unchained Engine",
|
|
4
|
+
"version": "4.6.0",
|
|
4
5
|
"main": "lib/payment-index.js",
|
|
5
6
|
"types": "lib/payment-index.d.ts",
|
|
6
7
|
"type": "module",
|
|
@@ -34,9 +35,9 @@
|
|
|
34
35
|
},
|
|
35
36
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
36
37
|
"dependencies": {
|
|
37
|
-
"@unchainedshop/events": "^4.
|
|
38
|
-
"@unchainedshop/logger": "^4.
|
|
39
|
-
"@unchainedshop/utils": "^4.
|
|
38
|
+
"@unchainedshop/events": "^4.6.0",
|
|
39
|
+
"@unchainedshop/logger": "^4.6.0",
|
|
40
|
+
"@unchainedshop/utils": "^4.6.0",
|
|
40
41
|
"expiry-map": "^2.0.0",
|
|
41
42
|
"p-memoize": "^8.0.0"
|
|
42
43
|
},
|