@unchainedshop/plugins 1.1.5 → 1.2.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.
Files changed (89) hide show
  1. package/jest.config.js +5 -0
  2. package/lib/files/gridfs/gridfs-adapter.js +1 -1
  3. package/lib/files/gridfs/gridfs-adapter.js.map +1 -1
  4. package/lib/files/gridfs/gridfs-webhook.d.ts +2 -1
  5. package/lib/files/gridfs/gridfs-webhook.js +5 -4
  6. package/lib/files/gridfs/gridfs-webhook.js.map +1 -1
  7. package/lib/files/gridfs/index.d.ts +3 -3
  8. package/lib/files/gridfs/index.js.map +1 -1
  9. package/lib/files/gridfs/promisePipe.d.ts +1 -1
  10. package/lib/files/gridfs/promisePipe.js.map +1 -1
  11. package/lib/files/gridfs/sign.d.ts +1 -1
  12. package/lib/files/gridfs/sign.js.map +1 -1
  13. package/lib/files/minio/minio-adapter.js +1 -1
  14. package/lib/files/minio/minio-adapter.js.map +1 -1
  15. package/lib/files/minio/minio-webhook.d.ts +2 -1
  16. package/lib/files/minio/minio-webhook.js +30 -28
  17. package/lib/files/minio/minio-webhook.js.map +1 -1
  18. package/lib/payment/apple-iap/adapter.d.ts +2 -1
  19. package/lib/payment/apple-iap/adapter.js +94 -92
  20. package/lib/payment/apple-iap/adapter.js.map +1 -1
  21. package/lib/payment/apple-iap/index.d.ts +2 -1
  22. package/lib/payment/apple-iap/index.js +2 -1
  23. package/lib/payment/apple-iap/index.js.map +1 -1
  24. package/lib/payment/bity/adapter.d.ts +2 -1
  25. package/lib/payment/bity/adapter.js +50 -48
  26. package/lib/payment/bity/adapter.js.map +1 -1
  27. package/lib/payment/bity/index.d.ts +2 -1
  28. package/lib/payment/bity/index.js +2 -1
  29. package/lib/payment/bity/index.js.map +1 -1
  30. package/lib/payment/braintree.js +2 -2
  31. package/lib/payment/braintree.js.map +1 -1
  32. package/lib/payment/cryptopay.d.ts +2 -1
  33. package/lib/payment/cryptopay.js +60 -58
  34. package/lib/payment/cryptopay.js.map +1 -1
  35. package/lib/payment/datatrans-v2/index.d.ts +2 -1
  36. package/lib/payment/datatrans-v2/index.js +2 -1
  37. package/lib/payment/datatrans-v2/index.js.map +1 -1
  38. package/lib/payment/datatrans-v2/middleware.d.ts +2 -1
  39. package/lib/payment/datatrans-v2/middleware.js +99 -97
  40. package/lib/payment/datatrans-v2/middleware.js.map +1 -1
  41. package/lib/payment/paypal-checkout.js +1 -1
  42. package/lib/payment/paypal-checkout.js.map +1 -1
  43. package/lib/payment/postfinance-checkout/index.d.ts +2 -1
  44. package/lib/payment/postfinance-checkout/index.js +2 -1
  45. package/lib/payment/postfinance-checkout/index.js.map +1 -1
  46. package/lib/payment/postfinance-checkout/middleware.d.ts +2 -1
  47. package/lib/payment/postfinance-checkout/middleware.js +36 -34
  48. package/lib/payment/postfinance-checkout/middleware.js.map +1 -1
  49. package/lib/payment/stripe.d.ts +2 -1
  50. package/lib/payment/stripe.js +63 -60
  51. package/lib/payment/stripe.js.map +1 -1
  52. package/lib/payment/worldline-saferpay/worldline-saferpay-client/index.d.ts +3 -3
  53. package/lib/pricing/product-price-ECB-interbank-exchange.js +1 -1
  54. package/lib/pricing/product-price-ECB-interbank-exchange.js.map +1 -1
  55. package/lib/pricing/product-price-cryptopay.d.ts +2 -1
  56. package/lib/pricing/product-price-cryptopay.js +20 -18
  57. package/lib/pricing/product-price-cryptopay.js.map +1 -1
  58. package/lib/worker/ZombieKillerWorker.js.map +1 -1
  59. package/lib/worker/email.js +1 -0
  60. package/lib/worker/email.js.map +1 -1
  61. package/package.json +30 -24
  62. package/src/files/gridfs/gridfs-adapter.ts +1 -1
  63. package/src/files/gridfs/gridfs-webhook.ts +62 -0
  64. package/src/files/gridfs/{index.js → index.ts} +0 -0
  65. package/src/files/gridfs/{promisePipe.js → promisePipe.ts} +0 -0
  66. package/src/files/gridfs/{sign.js → sign.ts} +0 -0
  67. package/src/files/minio/minio-adapter.ts +1 -1
  68. package/src/files/minio/minio-webhook.js +33 -30
  69. package/src/payment/apple-iap/adapter.ts +113 -110
  70. package/src/payment/apple-iap/index.ts +2 -1
  71. package/src/payment/bity/adapter.ts +53 -51
  72. package/src/payment/bity/index.ts +2 -1
  73. package/src/payment/braintree.ts +2 -2
  74. package/src/payment/cryptopay.ts +69 -67
  75. package/src/payment/datatrans-v2/index.ts +3 -1
  76. package/src/payment/datatrans-v2/middleware.ts +129 -123
  77. package/src/payment/paypal-checkout.ts +1 -1
  78. package/src/payment/postfinance-checkout/index.ts +3 -1
  79. package/src/payment/postfinance-checkout/middleware.ts +42 -40
  80. package/src/payment/stripe.ts +82 -74
  81. package/src/payment/worldline-saferpay/worldline-saferpay-client/index.ts +3 -3
  82. package/src/pricing/product-discount.ts +1 -1
  83. package/src/pricing/product-price-ECB-interbank-exchange.ts +1 -1
  84. package/src/pricing/product-price-cryptopay.ts +20 -18
  85. package/src/worker/ZombieKillerWorker.ts +5 -5
  86. package/src/worker/email.ts +1 -0
  87. package/tsconfig.json +26 -5
  88. package/src/files/gridfs/gridfs-webhook.js +0 -60
  89. package/tsconfig.build.json +0 -26
