@unchainedshop/plugins 1.1.4 → 1.1.9

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 (69) hide show
  1. package/lib/files/gridfs/gridfs-adapter.js +1 -1
  2. package/lib/files/gridfs/gridfs-adapter.js.map +1 -1
  3. package/lib/files/gridfs/gridfs-webhook.d.ts +2 -1
  4. package/lib/files/gridfs/gridfs-webhook.js +3 -3
  5. package/lib/files/gridfs/gridfs-webhook.js.map +1 -1
  6. package/lib/files/minio/minio-webhook.d.ts +2 -1
  7. package/lib/files/minio/minio-webhook.js +31 -29
  8. package/lib/files/minio/minio-webhook.js.map +1 -1
  9. package/lib/payment/apple-iap/adapter.d.ts +2 -1
  10. package/lib/payment/apple-iap/adapter.js +94 -92
  11. package/lib/payment/apple-iap/adapter.js.map +1 -1
  12. package/lib/payment/apple-iap/db/AppleTransactionsCollection.d.ts +2 -2
  13. package/lib/payment/apple-iap/index.d.ts +2 -1
  14. package/lib/payment/apple-iap/index.js +2 -1
  15. package/lib/payment/apple-iap/index.js.map +1 -1
  16. package/lib/payment/bity/adapter.d.ts +2 -1
  17. package/lib/payment/bity/adapter.js +50 -48
  18. package/lib/payment/bity/adapter.js.map +1 -1
  19. package/lib/payment/bity/db/BityCredentialsCollection.d.ts +2 -2
  20. package/lib/payment/bity/index.d.ts +2 -1
  21. package/lib/payment/bity/index.js +2 -1
  22. package/lib/payment/bity/index.js.map +1 -1
  23. package/lib/payment/cryptopay.d.ts +2 -1
  24. package/lib/payment/cryptopay.js +60 -58
  25. package/lib/payment/cryptopay.js.map +1 -1
  26. package/lib/payment/datatrans-v2/index.d.ts +2 -1
  27. package/lib/payment/datatrans-v2/index.js +2 -1
  28. package/lib/payment/datatrans-v2/index.js.map +1 -1
  29. package/lib/payment/datatrans-v2/middleware.d.ts +2 -1
  30. package/lib/payment/datatrans-v2/middleware.js +100 -98
  31. package/lib/payment/datatrans-v2/middleware.js.map +1 -1
  32. package/lib/payment/datatrans-v2/roundedAmountFromOrder.d.ts +0 -2
  33. package/lib/payment/paypal-checkout.js +1 -1
  34. package/lib/payment/paypal-checkout.js.map +1 -1
  35. package/lib/payment/postfinance-checkout/index.d.ts +2 -1
  36. package/lib/payment/postfinance-checkout/index.js +2 -1
  37. package/lib/payment/postfinance-checkout/index.js.map +1 -1
  38. package/lib/payment/postfinance-checkout/middleware.d.ts +2 -1
  39. package/lib/payment/postfinance-checkout/middleware.js +36 -34
  40. package/lib/payment/postfinance-checkout/middleware.js.map +1 -1
  41. package/lib/payment/postfinance-checkout/utils.d.ts +0 -1
  42. package/lib/payment/stripe.d.ts +2 -1
  43. package/lib/payment/stripe.js +63 -60
  44. package/lib/payment/stripe.js.map +1 -1
  45. package/lib/pricing/product-price-cryptopay.d.ts +2 -1
  46. package/lib/pricing/product-price-cryptopay.js +20 -18
  47. package/lib/pricing/product-price-cryptopay.js.map +1 -1
  48. package/lib/pricing/utils/cache.d.ts +1 -2
  49. package/lib/worker/ZombieKillerWorker.js.map +1 -1
  50. package/license +274 -0
  51. package/package.json +20 -19
  52. package/src/files/gridfs/gridfs-adapter.ts +1 -1
  53. package/src/files/gridfs/gridfs-webhook.js +42 -41
  54. package/src/files/minio/minio-webhook.js +34 -31
  55. package/src/payment/apple-iap/adapter.ts +113 -110
  56. package/src/payment/apple-iap/index.ts +2 -1
  57. package/src/payment/bity/adapter.ts +51 -49
  58. package/src/payment/bity/index.ts +2 -1
  59. package/src/payment/cryptopay.ts +69 -67
  60. package/src/payment/datatrans-v2/index.ts +3 -1
  61. package/src/payment/datatrans-v2/middleware.ts +130 -124
  62. package/src/payment/paypal-checkout.ts +1 -1
  63. package/src/payment/postfinance-checkout/index.ts +3 -1
  64. package/src/payment/postfinance-checkout/middleware.ts +42 -40
  65. package/src/payment/stripe.ts +82 -74
  66. package/src/pricing/product-price-cryptopay.ts +20 -18
  67. package/src/worker/ZombieKillerWorker.ts +5 -5
  68. package/tsconfig.build.json +13 -5
  69. package/lib/worker/MessageWorker.d.ts +0 -10
