@unchainedshop/plugins 3.0.0-rc1 → 3.0.0-rc11
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/lib/events/node-event-emitter.js +1 -1
- package/lib/events/node-event-emitter.js.map +1 -1
- package/lib/files/gridfs/gridfs-adapter.d.ts +7 -1
- package/lib/files/gridfs/gridfs-adapter.d.ts.map +1 -1
- package/lib/files/gridfs/gridfs-adapter.js +2 -3
- package/lib/files/gridfs/gridfs-adapter.js.map +1 -1
- package/lib/files/gridfs/gridfs-webhook.js +2 -2
- package/lib/files/gridfs/gridfs-webhook.js.map +1 -1
- package/lib/files/gridfs/index.d.ts +1 -0
- package/lib/files/gridfs/index.d.ts.map +1 -1
- package/lib/files/minio/minio-adapter.d.ts.map +1 -1
- package/lib/files/minio/minio-adapter.js +6 -23
- package/lib/files/minio/minio-adapter.js.map +1 -1
- package/lib/payment/apple-iap/adapter.js +1 -1
- package/lib/payment/apple-iap/adapter.js.map +1 -1
- package/lib/payment/datatrans-v2/api/makeFetcher.d.ts.map +1 -1
- package/lib/payment/datatrans-v2/api/makeFetcher.js +5 -9
- package/lib/payment/datatrans-v2/api/makeFetcher.js.map +1 -1
- package/lib/payment/paypal-checkout.js +2 -0
- package/lib/payment/paypal-checkout.js.map +1 -1
- package/lib/payment/payrexx/api/makeFetcher.d.ts.map +1 -1
- package/lib/payment/payrexx/api/makeFetcher.js +7 -12
- package/lib/payment/payrexx/api/makeFetcher.js.map +1 -1
- package/lib/payment/stripe/stripe.d.ts.map +1 -1
- package/lib/payment/stripe/stripe.js +3 -1
- package/lib/payment/stripe/stripe.js.map +1 -1
- package/lib/pricing/discount-100-off.d.ts +2 -2
- package/lib/pricing/discount-100-off.d.ts.map +1 -1
- package/lib/pricing/discount-100-off.js.map +1 -1
- package/lib/pricing/discount-half-price-manual.d.ts +2 -2
- package/lib/pricing/discount-half-price-manual.d.ts.map +1 -1
- package/lib/pricing/discount-half-price-manual.js.map +1 -1
- package/lib/pricing/discount-half-price.d.ts +2 -2
- package/lib/pricing/discount-half-price.d.ts.map +1 -1
- package/lib/pricing/discount-half-price.js.map +1 -1
- package/lib/worker/email.d.ts.map +1 -1
- package/lib/worker/email.js +17 -14
- package/lib/worker/email.js.map +1 -1
- package/package.json +110 -27
- package/src/events/node-event-emitter.ts +1 -1
- package/src/files/gridfs/gridfs-adapter.ts +14 -7
- package/src/files/gridfs/gridfs-webhook.ts +2 -2
- package/src/files/gridfs/index.ts +2 -0
- package/src/files/minio/minio-adapter.ts +7 -26
- package/src/payment/apple-iap/adapter.ts +1 -1
- package/src/payment/datatrans-v2/api/makeFetcher.ts +8 -11
- package/src/payment/paypal-checkout.ts +2 -0
- package/src/payment/payrexx/api/makeFetcher.ts +10 -13
- package/src/payment/stripe/stripe.ts +3 -1
- package/src/pricing/discount-100-off.ts +1 -2
- package/src/pricing/discount-half-price-manual.ts +1 -2
- package/src/pricing/discount-half-price.ts +1 -2
- package/src/worker/email.ts +19 -14
- package/tests/mock/datatrans/v1/secure-fields.json +4 -0
- package/tests/mock/datatrans/v1/transactions/authorize.json +48 -0
- package/tests/mock/datatrans/v1/transactions/card_check_authorized.json +47 -0
- package/tests/mock/datatrans/v1/transactions/payment_alias_authorized/settle.json +1 -0
- package/tests/mock/datatrans/v1/transactions/payment_alias_authorized.json +48 -0
- package/tests/mock/datatrans/v1/transactions/payment_authorized/cancel.json +1 -0
- package/tests/mock/datatrans/v1/transactions/payment_authorized/settle.json +1 -0
- package/tests/mock/datatrans/v1/transactions/payment_authorized.json +48 -0
- package/tests/mock/datatrans/v1/transactions/payment_authorized_low_amount/cancel.json +1 -0
- package/tests/mock/datatrans/v1/transactions/payment_authorized_low_amount.json +48 -0
- package/tests/mock/datatrans/v1/transactions/validate.json +1 -0
- package/tests/mock/datatrans/v1/transactions.json +4 -0
- package/tests/mock/payrexx/Gateway/1000001.json +106 -0
- package/tests/mock/payrexx/Gateway.json +24 -0
- package/tests/mock/payrexx/transaction_example1.json +65 -0
- package/tests/mock/payrexx/transaction_example2.json +65 -0
- package/tests/mock/payrexx/transaction_example3.json +94 -0
- package/lib/payment/datatrans-v2/generateSignature copy.d.ts +0 -11
- package/lib/payment/datatrans-v2/generateSignature copy.d.ts.map +0 -1
- package/lib/payment/datatrans-v2/generateSignature copy.js +0 -19
- package/lib/payment/datatrans-v2/generateSignature copy.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/plugins",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-rc11",
|
|
4
4
|
"main": "lib/plugins-index.js",
|
|
5
5
|
"types": "lib/plugins-index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -25,54 +25,137 @@
|
|
|
25
25
|
"ecommerce",
|
|
26
26
|
"core"
|
|
27
27
|
],
|
|
28
|
-
"
|
|
28
|
+
"authors": [
|
|
29
|
+
"Joël Meiller",
|
|
30
|
+
"Pascal Kaufmann"
|
|
31
|
+
],
|
|
29
32
|
"license": "EUPL-1.2",
|
|
30
33
|
"bugs": {
|
|
31
34
|
"url": "https://github.com/unchainedshop/unchained/issues"
|
|
32
35
|
},
|
|
33
36
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
34
37
|
"dependencies": {
|
|
35
|
-
"@
|
|
36
|
-
"@unchainedshop/
|
|
37
|
-
"@unchainedshop/core-
|
|
38
|
-
"@unchainedshop/core-
|
|
39
|
-
"@unchainedshop/core-
|
|
40
|
-
"@unchainedshop/core-
|
|
41
|
-
"@unchainedshop/core-
|
|
42
|
-
"@unchainedshop/core-
|
|
43
|
-
"@unchainedshop/
|
|
44
|
-
"@unchainedshop/
|
|
45
|
-
"@unchainedshop/
|
|
46
|
-
"@unchainedshop/
|
|
38
|
+
"@breejs/later": "^4.2.0",
|
|
39
|
+
"@unchainedshop/api": "^3.0.0-rc11",
|
|
40
|
+
"@unchainedshop/core-delivery": "^3.0.0-rc11",
|
|
41
|
+
"@unchainedshop/core-enrollments": "^3.0.0-rc11",
|
|
42
|
+
"@unchainedshop/core-orders": "^3.0.0-rc11",
|
|
43
|
+
"@unchainedshop/core-payment": "^3.0.0-rc11",
|
|
44
|
+
"@unchainedshop/core-products": "^3.0.0-rc11",
|
|
45
|
+
"@unchainedshop/core-warehousing": "^3.0.0-rc11",
|
|
46
|
+
"@unchainedshop/core-worker": "^3.0.0-rc11",
|
|
47
|
+
"@unchainedshop/events": "^3.0.0-rc11",
|
|
48
|
+
"@unchainedshop/file-upload": "^3.0.0-rc11",
|
|
49
|
+
"@unchainedshop/logger": "^3.0.0-rc11",
|
|
50
|
+
"@unchainedshop/utils": "^3.0.0-rc11",
|
|
51
|
+
"event-iterator": "^2.0.0",
|
|
52
|
+
"JSONStream": "^1.3.5"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"@aws-sdk/client-eventbridge": ">= 3.714 < 4",
|
|
56
|
+
"@paypal/checkout-server-sdk": "1.x",
|
|
57
|
+
"@redis/client": "1.x",
|
|
58
|
+
"bip32": "4.x",
|
|
59
|
+
"bitcoinjs-lib": ">= 6.1 <7",
|
|
60
|
+
"ethers": ">= 6.13 < 7",
|
|
61
|
+
"expiry-map": "2.x",
|
|
62
|
+
"express": "5.x",
|
|
63
|
+
"mime-types": "2.x",
|
|
64
|
+
"minio": "8.x",
|
|
65
|
+
"nodemailer": ">= 6.9 < 7",
|
|
66
|
+
"open": "10.x",
|
|
67
|
+
"p-memoize": "7.x",
|
|
68
|
+
"postfinancecheckout": ">= 4.5.0",
|
|
69
|
+
"stripe": "^17.4.0",
|
|
70
|
+
"tiny-secp256k1": "2.x",
|
|
71
|
+
"twilio": "5.x",
|
|
72
|
+
"web-push": ">= 3.6 <4",
|
|
73
|
+
"xml-js": ">= 1.6 < 2"
|
|
47
74
|
},
|
|
48
|
-
"
|
|
49
|
-
"@aws-sdk/client-eventbridge":
|
|
75
|
+
"peerDependenciesMeta": {
|
|
76
|
+
"@aws-sdk/client-eventbridge": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"@paypal/checkout-server-sdk": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
82
|
+
"@redis/client": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"bip32": {
|
|
86
|
+
"optional": true
|
|
87
|
+
},
|
|
88
|
+
"bitcoinjs-lib": {
|
|
89
|
+
"optional": true
|
|
90
|
+
},
|
|
91
|
+
"ethers": {
|
|
92
|
+
"optional": true
|
|
93
|
+
},
|
|
94
|
+
"expiry-map": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"express": {
|
|
98
|
+
"optional": true
|
|
99
|
+
},
|
|
100
|
+
"mime-types": {
|
|
101
|
+
"optional": true
|
|
102
|
+
},
|
|
103
|
+
"minio": {
|
|
104
|
+
"optional": true
|
|
105
|
+
},
|
|
106
|
+
"nodemailer": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"open": {
|
|
110
|
+
"optional": true
|
|
111
|
+
},
|
|
112
|
+
"p-memoize": {
|
|
113
|
+
"optional": true
|
|
114
|
+
},
|
|
115
|
+
"postfinancecheckout": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"stripe": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"tiny-secp256k1": {
|
|
122
|
+
"optional": true
|
|
123
|
+
},
|
|
124
|
+
"twilio": {
|
|
125
|
+
"optional": true
|
|
126
|
+
},
|
|
127
|
+
"web-push": {
|
|
128
|
+
"optional": true
|
|
129
|
+
},
|
|
130
|
+
"xml-js": {
|
|
131
|
+
"optional": true
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"devDependencies": {
|
|
135
|
+
"@aws-sdk/client-eventbridge": "^3.716.0",
|
|
50
136
|
"@breejs/later": "^4.2.0",
|
|
51
137
|
"@paypal/checkout-server-sdk": "^1.0.3",
|
|
52
138
|
"@redis/client": "^1.6.0",
|
|
139
|
+
"@types/express": "^5.0.0",
|
|
140
|
+
"@types/node": "^22.10.2",
|
|
53
141
|
"bip32": "^4.0.0",
|
|
54
142
|
"bitcoinjs-lib": "^6.1.7",
|
|
55
143
|
"ethers": "^6.13.4",
|
|
56
|
-
"event-iterator": "^2.0.0",
|
|
57
144
|
"expiry-map": "^2.0.0",
|
|
58
|
-
"express": "^
|
|
59
|
-
"
|
|
145
|
+
"express": "^5.0.1",
|
|
146
|
+
"jest": "^29.7.0",
|
|
60
147
|
"mime-types": "^2.1.35",
|
|
61
|
-
"minio": "^8.0.
|
|
148
|
+
"minio": "^8.0.3",
|
|
62
149
|
"nodemailer": "^6.9.16",
|
|
63
150
|
"open": "^10.1.0",
|
|
64
151
|
"p-memoize": "^7.1.1",
|
|
65
152
|
"postfinancecheckout": "^4.5.0",
|
|
66
|
-
"stripe": "^17.
|
|
153
|
+
"stripe": "^17.5.0",
|
|
67
154
|
"tiny-secp256k1": "^2.2.3",
|
|
155
|
+
"ts-jest": "^29.2.5",
|
|
68
156
|
"twilio": "^5.4.0",
|
|
157
|
+
"typescript": "^5.7.2",
|
|
69
158
|
"web-push": "^3.6.7",
|
|
70
159
|
"xml-js": "^1.6.11"
|
|
71
|
-
},
|
|
72
|
-
"devDependencies": {
|
|
73
|
-
"@types/node": "^22.10.2",
|
|
74
|
-
"jest": "^29.7.0",
|
|
75
|
-
"ts-jest": "^29.2.5",
|
|
76
|
-
"typescript": "^5.7.2"
|
|
77
160
|
}
|
|
78
161
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { pipeline } from 'stream/promises';
|
|
1
|
+
import { Readable, PassThrough } from 'node:stream';
|
|
2
|
+
import { pipeline } from 'node:stream/promises';
|
|
4
3
|
import mimeType from 'mime-types';
|
|
5
4
|
import {
|
|
6
5
|
FileAdapter,
|
|
@@ -12,6 +11,8 @@ import {
|
|
|
12
11
|
import { UploadFileData } from '@unchainedshop/file-upload';
|
|
13
12
|
import sign from './sign.js';
|
|
14
13
|
import { filesSettings } from '@unchainedshop/core-files';
|
|
14
|
+
import { UnchainedCore } from '@unchainedshop/core';
|
|
15
|
+
import { GridFSFileUploadsModule } from './index.js';
|
|
15
16
|
|
|
16
17
|
const { ROOT_URL } = process.env;
|
|
17
18
|
|
|
@@ -23,7 +24,13 @@ const bufferToStream = (buffer: any) => {
|
|
|
23
24
|
return stream;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
|
-
export const GridFSAdapter: IFileAdapter
|
|
27
|
+
export const GridFSAdapter: IFileAdapter<
|
|
28
|
+
UnchainedCore & {
|
|
29
|
+
modules: {
|
|
30
|
+
gridfsFileUploads: GridFSFileUploadsModule;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
> = {
|
|
27
34
|
key: 'shop.unchained.file-upload-plugin.gridfs',
|
|
28
35
|
label: 'Uploads files to Database using GridFS',
|
|
29
36
|
version: '1.0.0',
|
|
@@ -64,8 +71,8 @@ export const GridFSAdapter: IFileAdapter = {
|
|
|
64
71
|
} as UploadFileData & { putURL: string };
|
|
65
72
|
},
|
|
66
73
|
|
|
67
|
-
async uploadFileFromStream(directoryName: string, rawFile: any, { modules }
|
|
68
|
-
let stream;
|
|
74
|
+
async uploadFileFromStream(directoryName: string, rawFile: any, { modules }) {
|
|
75
|
+
let stream: Readable;
|
|
69
76
|
let fileName;
|
|
70
77
|
if (rawFile instanceof Promise) {
|
|
71
78
|
const { filename: f, createReadStream } = await rawFile;
|
|
@@ -104,7 +111,7 @@ export const GridFSAdapter: IFileAdapter = {
|
|
|
104
111
|
async uploadFileFromURL(
|
|
105
112
|
directoryName: string,
|
|
106
113
|
{ fileLink, fileName: fname, fileId, headers }: any,
|
|
107
|
-
{ modules }
|
|
114
|
+
{ modules },
|
|
108
115
|
) {
|
|
109
116
|
const { href } = new URL(fileLink);
|
|
110
117
|
const fileName = decodeURIComponent(fname || href.split('/').pop());
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { pipeline, finished } from 'stream/promises';
|
|
2
|
-
import { PassThrough } from 'stream';
|
|
1
|
+
import { pipeline, finished } from 'node:stream/promises';
|
|
2
|
+
import { PassThrough } from 'node:stream';
|
|
3
3
|
import { buildHashedFilename } from '@unchainedshop/file-upload';
|
|
4
4
|
import express from 'express';
|
|
5
5
|
import sign from './sign.js';
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { Readable } from 'stream';
|
|
4
|
-
import { URL } from 'url';
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import type { ReadableStream } from 'node:stream/web';
|
|
5
3
|
import { UploadFileData } from '@unchainedshop/file-upload';
|
|
6
4
|
import {
|
|
7
5
|
FileAdapter,
|
|
@@ -85,24 +83,6 @@ connectToMinio().then(function setClient(c) {
|
|
|
85
83
|
client = c;
|
|
86
84
|
});
|
|
87
85
|
|
|
88
|
-
const createHttpDownloadStream = async (
|
|
89
|
-
fileUrl: string,
|
|
90
|
-
headers: OutgoingHttpHeaders,
|
|
91
|
-
): Promise<http.IncomingMessage> => {
|
|
92
|
-
const { href, protocol } = new URL(fileUrl);
|
|
93
|
-
return new Promise((resolve, reject) => {
|
|
94
|
-
try {
|
|
95
|
-
if (protocol === 'http:') {
|
|
96
|
-
http.get(href, { headers }, resolve);
|
|
97
|
-
} else {
|
|
98
|
-
https.get(href, { headers }, resolve);
|
|
99
|
-
}
|
|
100
|
-
} catch (e) {
|
|
101
|
-
reject(e);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
|
|
106
86
|
const getObjectStats = async (fileName: string) => {
|
|
107
87
|
if (!client) throw new Error('Minio not connected, check env variables');
|
|
108
88
|
|
|
@@ -211,9 +191,10 @@ export const MinioAdapter: IFileAdapter = {
|
|
|
211
191
|
const fileName = fname || href.split('/').pop();
|
|
212
192
|
const hashedFilename = await buildHashedFilename(directoryName, fileName, new Date());
|
|
213
193
|
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
|
|
194
|
+
const url = new URL(fileLink);
|
|
195
|
+
const response = await fetch(url, { headers });
|
|
196
|
+
const type = mimeType.lookup(fileName) || response.headers['content-type'];
|
|
197
|
+
const readable = Readable.fromWeb(response.body as ReadableStream<Uint8Array<ArrayBufferLike>>);
|
|
217
198
|
const metaData = {
|
|
218
199
|
'Content-Type': type,
|
|
219
200
|
};
|
|
@@ -221,7 +202,7 @@ export const MinioAdapter: IFileAdapter = {
|
|
|
221
202
|
await client.putObject(
|
|
222
203
|
MINIO_BUCKET_NAME,
|
|
223
204
|
generateMinioPath(directoryName, hashedFilename),
|
|
224
|
-
|
|
205
|
+
readable,
|
|
225
206
|
undefined,
|
|
226
207
|
metaData,
|
|
227
208
|
);
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import util from 'util';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
1
|
import { createLogger } from '@unchainedshop/logger';
|
|
5
|
-
|
|
6
|
-
const readFile = util.promisify(fs.readFile);
|
|
7
|
-
|
|
8
|
-
const { DATATRANS_API_MOCKS_PATH } = process.env;
|
|
2
|
+
const { MOCK_APIS } = process.env;
|
|
9
3
|
|
|
10
4
|
const logger = createLogger('unchained:datatrans');
|
|
11
5
|
|
|
@@ -14,12 +8,15 @@ export default (
|
|
|
14
8
|
merchantId: string,
|
|
15
9
|
secret: string,
|
|
16
10
|
): ((path: string, body: unknown) => Promise<Response>) => {
|
|
17
|
-
if (
|
|
11
|
+
if (MOCK_APIS) {
|
|
18
12
|
return async (path): Promise<Response> => {
|
|
19
13
|
try {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
const { default: json } = await import(
|
|
15
|
+
`${import.meta.dirname}/../../../../tests/mock/datatrans/${path}.json`,
|
|
16
|
+
{
|
|
17
|
+
with: { type: 'json' },
|
|
18
|
+
}
|
|
19
|
+
);
|
|
23
20
|
return {
|
|
24
21
|
json: async () => json,
|
|
25
22
|
status: json?.error ? 500 : 204,
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import util from 'util';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
1
|
import { createLogger } from '@unchainedshop/logger';
|
|
5
2
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const { PAYREXX_API_MOCKS_PATH } = process.env;
|
|
3
|
+
const { MOCK_APIS } = process.env;
|
|
9
4
|
|
|
10
5
|
const logger = createLogger('unchained:payrexx');
|
|
11
6
|
|
|
@@ -14,17 +9,19 @@ export default (
|
|
|
14
9
|
instance: string = null,
|
|
15
10
|
secret: string = null,
|
|
16
11
|
): ((path: string, method: 'GET' | 'DELETE' | 'PUT' | 'POST', data?: any) => Promise<Response>) => {
|
|
17
|
-
if (
|
|
12
|
+
if (MOCK_APIS) {
|
|
18
13
|
return async (path): Promise<Response> => {
|
|
19
14
|
try {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
const { default: jsonData } = await import(
|
|
16
|
+
`${import.meta.dirname}/../../../../tests/mock/payrexx/${path}.json`,
|
|
17
|
+
{
|
|
18
|
+
with: { type: 'json' },
|
|
19
|
+
}
|
|
20
|
+
);
|
|
24
21
|
return {
|
|
25
22
|
json: async () => jsonData,
|
|
26
|
-
text: async () =>
|
|
27
|
-
ok:
|
|
23
|
+
text: async () => JSON.stringify(jsonData?.error),
|
|
24
|
+
ok: true,
|
|
28
25
|
status: jsonData?.error ? 500 : 204,
|
|
29
26
|
} as any;
|
|
30
27
|
} catch (error) {
|
|
@@ -14,9 +14,11 @@ export const initStripeClient = async (): Promise<StripeType> => {
|
|
|
14
14
|
logger.warn('STRIPE_SECRET is not set, skipping initialization');
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
|
+
// eslint-disable-next-line
|
|
18
|
+
// @ts-ignore
|
|
17
19
|
const { default: Stripe } = await import('stripe');
|
|
18
20
|
stripe = new Stripe(STRIPE_SECRET, {
|
|
19
|
-
apiVersion: '2024-
|
|
21
|
+
apiVersion: '2024-12-18.acacia',
|
|
20
22
|
});
|
|
21
23
|
return stripe;
|
|
22
24
|
};
|
|
@@ -2,11 +2,10 @@ import {
|
|
|
2
2
|
OrderDiscountDirector,
|
|
3
3
|
OrderDiscountAdapter,
|
|
4
4
|
OrderDiscountConfiguration,
|
|
5
|
-
UnchainedCore,
|
|
6
5
|
IDiscountAdapter,
|
|
7
6
|
} from '@unchainedshop/core';
|
|
8
7
|
|
|
9
|
-
export const HundredOff: IDiscountAdapter<OrderDiscountConfiguration
|
|
8
|
+
export const HundredOff: IDiscountAdapter<OrderDiscountConfiguration> = {
|
|
10
9
|
...OrderDiscountAdapter,
|
|
11
10
|
|
|
12
11
|
key: 'shop.unchained.discount.100-off',
|
|
@@ -2,11 +2,10 @@ import {
|
|
|
2
2
|
OrderDiscountDirector,
|
|
3
3
|
OrderDiscountAdapter,
|
|
4
4
|
ProductDiscountConfiguration,
|
|
5
|
-
UnchainedCore,
|
|
6
5
|
IDiscountAdapter,
|
|
7
6
|
} from '@unchainedshop/core';
|
|
8
7
|
|
|
9
|
-
export const HalfPriceManual: IDiscountAdapter<ProductDiscountConfiguration
|
|
8
|
+
export const HalfPriceManual: IDiscountAdapter<ProductDiscountConfiguration> = {
|
|
10
9
|
...OrderDiscountAdapter,
|
|
11
10
|
|
|
12
11
|
key: 'shop.unchained.discount.half-price-manual',
|
|
@@ -3,10 +3,9 @@ import {
|
|
|
3
3
|
OrderDiscountAdapter,
|
|
4
4
|
ProductDiscountConfiguration,
|
|
5
5
|
IDiscountAdapter,
|
|
6
|
-
UnchainedCore,
|
|
7
6
|
} from '@unchainedshop/core';
|
|
8
7
|
|
|
9
|
-
export const HalfPrice: IDiscountAdapter<ProductDiscountConfiguration
|
|
8
|
+
export const HalfPrice: IDiscountAdapter<ProductDiscountConfiguration> = {
|
|
10
9
|
...OrderDiscountAdapter,
|
|
11
10
|
|
|
12
11
|
key: 'shop.unchained.discount.half-price',
|
package/src/worker/email.ts
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import { mkdtemp, writeFile } from 'fs/promises';
|
|
2
|
-
import { join, isAbsolute } from 'path';
|
|
3
|
-
import { tmpdir } from 'os';
|
|
4
1
|
import { WorkerDirector, WorkerAdapter, IWorkerAdapter } from '@unchainedshop/core';
|
|
5
|
-
import open from 'open';
|
|
6
2
|
import nodemailer from 'nodemailer';
|
|
7
3
|
|
|
8
4
|
export const checkEmailInterceptionEnabled = () => {
|
|
9
5
|
return process.env.NODE_ENV !== 'production' && !process.env.UNCHAINED_DISABLE_EMAIL_INTERCEPTION;
|
|
10
6
|
};
|
|
11
7
|
|
|
12
|
-
const buildLink = ({ filename, content, href, contentType, encoding, path }) => {
|
|
8
|
+
const buildLink = async ({ filename, content, href, contentType, encoding, path }) => {
|
|
13
9
|
if (path) {
|
|
14
|
-
return `<a href="
|
|
10
|
+
return `<a href="file:/${path.startsWith('/') ? path : `${process.cwd()}/${path}`}">${filename}</a>`;
|
|
15
11
|
}
|
|
16
12
|
if (href) {
|
|
17
13
|
return `<a href="${href}">${filename}</a>`;
|
|
@@ -23,8 +19,12 @@ const buildLink = ({ filename, content, href, contentType, encoding, path }) =>
|
|
|
23
19
|
};
|
|
24
20
|
|
|
25
21
|
const openInBrowser = async (options) => {
|
|
26
|
-
|
|
22
|
+
// eslint-disable-next-line
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
const { default: open, apps } = await import('open');
|
|
25
|
+
|
|
27
26
|
const messageBody = options.html || options.text.replace(/(\r\n|\n|\r)/gm, '<br/>');
|
|
27
|
+
const attachmentLinks = await Promise.all((options.attachments || []).map(buildLink));
|
|
28
28
|
const content = `
|
|
29
29
|
<!DOCTYPE html>
|
|
30
30
|
<html lang="en" xmlns="https://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
|
@@ -40,16 +40,17 @@ const openInBrowser = async (options) => {
|
|
|
40
40
|
<b>Reply-To: </b>${options.replyTo}<br/>
|
|
41
41
|
<br/>
|
|
42
42
|
<b>subject: </b>${options.subject}<br/>
|
|
43
|
-
<b>attachments: </b>${
|
|
43
|
+
<b>attachments: </b>${attachmentLinks.join(', ')}<br/>
|
|
44
44
|
<hr/>
|
|
45
45
|
${messageBody}
|
|
46
46
|
</body>
|
|
47
47
|
</html>`;
|
|
48
48
|
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
const base64 = Buffer.from(content).toString('base64');
|
|
50
|
+
const dataUri = `data:text/html;base64,${base64}`;
|
|
51
|
+
|
|
52
|
+
await open(dataUri, { app: [{ name: apps.chrome }, { name: apps.firefox }, { name: apps.browser }] });
|
|
53
|
+
return true;
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
const EmailWorkerPlugin: IWorkerAdapter<
|
|
@@ -87,8 +88,12 @@ const EmailWorkerPlugin: IWorkerAdapter<
|
|
|
87
88
|
...rest,
|
|
88
89
|
};
|
|
89
90
|
if (checkEmailInterceptionEnabled()) {
|
|
90
|
-
await openInBrowser(sendMailOptions);
|
|
91
|
-
return {
|
|
91
|
+
const opened = await openInBrowser(sendMailOptions);
|
|
92
|
+
return {
|
|
93
|
+
success: opened,
|
|
94
|
+
result: opened ? { intercepted: true } : undefined,
|
|
95
|
+
error: !opened ? { message: "Interception failed due to missing package 'open'" } : undefined,
|
|
96
|
+
};
|
|
92
97
|
}
|
|
93
98
|
if (!process.env.MAIL_URL) {
|
|
94
99
|
return {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"transactionId": "payment_alias_authorized",
|
|
3
|
+
"type": "payment",
|
|
4
|
+
"status": "authorized",
|
|
5
|
+
"currency": "CHF",
|
|
6
|
+
"refno": "MTExMTExMjIyMjI=",
|
|
7
|
+
"refno2": "user",
|
|
8
|
+
"paymentMethod": "VIS",
|
|
9
|
+
"detail": {
|
|
10
|
+
"authorize": {
|
|
11
|
+
"amount": 30000,
|
|
12
|
+
"acquirerAuthorizationCode": "131704"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"language": "de",
|
|
16
|
+
"card": {
|
|
17
|
+
"alias": "70119122433810042",
|
|
18
|
+
"masked": "424242xxxxxx4242",
|
|
19
|
+
"expiryMonth": "12",
|
|
20
|
+
"expiryYear": "21",
|
|
21
|
+
"info": {
|
|
22
|
+
"brand": "VISA CREDIT",
|
|
23
|
+
"type": "credit",
|
|
24
|
+
"usage": "consumer",
|
|
25
|
+
"country": "GB",
|
|
26
|
+
"issuer": "DATATRANS"
|
|
27
|
+
},
|
|
28
|
+
"3D": {
|
|
29
|
+
"authenticationResponse": "D"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"history": [
|
|
33
|
+
{
|
|
34
|
+
"action": "init",
|
|
35
|
+
"source": "api",
|
|
36
|
+
"date": "2021-09-03T11:16:50Z",
|
|
37
|
+
"success": true,
|
|
38
|
+
"ip": "212.232.234.26"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"action": "authorize",
|
|
42
|
+
"source": "redirect",
|
|
43
|
+
"date": "2021-09-03T11:17:04Z",
|
|
44
|
+
"success": true,
|
|
45
|
+
"ip": "212.232.234.26"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"transactionId": "card_check_authorized",
|
|
3
|
+
"type": "card_check",
|
|
4
|
+
"status": "authorized",
|
|
5
|
+
"currency": "CHF",
|
|
6
|
+
"refno": "ZDRkNGQ0ZDRkNA==",
|
|
7
|
+
"refno2": "user",
|
|
8
|
+
"paymentMethod": "VIS",
|
|
9
|
+
"detail": {
|
|
10
|
+
"authorize": {
|
|
11
|
+
"acquirerAuthorizationCode": "131704"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"language": "de",
|
|
15
|
+
"card": {
|
|
16
|
+
"alias": "70119122433810042",
|
|
17
|
+
"masked": "424242xxxxxx4242",
|
|
18
|
+
"expiryMonth": "12",
|
|
19
|
+
"expiryYear": "21",
|
|
20
|
+
"info": {
|
|
21
|
+
"brand": "VISA CREDIT",
|
|
22
|
+
"type": "credit",
|
|
23
|
+
"usage": "consumer",
|
|
24
|
+
"country": "GB",
|
|
25
|
+
"issuer": "DATATRANS"
|
|
26
|
+
},
|
|
27
|
+
"3D": {
|
|
28
|
+
"authenticationResponse": "D"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"history": [
|
|
32
|
+
{
|
|
33
|
+
"action": "init",
|
|
34
|
+
"source": "api",
|
|
35
|
+
"date": "2021-09-03T11:16:50Z",
|
|
36
|
+
"success": true,
|
|
37
|
+
"ip": "212.232.234.26"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"action": "authorize",
|
|
41
|
+
"source": "redirect",
|
|
42
|
+
"date": "2021-09-03T11:17:04Z",
|
|
43
|
+
"success": true,
|
|
44
|
+
"ip": "212.232.234.26"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|