@@ -1,3 +1,4 @@
1
- import './adapter';
1
+ import setupAppleIAP from './adapter';
2
2
 
3
+ export default setupAppleIAP;
3
4
  export { configureAppleTransactionsModule } from './module/configureAppleTransactionsModule';
@@ -29,10 +29,10 @@ const {
29
29
  BITY_BANK_ACCOUNT_NAME,
30
30
  BITY_BANK_ACCOUNT_ZIP,
31
31
  BITY_API_ENDPOINT = 'https://exchange.api.bity.com',
32
- BITY_OAUTH_INIT_PATH = '/graphql/bity-auth',
33
- BITY_OAUTH_REDIRECT_URI = 'http://localhost:4010/graphql/bity',
32
+ BITY_OAUTH_INIT_PATH = '/payment/bity-auth',
33
+ BITY_OAUTH_REDIRECT_URI = 'http://localhost:4010/payment/bity',
34
34
  BITY_OAUTH_STATE = 'unchained',
35
- BITY_OAUTH_PATH = '/graphql/bity',
35
+ BITY_OAUTH_PATH = '/payment/bity',
36
36
  } = process.env;
37
37
 
38
38
  const createBityAuth = () => {
@@ -185,56 +185,58 @@ const estimateBityOrder = async (data: any, context: Context) => {
185
185
  return response.json();
186
186
  };
187
187
 
188
- useMiddlewareWithCurrentContext(BITY_OAUTH_INIT_PATH, async (req, res) => {
189
- if (req.method === 'GET') {
190
- try {
191
- const resolvedContext = req.unchainedContext;
192
- await checkAction(resolvedContext, actions.managePaymentProviders);
193
-
194
- const bityAuthClient = createBityAuth();
195
- const uri = bityAuthClient.code.getUri();
196
- logger.info(`Bity Webhook: Login ${uri}`);
197
- res.writeHead(302, {
198
- Location: uri,
199
- });
200
- res.end();
201
- return;
202
- } catch (e) {
203
- logger.warn(`Bity Webhook: Failed with ${e.message}`);
204
- res.writeHead(503);
205
- res.end(JSON.stringify(e));
206
- return;
188
+ export default (app) => {
189
+ useMiddlewareWithCurrentContext(app, BITY_OAUTH_INIT_PATH, async (req, res) => {
190
+ if (req.method === 'GET') {
191
+ try {
192
+ const resolvedContext = req.unchainedContext;
193
+ await checkAction(resolvedContext, actions.managePaymentProviders);
194
+
195
+ const bityAuthClient = createBityAuth();
196
+ const uri = bityAuthClient.code.getUri();
197
+ logger.info(`Bity Webhook: Login ${uri}`);
198
+ res.writeHead(302, {
199
+ Location: uri,
200
+ });
201
+ res.end();
202
+ return;
203
+ } catch (e) {
204
+ logger.warn(`Bity Webhook: Failed with ${e.message}`);
205
+ res.writeHead(503);
206
+ res.end(JSON.stringify(e));
207
+ return;
208
+ }
207
209
  }
208
- }
209
- res.writeHead(404);
210
- res.end();
211
- });
212
-
213
- useMiddlewareWithCurrentContext(BITY_OAUTH_PATH, async (req, res, next) => {
214
- bodyParser.urlencoded({ extended: false })(req, res, next);
215
- });
216
-
217
- useMiddlewareWithCurrentContext(BITY_OAUTH_PATH, async (req, res) => {
218
- if (req.method === 'GET') {
219
- try {
220
- const resolvedContext = req.unchainedContext as Context;
221
- await checkAction(resolvedContext, actions.managePaymentProviders);
222
- const bityAuthClient = createBityAuth();
223
- const user = await bityAuthClient.code.getToken(req.originalUrl);
224
- await upsertBityCredentials(user, resolvedContext);
225
- res.writeHead(200);
226
- res.end('Bity Credentials Setup Complete');
227
- return;
228
- } catch (e) {
229
- logger.warn(`Bity Webhook: Failed with ${e.message}`);
230
- res.writeHead(503);
231
- res.end(JSON.stringify(e));
232
- return;
210
+ res.writeHead(404);
211
+ res.end();
212
+ });
213
+
214
+ useMiddlewareWithCurrentContext(app, BITY_OAUTH_PATH, async (req, res, next) => {
215
+ bodyParser.urlencoded({ extended: false })(req, res, next);
216
+ });
217
+
218
+ useMiddlewareWithCurrentContext(app, BITY_OAUTH_PATH, async (req, res) => {
219
+ if (req.method === 'GET') {
220
+ try {
221
+ const resolvedContext = req.unchainedContext as Context;
222
+ await checkAction(resolvedContext, actions.managePaymentProviders);
223
+ const bityAuthClient = createBityAuth();
224
+ const user = await bityAuthClient.code.getToken(req.originalUrl);
225
+ await upsertBityCredentials(user, resolvedContext);
226
+ res.writeHead(200);
227
+ res.end('Bity Credentials Setup Complete');
228
+ return;
229
+ } catch (e) {
230
+ logger.warn(`Bity Webhook: Failed with ${e.message}`);
231
+ res.writeHead(503);
232
+ res.end(JSON.stringify(e));
233
+ return;
234
+ }
233
235
  }
234
- }
235
- res.writeHead(404);
236
- res.end();
237
- });
236
+ res.writeHead(404);
237
+ res.end();
238
+ });
239
+ };
238
240
 
239
241
  let bityAuthClient;
240
242
  const loadToken = async (context: Context) => {
@@ -1,3 +1,4 @@
1
- import './adapter';
1
+ import setupBity from './adapter';
2
2
 
3
+ export default setupBity;
3
4
  export { configureBityModule } from './module/configureBityModule';
@@ -91,7 +91,7 @@ const BraintreeDirect: IPaymentAdapter = {
91
91
  },
92
92
 
93
93
  sign: async () => {
94
- const braintree = require('braintree'); // eslint-disable-line
94
+ const braintree = (await import('braintree')).default; // eslint-disable-line
95
95
  const gateway = getGateway(braintree);
96
96
  const result = await gateway.clientToken.generate({});
97
97
  if (result.success) {
@@ -105,7 +105,7 @@ const BraintreeDirect: IPaymentAdapter = {
105
105
  const { order } = params.paymentContext;
106
106
  if (!paypalPaymentMethodNonce)
107
107
  throw new Error('You have to provide paypalPaymentMethodNonce in paymentContext');
108
- const braintree = require('braintree'); // eslint-disable-line
108
+ const braintree = (await import('braintree')).default; // eslint-disable-line
109
109
  const gateway = getGateway(braintree);
110
110
  const address = order.billingAddress || {};
111
111
  const pricing = modules.orders.pricingSheet(order);
@@ -14,7 +14,7 @@ const logger = createLogger('unchained:core-payment:cryptopay');
14
14
 
15
15
  const {
16
16
  CRYPTOPAY_SECRET,
17
- CRYPTOPAY_WEBHOOK_PATH = '/graphql/cryptopay',
17
+ CRYPTOPAY_WEBHOOK_PATH = '/payment/cryptopay',
18
18
  CRYPTOPAY_BTC_XPUB,
19
19
  CRYPTOPAY_ETH_XPUB,
20
20
  CRYPTOPAY_BTC_TESTNET = false,
@@ -30,79 +30,81 @@ enum CryptopayCurrencies { // eslint-disable-line
30
30
  const MAX_RATE_AGE = parseInt(CRYPTOPAY_MAX_RATE_AGE, 10);
31
31
  const MAX_ALLOWED_DIFF = parseFloat(CRYPTOPAY_MAX_CONV_DIFF); // Accept payments when the converted amount differs by adapterActions much (in percent)
32
32
 
33
- useMiddlewareWithCurrentContext(CRYPTOPAY_WEBHOOK_PATH, bodyParser.json());
34
-
35
- useMiddlewareWithCurrentContext(CRYPTOPAY_WEBHOOK_PATH, async (request, response) => {
36
- // Return a 200 response to acknowledge receipt of the event
37
- const resolvedContext = request.unchainedContext as Context;
38
- const { currency, contract, decimals, address, amount, secret } = request.body;
39
- if (secret !== CRYPTOPAY_SECRET) {
40
- logger.warn(`Cryptopay Plugin: Invalid Cryptopay Secret provided`);
41
- response.end(JSON.stringify({ success: false }));
42
- return;
43
- }
44
- const orderPayment = await resolvedContext.modules.orders.payments.findOrderPaymentByContextData({
45
- context: { currency, address },
46
- });
47
- if (orderPayment) {
48
- if (currency === CryptopayCurrencies.ETH && contract && contract !== '') {
49
- const ERC20CurrencyCount = await resolvedContext.modules.currencies.count({
50
- includeInactive: false,
51
- contractAddress: contract,
52
- });
53
- if (!ERC20CurrencyCount) {
54
- logger.warn(`Cryptopay Plugin: ERC20 token address ${contract} not whitelisted.`);
55
- response.end(JSON.stringify({ success: false }));
56
- return;
57
- }
33
+ export default (app) => {
34
+ useMiddlewareWithCurrentContext(app, CRYPTOPAY_WEBHOOK_PATH, bodyParser.json());
35
+
36
+ useMiddlewareWithCurrentContext(app, CRYPTOPAY_WEBHOOK_PATH, async (request, response) => {
37
+ // Return a 200 response to acknowledge receipt of the event
38
+ const resolvedContext = request.unchainedContext as Context;
39
+ const { currency, contract, decimals, address, amount, secret } = request.body;
40
+ if (secret !== CRYPTOPAY_SECRET) {
41
+ logger.warn(`Cryptopay Plugin: Invalid Cryptopay Secret provided`);
42
+ response.end(JSON.stringify({ success: false }));
43
+ return;
58
44
  }
59
- const order = await resolvedContext.modules.orders.findOrder({
60
- orderId: orderPayment.orderId,
45
+ const orderPayment = await resolvedContext.modules.orders.payments.findOrderPaymentByContextData({
46
+ context: { currency, address },
61
47
  });
62
- const pricing = OrderPricingSheet({
63
- calculation: order.calculation,
64
- currency: order.currency,
65
- });
66
- const totalAmount = pricing?.total({ useNetPrice: false }).amount;
67
- let convertedAmount: number;
68
- if (order.currency === currency) {
69
- convertedAmount = amount / 10 ** (decimals - 8); // All crypto native prices denoted with 8 decimals
70
- } else {
71
- // Need to convert
72
- const rate = await resolvedContext.modules.products.prices.rates.getRate(
73
- order.currency,
74
- contract && contract !== '' ? contract : currency, // Convert to the smart contract if given
75
- MAX_RATE_AGE,
76
- );
77
- if (rate) {
78
- // We assume that we are converting to a fiat currency here (with 2 decimals).
79
- // Paying an order with prices in crypto in another crypto is not supported.
80
- convertedAmount = Math.round((amount / 10 ** decimals) * rate * 100);
48
+ if (orderPayment) {
49
+ if (currency === CryptopayCurrencies.ETH && contract && contract !== '') {
50
+ const ERC20CurrencyCount = await resolvedContext.modules.currencies.count({
51
+ includeInactive: false,
52
+ contractAddress: contract,
53
+ });
54
+ if (!ERC20CurrencyCount) {
55
+ logger.warn(`Cryptopay Plugin: ERC20 token address ${contract} not whitelisted.`);
56
+ response.end(JSON.stringify({ success: false }));
57
+ return;
58
+ }
59
+ }
60
+ const order = await resolvedContext.modules.orders.findOrder({
61
+ orderId: orderPayment.orderId,
62
+ });
63
+ const pricing = OrderPricingSheet({
64
+ calculation: order.calculation,
65
+ currency: order.currency,
66
+ });
67
+ const totalAmount = pricing?.total({ useNetPrice: false }).amount;
68
+ let convertedAmount: number;
69
+ if (order.currency === currency) {
70
+ convertedAmount = amount / 10 ** (decimals - 8); // All crypto native prices denoted with 8 decimals
71
+ } else {
72
+ // Need to convert
73
+ const rate = await resolvedContext.modules.products.prices.rates.getRate(
74
+ order.currency,
75
+ contract && contract !== '' ? contract : currency, // Convert to the smart contract if given
76
+ MAX_RATE_AGE,
77
+ );
78
+ if (rate) {
79
+ // We assume that we are converting to a fiat currency here (with 2 decimals).
80
+ // Paying an order with prices in crypto in another crypto is not supported.
81
+ convertedAmount = Math.round((amount / 10 ** decimals) * rate * 100);
82
+ }
83
+ }
84
+ if (convertedAmount && convertedAmount >= totalAmount * (1 - MAX_ALLOWED_DIFF)) {
85
+ await resolvedContext.modules.orders.checkout(
86
+ order._id,
87
+ {
88
+ transactionContext: { address },
89
+ paymentContext: { address },
90
+ },
91
+ resolvedContext,
92
+ );
93
+ response.end(JSON.stringify({ success: true }));
94
+ } else {
95
+ logger.warn(
96
+ `Cryptopay Plugin: OrderPayment ${orderPayment._id} not marked as paid. Converted amount is ${convertedAmount}`,
97
+ );
98
+ response.end(JSON.stringify({ success: false }));
81
99
  }
82
- }
83
- if (convertedAmount && convertedAmount >= totalAmount * (1 - MAX_ALLOWED_DIFF)) {
84
- await resolvedContext.modules.orders.checkout(
85
- order._id,
86
- {
87
- transactionContext: { address },
88
- paymentContext: { address },
89
- },
90
- resolvedContext,
91
- );
92
- response.end(JSON.stringify({ success: true }));
93
100
  } else {
94
- logger.warn(
95
- `Cryptopay Plugin: OrderPayment ${orderPayment._id} not marked as paid. Converted amount is ${convertedAmount}`,
101
+ logger.info(
102
+ `Cryptopay Plugin: No orderPayment with address ${address} and currency ${currency} found`,
96
103
  );
97
104
  response.end(JSON.stringify({ success: false }));
98
105
  }
99
- } else {
100
- logger.info(
101
- `Cryptopay Plugin: No orderPayment with address ${address} and currency ${currency} found`,
102
- );
103
- response.end(JSON.stringify({ success: false }));
104
- }
105
- });
106
+ });
107
+ };
106
108
 
107
109
  const Cryptopay: IPaymentAdapter = {
108
110
  ...PaymentAdapter,
@@ -10,12 +10,14 @@ import type {
10
10
  StatusResponseSuccess,
11
11
  ValidateResponseSuccess,
12
12
  } from './api/types';
13
- import './middleware';
13
+ import setupDatatrans from './middleware';
14
14
  import parseRegistrationData from './parseRegistrationData';
15
15
  import roundedAmountFromOrder from './roundedAmountFromOrder';
16
16
 
17
17
  const logger = createLogger('unchained:core-payment:datatrans');
18
18
 
19
+ export default setupDatatrans;
20
+
19
21
  // v2
20
22
  const { DATATRANS_SECRET, DATATRANS_SIGN_KEY, DATATRANS_API_ENDPOINT, DATATRANS_MERCHANT_ID } =
21
23
  process.env;
@@ -17,131 +17,137 @@ const logger = createLogger('unchained:core-payment:datatrans');
17
17
 
18
18
  const { postUrl, cancelUrl, errorUrl, successUrl, returnUrl } = getPaths(true);
19
19
 
20
- useMiddlewareWithCurrentContext(
21
- postUrl,
22
- bodyParser.text({
23
- type: 'application/json',
24
- }),
25
- );
26
-
27
- useMiddlewareWithCurrentContext(cancelUrl, bodyParser.urlencoded({ extended: false }));
28
-
29
- useMiddlewareWithCurrentContext(errorUrl, bodyParser.urlencoded({ extended: false }));
30
-
31
- useMiddlewareWithCurrentContext(successUrl, bodyParser.urlencoded({ extended: false }));
32
-
33
- useMiddlewareWithCurrentContext(returnUrl, bodyParser.urlencoded({ extended: false }));
34
-
35
- useMiddlewareWithCurrentContext(postUrl, async (req, res) => {
36
- const resolvedContext = req.unchainedContext as Context;
37
- const { services, modules } = resolvedContext;
38
- const signature = req.headers['datatrans-signature'];
39
- if (req.method === 'POST' && signature) {
40
- const [rawTimestamp, rawHash] = signature.split(',');
41
- const [, hash] = rawHash.split('=');
42
- const [, timestamp] = rawTimestamp.split('=');
43
-
44
- const comparableSignature = generateSignature({
45
- security: DATATRANS_SECURITY,
46
- signKey: DATATRANS_SIGN2_KEY || DATATRANS_SIGN_KEY,
47
- })(timestamp, req.body);
48
-
49
- if (hash !== comparableSignature) {
50
- logger.error(`Datatrans Plugin: Hash mismatch: ${signature} / ${comparableSignature}`, req.body);
51
- res.writeHead(403);
52
- res.end('Hash mismatch');
53
- return;
54
- }
20
+ export default (app) => {
21
+ useMiddlewareWithCurrentContext(
22
+ app,
23
+ postUrl,
24
+ bodyParser.text({
25
+ type: 'application/json',
26
+ }),
27
+ );
28
+
29
+ useMiddlewareWithCurrentContext(app, cancelUrl, bodyParser.urlencoded({ extended: false }));
30
+
31
+ useMiddlewareWithCurrentContext(app, errorUrl, bodyParser.urlencoded({ extended: false }));
32
+
33
+ useMiddlewareWithCurrentContext(app, successUrl, bodyParser.urlencoded({ extended: false }));
34
+
35
+ useMiddlewareWithCurrentContext(app, returnUrl, bodyParser.urlencoded({ extended: false }));
36
+
37
+ useMiddlewareWithCurrentContext(app, postUrl, async (req, res) => {
38
+ const resolvedContext = req.unchainedContext as Context;
39
+ const { services, modules } = resolvedContext;
40
+ const signature = req.headers['datatrans-signature'];
41
+ if (req.method === 'POST' && signature) {
42
+ const [rawTimestamp, rawHash] = signature.split(',');
43
+ const [, hash] = rawHash.split('=');
44
+ const [, timestamp] = rawTimestamp.split('=');
45
+
46
+ const comparableSignature = generateSignature({
47
+ security: DATATRANS_SECURITY,
48
+ signKey: DATATRANS_SIGN2_KEY || DATATRANS_SIGN_KEY,
49
+ })(timestamp, req.body);
50
+
51
+ if (hash !== comparableSignature) {
52
+ logger.error(`Datatrans Plugin: Hash mismatch: ${signature} / ${comparableSignature}`, req.body);
53
+ res.writeHead(403);
54
+ res.end('Hash mismatch');
55
+ return;
56
+ }
55
57
 
56
- const transaction: StatusResponseSuccess = JSON.parse(req.body) as StatusResponseSuccess;
57
-
58
- if (transaction.status === 'authorized') {
59
- const userId = transaction.refno2;
60
- const referenceId = Buffer.from(transaction.refno, 'base64').toString('hex');
61
-
62
- try {
63
- if (transaction.type === 'card_check') {
64
- const paymentProviderId = referenceId;
65
- const paymentCredentials = await services.payment.registerPaymentCredentials(
66
- paymentProviderId,
67
- { transactionContext: { transactionId: transaction.transactionId } },
68
- { ...resolvedContext, userId },
69
- );
70
- logger.info(`Datatrans Webhook: Unchained registered payment credentials for ${userId}`, {
71
- userId,
72
- });
73
- res.writeHead(200);
74
- res.end(JSON.stringify(paymentCredentials));
58
+ const transaction: StatusResponseSuccess = JSON.parse(req.body) as StatusResponseSuccess;
59
+
60
+ if (transaction.status === 'authorized') {
61
+ const userId = transaction.refno2;
62
+ const referenceId = Buffer.from(transaction.refno, 'base64').toString('hex');
63
+
64
+ try {
65
+ if (transaction.type === 'card_check') {
66
+ const paymentProviderId = referenceId;
67
+ const paymentCredentials = await services.payment.registerPaymentCredentials(
68
+ paymentProviderId,
69
+ { transactionContext: { transactionId: transaction.transactionId } },
70
+ { ...resolvedContext, userId },
71
+ );
72
+ logger.info(`Datatrans Webhook: Unchained registered payment credentials for ${userId}`, {
73
+ userId,
74
+ });
75
+ res.writeHead(200);
76
+ res.end(JSON.stringify(paymentCredentials));
77
+ return;
78
+ }
79
+ if (transaction.type === 'payment') {
80
+ const orderPaymentId = referenceId;
81
+ const orderPayment = await modules.orders.payments.findOrderPayment({
82
+ orderPaymentId,
83
+ });
84
+ if (!orderPayment) throw new Error(`Order Payment with id ${orderPaymentId} not found`);
85
+
86
+ const order = await modules.orders.checkout(
87
+ orderPayment.orderId,
88
+ { paymentContext: { transactionId: transaction.transactionId } },
89
+ { ...resolvedContext, userId },
90
+ );
91
+ res.writeHead(200);
92
+ logger.info(
93
+ `Datatrans Webhook: Unchained confirmed checkout for order ${order.orderNumber}`,
94
+ {
95
+ orderId: order._id,
96
+ },
97
+ );
98
+ res.end(JSON.stringify(order));
99
+ return;
100
+ }
101
+ } catch (e) {
102
+ logger.error(`Datatrans Webhook: Unchained rejected to checkout with message`, e);
103
+ res.writeHead(500);
104
+ res.end(JSON.stringify(e));
75
105
  return;
76
106
  }
77
- if (transaction.type === 'payment') {
78
- const orderPaymentId = referenceId;
79
- const orderPayment = await modules.orders.payments.findOrderPayment({
80
- orderPaymentId,
81
- });
82
- if (!orderPayment) throw new Error(`Order Payment with id ${orderPaymentId} not found`);
83
-
84
- const order = await modules.orders.checkout(
85
- orderPayment.orderId,
86
- { paymentContext: { transactionId: transaction.transactionId } },
87
- resolvedContext,
88
- );
89
- res.writeHead(200);
90
- logger.info(`Datatrans Webhook: Unchained confirmed checkout for order ${order.orderNumber}`, {
91
- orderId: order._id,
92
- });
93
- res.end(JSON.stringify(order));
94
- return;
95
- }
96
- } catch (e) {
97
- logger.error(`Datatrans Webhook: Unchained rejected to checkout with message`, e);
98
- res.writeHead(500);
99
- res.end(JSON.stringify(e));
100
- return;
101
107
  }
102
108
  }
103
- }
104
- res.writeHead(404);
105
- res.end();
106
- });
107
-
108
- useMiddlewareWithCurrentContext(successUrl, async (req, res) => {
109
- if (req.method === 'GET') {
110
- const { datatransTrxId } = req.query;
111
- res.end(`Payment successful\nTransaction ID: ${datatransTrxId}`);
112
- return;
113
- }
114
- res.writeHead(404);
115
- res.end();
116
- });
117
-
118
- useMiddlewareWithCurrentContext(errorUrl, async (req, res) => {
119
- if (req.method === 'GET') {
120
- const { datatransTrxId } = req.query;
121
- res.end(`Payment error\nTransaction ID: ${datatransTrxId}`);
122
- return;
123
- }
124
- res.writeHead(404);
125
- res.end();
126
- });
127
-
128
- useMiddlewareWithCurrentContext(cancelUrl, async (req, res) => {
129
- if (req.method === 'GET') {
130
- const { datatransTrxId } = req.query;
131
- res.end(`Payment cancelled\nTransaction ID: ${datatransTrxId}`);
132
- return;
133
- }
134
- res.writeHead(404);
135
- res.end();
136
- });
137
-
138
- useMiddlewareWithCurrentContext(returnUrl, async (req, res) => {
139
- if (req.method === 'GET') {
140
- const { datatransTrxId } = req.query;
141
- res.end(
142
- `Secure Fields Payment authenticated\nTransaction ID: ${datatransTrxId}\nNeeds authorization`,
143
- );
144
- }
145
- res.writeHead(404);
146
- res.end();
147
- });
109
+ res.writeHead(404);
110
+ res.end();
111
+ });
112
+
113
+ useMiddlewareWithCurrentContext(app, successUrl, async (req, res) => {
114
+ if (req.method === 'GET') {
115
+ const { datatransTrxId } = req.query;
116
+ res.end(`Payment successful\nTransaction ID: ${datatransTrxId}`);
117
+ return;
118
+ }
119
+ res.writeHead(404);
120
+ res.end();
121
+ });
122
+
123
+ useMiddlewareWithCurrentContext(app, errorUrl, async (req, res) => {
124
+ if (req.method === 'GET') {
125
+ const { datatransTrxId } = req.query;
126
+ res.end(`Payment error\nTransaction ID: ${datatransTrxId}`);
127
+ return;
128
+ }
129
+ res.writeHead(404);
130
+ res.end();
131
+ });
132
+
133
+ useMiddlewareWithCurrentContext(app, cancelUrl, async (req, res) => {
134
+ if (req.method === 'GET') {
135
+ const { datatransTrxId } = req.query;
136
+ res.end(`Payment cancelled\nTransaction ID: ${datatransTrxId}`);
137
+ return;
138
+ }
139
+ res.writeHead(404);
140
+ res.end();
141
+ });
142
+
143
+ useMiddlewareWithCurrentContext(app, returnUrl, async (req, res) => {
144
+ if (req.method === 'GET') {
145
+ const { datatransTrxId } = req.query;
146
+ res.end(
147
+ `Secure Fields Payment authenticated\nTransaction ID: ${datatransTrxId}\nNeeds authorization`,
148
+ );
149
+ }
150
+ res.writeHead(404);
151
+ res.end();
152
+ });
153
+ };
@@ -2,7 +2,7 @@ import { IPaymentAdapter } from '@unchainedshop/types/payments';
2
2
  import { PaymentDirector, PaymentAdapter, PaymentError } from '@unchainedshop/core-payment';
3
3
  import { createLogger } from '@unchainedshop/logger';
4
4
 
5
- const checkoutNodeJssdk = require('@paypal/checkout-server-sdk'); // eslint-disable-line
5
+ import checkoutNodeJssdk from '@paypal/checkout-server-sdk'; // eslint-disable-line
6
6
 
7
7
  const logger = createLogger('unchained:core-payment');
8
8
 
@@ -17,9 +17,11 @@ import {
17
17
  voidTransaction,
18
18
  } from './api';
19
19
  import { orderIsPaid } from './utils';
20
- import './middleware';
20
+ import setupPostfinance from './middleware';
21
21
  import { CompletionModes, IntegrationModes, SignResponse } from './types';
22
22
 
23
+ export default setupPostfinance;
24
+
23
25
  const {
24
26
  PFCHECKOUT_SPACE_ID,
25
27
  PFCHECKOUT_USER_ID,