@@ -2,7 +2,7 @@ import { Context } from '@unchainedshop/types/api';
2
2
  import { IPaymentAdapter } from '@unchainedshop/types/payments';
3
3
  import bodyParser from 'body-parser';
4
4
  import fetch from 'isomorphic-unfetch';
5
- import { useMiddlewareWithCurrentContext } from 'meteor/unchained:api';
5
+ import { useMiddlewareWithCurrentContext } from '@unchainedshop/api';
6
6
  import { EnrollmentStatus } from '@unchainedshop/core-enrollments';
7
7
  import { PaymentAdapter, PaymentDirector, PaymentError } from '@unchainedshop/core-payment';
8
8
  import { createLogger } from '@unchainedshop/logger';
@@ -88,44 +88,89 @@ const fixPeriods = async (
88
88
  );
89
89
  };
90
90
 
91
- useMiddlewareWithCurrentContext(
92
- APPLE_IAP_WEBHOOK_PATH,
93
- bodyParser.json({
94
- strict: false,
95
- }),
96
- );
97
-
98
- useMiddlewareWithCurrentContext(APPLE_IAP_WEBHOOK_PATH, async (req, res) => {
99
- if (req.method === 'POST') {
100
- try {
101
- const resolvedContext = req.unchainedContext as Context;
102
- const { modules, services } = resolvedContext;
103
- const responseBody = req.body || {};
104
- if (responseBody.password !== APPLE_IAP_SHARED_SECRET) {
105
- throw new Error('shared secret not valid');
106
- }
91
+ export default (app) => {
92
+ useMiddlewareWithCurrentContext(
93
+ app,
94
+ APPLE_IAP_WEBHOOK_PATH,
95
+ bodyParser.json({
96
+ strict: false,
97
+ }),
98
+ );
107
99
 
108
- const transactions = responseBody?.unified_receipt?.latest_receipt_info; // eslint-disable-line
109
- const latestTransaction = transactions[0];
100
+ useMiddlewareWithCurrentContext(app, APPLE_IAP_WEBHOOK_PATH, async (req, res) => {
101
+ if (req.method === 'POST') {
102
+ try {
103
+ const resolvedContext = req.unchainedContext as Context;
104
+ const { modules, services } = resolvedContext;
105
+ const responseBody = req.body || {};
106
+ if (responseBody.password !== APPLE_IAP_SHARED_SECRET) {
107
+ throw new Error('shared secret not valid');
108
+ }
110
109
 
111
- if (responseBody.notification_type === AppleNotificationTypes.INITIAL_BUY) {
112
- // Find the cart to checkout
113
- const orderPayment = await modules.orders.payments.findOrderPaymentByContextData({
114
- context: {
115
- 'meta.transactionIdentifier': latestTransaction.transaction_id,
116
- },
117
- });
110
+ const transactions = responseBody?.unified_receipt?.latest_receipt_info; // eslint-disable-line
111
+ const latestTransaction = transactions[0];
118
112
 
119
- if (!orderPayment) throw new Error('Could not find any matching order payment');
120
- const order = await modules.orders.findOrder({
121
- orderId: orderPayment.orderId,
122
- });
113
+ if (responseBody.notification_type === AppleNotificationTypes.INITIAL_BUY) {
114
+ // Find the cart to checkout
115
+ const orderPayment = await modules.orders.payments.findOrderPaymentByContextData({
116
+ context: {
117
+ 'meta.transactionIdentifier': latestTransaction.transaction_id,
118
+ },
119
+ });
120
+
121
+ if (!orderPayment) throw new Error('Could not find any matching order payment');
122
+ const order = await modules.orders.findOrder({
123
+ orderId: orderPayment.orderId,
124
+ });
125
+
126
+ if (modules.orders.isCart(order)) {
127
+ // checkout if is cart, else just ignore because the cart is already checked out
128
+ // through submission of the receipt with GraphQL
129
+ const checkedOut = await modules.orders.checkout(
130
+ order._id,
131
+ {
132
+ transactionContext: {
133
+ receiptData: responseBody?.unified_receipt?.latest_receipt, // eslint-disable-line
134
+ },
135
+ },
136
+ resolvedContext,
137
+ );
138
+ const orderId = checkedOut._id;
139
+ const enrollment = await modules.enrollments.findEnrollment({
140
+ orderId,
141
+ });
142
+ await fixPeriods(
143
+ {
144
+ transactionId: latestTransaction.original_transaction_id,
145
+ transactions,
146
+ enrollmentId: enrollment._id,
147
+ orderId,
148
+ },
149
+ resolvedContext,
150
+ );
123
151
 
124
- if (modules.orders.isCart(order)) {
125
- // checkout if is cart, else just ignore because the cart is already checked out
126
- // through submission of the receipt with GraphQL
127
- const checkedOut = await modules.orders.checkout(
128
- order._id,
152
+ logger.info(`Apple IAP Webhook: Confirmed checkout for order ${checkedOut.orderNumber}`, {
153
+ orderId: checkedOut._id,
154
+ });
155
+ }
156
+ } else {
157
+ // Just store payment credentials, use the enrollments paymentProvider reference and
158
+ // let the job do the rest
159
+ const originalOrderPayment = await modules.orders.payments.findOrderPaymentByContextData({
160
+ context: {
161
+ 'meta.transactionIdentifier': latestTransaction.original_transaction_id,
162
+ },
163
+ });
164
+ if (!originalOrderPayment) throw new Error('Could not find any matching order payment');
165
+ const originalOrder = await modules.orders.findOrder({
166
+ orderId: originalOrderPayment.orderId,
167
+ });
168
+ const enrollment = await modules.enrollments.findEnrollment({
169
+ orderId: originalOrder._id,
170
+ });
171
+
172
+ await services.payment.registerPaymentCredentials(
173
+ enrollment.payment.paymentProviderId,
129
174
  {
130
175
  transactionContext: {
131
176
  receiptData: responseBody?.unified_receipt?.latest_receipt, // eslint-disable-line
@@ -133,97 +178,55 @@ useMiddlewareWithCurrentContext(APPLE_IAP_WEBHOOK_PATH, async (req, res) => {
133
178
  },
134
179
  resolvedContext,
135
180
  );
136
- const orderId = checkedOut._id;
137
- const enrollment = await modules.enrollments.findEnrollment({
138
- orderId,
139
- });
181
+
140
182
  await fixPeriods(
141
183
  {
142
184
  transactionId: latestTransaction.original_transaction_id,
143
185
  transactions,
144
186
  enrollmentId: enrollment._id,
145
- orderId,
187
+ orderId: originalOrder._id,
146
188
  },
147
189
  resolvedContext,
148
190
  );
149
191
 
150
- logger.info(`Apple IAP Webhook: Confirmed checkout for order ${checkedOut.orderNumber}`, {
151
- orderId: checkedOut._id,
152
- });
153
- }
154
- } else {
155
- // Just store payment credentials, use the enrollments paymentProvider reference and
156
- // let the job do the rest
157
- const originalOrderPayment = await modules.orders.payments.findOrderPaymentByContextData({
158
- context: {
159
- 'meta.transactionIdentifier': latestTransaction.original_transaction_id,
160
- },
161
- });
162
- if (!originalOrderPayment) throw new Error('Could not find any matching order payment');
163
- const originalOrder = await modules.orders.findOrder({
164
- orderId: originalOrderPayment.orderId,
165
- });
166
- const enrollment = await modules.enrollments.findEnrollment({
167
- orderId: originalOrder._id,
168
- });
169
-
170
- await services.payment.registerPaymentCredentials(
171
- enrollment.payment.paymentProviderId,
172
- {
173
- transactionContext: {
174
- receiptData: responseBody?.unified_receipt?.latest_receipt, // eslint-disable-line
175
- },
176
- },
177
- resolvedContext,
178
- );
179
-
180
- await fixPeriods(
181
- {
182
- transactionId: latestTransaction.original_transaction_id,
183
- transactions,
184
- enrollmentId: enrollment._id,
185
- orderId: originalOrder._id,
186
- },
187
- resolvedContext,
188
- );
189
-
190
- logger.info(
191
- `Apple IAP Webhook: Processed notification for ${latestTransaction.original_transaction_id} and type ${responseBody.notification_type}`,
192
- );
192
+ logger.info(
193
+ `Apple IAP Webhook: Processed notification for ${latestTransaction.original_transaction_id} and type ${responseBody.notification_type}`,
194
+ );
193
195
 
194
- if (responseBody.notification_type === AppleNotificationTypes.DID_RECOVER) {
195
- if (
196
- enrollment.status !== EnrollmentStatus.TERMINATED &&
197
- responseBody.auto_renew_status === 'false'
198
- ) {
199
- await modules.enrollments.terminateEnrollment(enrollment, {}, resolvedContext);
196
+ if (responseBody.notification_type === AppleNotificationTypes.DID_RECOVER) {
197
+ if (
198
+ enrollment.status !== EnrollmentStatus.TERMINATED &&
199
+ responseBody.auto_renew_status === 'false'
200
+ ) {
201
+ await modules.enrollments.terminateEnrollment(enrollment, {}, resolvedContext);
202
+ }
200
203
  }
201
- }
202
204
 
203
- if (responseBody.notification_type === AppleNotificationTypes.DID_CHANGE_RENEWAL_STATUS) {
204
- if (
205
- enrollment.status !== EnrollmentStatus.TERMINATED &&
206
- responseBody.auto_renew_status === 'false'
207
- ) {
208
- await modules.enrollments.terminateEnrollment(enrollment, {}, resolvedContext);
205
+ if (responseBody.notification_type === AppleNotificationTypes.DID_CHANGE_RENEWAL_STATUS) {
206
+ if (
207
+ enrollment.status !== EnrollmentStatus.TERMINATED &&
208
+ responseBody.auto_renew_status === 'false'
209
+ ) {
210
+ await modules.enrollments.terminateEnrollment(enrollment, {}, resolvedContext);
211
+ }
209
212
  }
213
+ logger.info(`Apple IAP Webhook: Updated enrollment from Apple`);
210
214
  }
211
- logger.info(`Apple IAP Webhook: Updated enrollment from Apple`);
212
- }
213
215
 
214
- res.writeHead(200);
215
- res.end();
216
- return;
217
- } catch (e) {
218
- logger.warn(`Apple IAP Webhook: ${e.message}`, e);
219
- res.writeHead(503);
220
- res.end(JSON.stringify(e));
221
- return;
216
+ res.writeHead(200);
217
+ res.end();
218
+ return;
219
+ } catch (e) {
220
+ logger.warn(`Apple IAP Webhook: ${e.message}`, e);
221
+ res.writeHead(503);
222
+ res.end(JSON.stringify(e));
223
+ return;
224
+ }
222
225
  }
223
- }
224
- res.writeHead(404);
225
- res.end();
226
- });
226
+ res.writeHead(404);
227
+ res.end();
228
+ });
229
+ };
227
230
 
228
231
  const AppleIAP: IPaymentAdapter = {
229
232
  ...PaymentAdapter,
@@ -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';
@@ -5,7 +5,7 @@ import { createLogger } from '@unchainedshop/logger';
5
5
 
6
6
  import { OrderPricingSheet } from '@unchainedshop/core-orders';
7
7
  import bodyParser from 'body-parser';
8
- import { acl, roles, useMiddlewareWithCurrentContext } from 'meteor/unchained:api';
8
+ import { acl, roles, useMiddlewareWithCurrentContext } from '@unchainedshop/api';
9
9
  import crypto from 'crypto';
10
10
  import fetch from 'isomorphic-unfetch';
11
11
  import ClientOAuth2 from '@unchainedshop/client-oauth2';
@@ -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';
@@ -1,7 +1,7 @@
1
1
  import { Context } from '@unchainedshop/types/api';
2
2
  import { IPaymentAdapter } from '@unchainedshop/types/payments';
3
3
  import bodyParser from 'body-parser';
4
- import { useMiddlewareWithCurrentContext } from 'meteor/unchained:api';
4
+ import { useMiddlewareWithCurrentContext } from '@unchainedshop/api';
5
5
  import { PaymentAdapter, PaymentDirector, PaymentError } from '@unchainedshop/core-payment';
6
6
  import { OrderPricingSheet } from '@unchainedshop/core-orders';
7
7
  import { ethers } from 'ethers';
@@ -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;