@unchainedshop/plugins 2.0.0-beta6 → 2.0.0-beta8
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/delivery/pick-mup.d.ts +1 -0
- package/lib/delivery/pick-mup.js +1 -1
- package/lib/delivery/pick-mup.js.map +1 -1
- package/lib/files/gridfs/gridfs-adapter.d.ts +1 -0
- package/lib/files/gridfs/gridfs-adapter.js +0 -1
- package/lib/files/gridfs/gridfs-adapter.js.map +1 -1
- package/lib/files/gridfs/gridfs-webhook.d.ts +1 -2
- package/lib/files/gridfs/gridfs-webhook.js +2 -6
- package/lib/files/gridfs/gridfs-webhook.js.map +1 -1
- package/lib/files/minio/minio-adapter.d.ts +2 -1
- package/lib/files/minio/minio-adapter.js +13 -7
- package/lib/files/minio/minio-adapter.js.map +1 -1
- package/lib/files/minio/minio-webhook.d.ts +1 -2
- package/lib/files/minio/minio-webhook.js +24 -37
- package/lib/files/minio/minio-webhook.js.map +1 -1
- package/lib/payment/apple-iap/adapter.d.ts +2 -2
- package/lib/payment/apple-iap/adapter.js +89 -97
- package/lib/payment/apple-iap/adapter.js.map +1 -1
- package/lib/payment/apple-iap/db/AppleTransactionsCollection.d.ts +1 -1
- package/lib/payment/apple-iap/index.d.ts +2 -3
- package/lib/payment/apple-iap/index.js +2 -3
- package/lib/payment/apple-iap/index.js.map +1 -1
- package/lib/payment/braintree.js +14 -12
- package/lib/payment/braintree.js.map +1 -1
- package/lib/payment/cryptopay/db/CryptopayTransactions.d.ts +1 -1
- package/lib/payment/cryptopay/index.d.ts +2 -3
- package/lib/payment/cryptopay/index.js +2 -3
- package/lib/payment/cryptopay/index.js.map +1 -1
- package/lib/payment/cryptopay/middleware.d.ts +1 -2
- package/lib/payment/cryptopay/middleware.js +64 -69
- package/lib/payment/cryptopay/middleware.js.map +1 -1
- package/lib/payment/datatrans-v2/api/makeFetcher.d.ts +1 -1
- package/lib/payment/datatrans-v2/api/makeFetcher.js +1 -1
- package/lib/payment/datatrans-v2/api/makeFetcher.js.map +1 -1
- package/lib/payment/datatrans-v2/getPaths.d.ts +2 -2
- package/lib/payment/datatrans-v2/getPaths.js +7 -7
- package/lib/payment/datatrans-v2/getPaths.js.map +1 -1
- package/lib/payment/datatrans-v2/index.d.ts +1 -2
- package/lib/payment/datatrans-v2/index.js +1 -2
- package/lib/payment/datatrans-v2/index.js.map +1 -1
- package/lib/payment/datatrans-v2/middleware.d.ts +1 -2
- package/lib/payment/datatrans-v2/middleware.js +54 -102
- package/lib/payment/datatrans-v2/middleware.js.map +1 -1
- package/lib/payment/postfinance-checkout/index.d.ts +1 -2
- package/lib/payment/postfinance-checkout/index.js +1 -2
- package/lib/payment/postfinance-checkout/index.js.map +1 -1
- package/lib/payment/postfinance-checkout/middleware.d.ts +1 -2
- package/lib/payment/postfinance-checkout/middleware.js +31 -37
- package/lib/payment/postfinance-checkout/middleware.js.map +1 -1
- package/lib/payment/postfinance-checkout/types.d.ts +3 -3
- package/lib/payment/stripe.d.ts +1 -2
- package/lib/payment/stripe.js +55 -60
- package/lib/payment/stripe.js.map +1 -1
- package/lib/payment/worldline-saferpay/worldline-saferpay-client/api/SaferpayConnection.d.ts +1 -0
- package/lib/payment/worldline-saferpay/worldline-saferpay-client/api/SaferpayConnection.js +4 -3
- package/lib/payment/worldline-saferpay/worldline-saferpay-client/api/SaferpayConnection.js.map +1 -1
- package/lib/payment/worldline-saferpay/worldline-saferpay-client/models/PaymentMethods.d.ts +1 -1
- package/lib/payment/worldline-saferpay/worldline-saferpay-client/models/Transaction.d.ts +2 -2
- package/lib/plugins-index.d.ts +64 -0
- package/lib/plugins-index.js +100 -0
- package/lib/plugins-index.js.map +1 -1
- package/lib/warehousing/eth-minter.js +27 -40
- package/lib/warehousing/eth-minter.js.map +1 -1
- package/lib/worker/http-request.d.ts +1 -0
- package/lib/worker/http-request.js +0 -1
- package/lib/worker/http-request.js.map +1 -1
- package/lib/worker/update-coinbase-rates.d.ts +1 -0
- package/lib/worker/update-coinbase-rates.js +0 -1
- package/lib/worker/update-coinbase-rates.js.map +1 -1
- package/lib/worker/update-ecb-rates.d.ts +1 -0
- package/lib/worker/update-ecb-rates.js +0 -1
- package/lib/worker/update-ecb-rates.js.map +1 -1
- package/lib/worker/zombie-killer.js +13 -28
- package/lib/worker/zombie-killer.js.map +1 -1
- package/package.json +27 -26
- package/src/delivery/pick-mup.ts +1 -1
- package/src/files/gridfs/gridfs-adapter.ts +3 -2
- package/src/files/gridfs/gridfs-webhook.ts +40 -46
- package/src/files/minio/minio-adapter.ts +13 -8
- package/src/files/minio/minio-webhook.ts +35 -0
- package/src/payment/apple-iap/adapter.ts +104 -120
- package/src/payment/apple-iap/index.ts +2 -4
- package/src/payment/braintree.ts +14 -12
- package/src/payment/cryptopay/index.ts +2 -4
- package/src/payment/cryptopay/middleware.ts +65 -74
- package/src/payment/datatrans-v2/api/makeFetcher.ts +1 -1
- package/src/payment/datatrans-v2/getPaths.ts +12 -11
- package/src/payment/datatrans-v2/index.ts +2 -3
- package/src/payment/datatrans-v2/middleware.ts +66 -133
- package/src/payment/postfinance-checkout/index.ts +2 -3
- package/src/payment/postfinance-checkout/middleware.ts +37 -45
- package/src/payment/stripe.ts +68 -83
- package/src/payment/worldline-saferpay/worldline-saferpay-client/api/SaferpayConnection.ts +4 -4
- package/src/plugins-index.ts +151 -0
- package/src/warehousing/eth-minter.ts +32 -48
- package/src/worker/http-request.ts +1 -1
- package/src/worker/update-coinbase-rates.ts +1 -1
- package/src/worker/update-ecb-rates.ts +1 -1
- package/src/worker/zombie-killer.ts +33 -30
- package/lib/payment/bity/adapter.d.ts +0 -2
- package/lib/payment/bity/adapter.js +0 -320
- package/lib/payment/bity/adapter.js.map +0 -1
- package/lib/payment/bity/db/BityCredentialsCollection.d.ts +0 -11
- package/lib/payment/bity/db/BityCredentialsCollection.js +0 -5
- package/lib/payment/bity/db/BityCredentialsCollection.js.map +0 -1
- package/lib/payment/bity/index.d.ts +0 -3
- package/lib/payment/bity/index.js +0 -4
- package/lib/payment/bity/index.js.map +0 -1
- package/lib/payment/bity/module/configureBityModule.d.ts +0 -11
- package/lib/payment/bity/module/configureBityModule.js +0 -33
- package/lib/payment/bity/module/configureBityModule.js.map +0 -1
- package/src/files/minio/minio-webhook.js +0 -54
- package/src/payment/bity/adapter.ts +0 -421
- package/src/payment/bity/db/BityCredentialsCollection.ts +0 -17
- package/src/payment/bity/index.ts +0 -4
- package/src/payment/bity/module/configureBityModule.ts +0 -46
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configureBityModule.js","sourceRoot":"","sources":["../../../../src/payment/bity/module/configureBityModule.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAuB,MAAM,iCAAiC,CAAC;AAQjG,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,EAAE,EAAc,EAAc,EAAE;IACpE,MAAM,eAAe,GAAG,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAEtD,OAAO;QACL,mBAAmB,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;YAC5C,OAAO,eAAe,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE;YACvC,MAAM,eAAe,CAAC,SAAS,CAC7B;gBACE,UAAU,EAAE,GAAG,CAAC,UAAU;aAC3B,EACD;gBACE,IAAI,EAAE;oBACJ,IAAI,EAAE;wBACJ,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;wBACf,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,aAAa;qBACtC;oBACD,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,OAAO,EAAE,IAAI,IAAI,EAAE;oBACnB,SAAS,EAAE,MAAM;iBAClB;gBACD,YAAY,EAAE;oBACZ,GAAG,EAAE,kBAAkB,EAAE;oBACzB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,OAAO,EAAE,IAAI,IAAI,EAAE;oBACnB,SAAS,EAAE,MAAM;iBAClB;aACF,CACF,CAAC;YAEF,OAAO,GAAG,CAAC,UAAU,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { useMiddlewareWithCurrentContext } from '@unchainedshop/api';
|
|
2
|
-
import { log, LogLevel } from '@unchainedshop/logger';
|
|
3
|
-
import bodyParser from 'body-parser';
|
|
4
|
-
|
|
5
|
-
const { MINIO_WEBHOOK_AUTH_TOKEN } = process.env;
|
|
6
|
-
|
|
7
|
-
const isAuthorized = ({ authorization = '' }) => {
|
|
8
|
-
const [type, token] = authorization.split(' ');
|
|
9
|
-
return type === 'Bearer' && token === MINIO_WEBHOOK_AUTH_TOKEN;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default (app) => {
|
|
13
|
-
useMiddlewareWithCurrentContext(
|
|
14
|
-
app,
|
|
15
|
-
'/minio/',
|
|
16
|
-
bodyParser.json({
|
|
17
|
-
strict: false,
|
|
18
|
-
}),
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
useMiddlewareWithCurrentContext(app, '/minio/', async (req, res) => {
|
|
22
|
-
try {
|
|
23
|
-
if (req.method === 'POST' && req.body) {
|
|
24
|
-
const { headers } = req;
|
|
25
|
-
const { Records = [], EventName } = req.body;
|
|
26
|
-
if (EventName === 's3:ObjectCreated:Put' && isAuthorized(headers)) {
|
|
27
|
-
const [{ s3 }] = Records;
|
|
28
|
-
const { object } = s3;
|
|
29
|
-
const { size, contentType: type } = object;
|
|
30
|
-
const [fileId] = object.key.split('.');
|
|
31
|
-
const { services } = req.unchainedContext;
|
|
32
|
-
await services.files.linkFile({ fileId, type, size }, req.unchainedContext);
|
|
33
|
-
res.writeHead(200);
|
|
34
|
-
res.end();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
res.writeHead(404);
|
|
39
|
-
res.end();
|
|
40
|
-
return;
|
|
41
|
-
} catch (e) {
|
|
42
|
-
log(e.message, { level: LogLevel.Error });
|
|
43
|
-
res.writeHead(503);
|
|
44
|
-
res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/*
|
|
50
|
-
|
|
51
|
-
curl -X PUT -T /Users/pozylon/Desktop/Bildschirmfoto\ 2022-02-17\ um\ 16.47.22.png http://localhost:4010/gridfs/3e0cd78ac07f0028890ce36c391057dd0c5fb46f4c147fb73e54bd8a7ffee389/user-avatars/avatar.png?e=1645883865878&s=e7466b30039593e5790e23cab92878e0144289c3710344a55b78c9a916e2f78c
|
|
52
|
-
curl -X PUT -T /Users/pozylon/Desktop/Bildschirmfoto\ 2022-02-17\ um\ 16.47.22.png https://minio.dev.shared.ucc.dev/unchained-test-bucket/user-avatars/9aedd551499b2850e9483b07cd4c8cff7ad1d710f49933c183861bf40183bc5a?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=unchained-test%2F20220225%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220225T140957Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=22807026db1210370170cd5cf49bfbb9e86010425c9d1834a56e049faf39b368
|
|
53
|
-
|
|
54
|
-
*/
|
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
import { PaymentDirector, PaymentAdapter, PaymentError } from '@unchainedshop/core-payment';
|
|
2
|
-
|
|
3
|
-
import { IPaymentAdapter } from '@unchainedshop/types/payments';
|
|
4
|
-
import { createLogger } from '@unchainedshop/logger';
|
|
5
|
-
|
|
6
|
-
import { OrderPricingSheet } from '@unchainedshop/core-orders';
|
|
7
|
-
import bodyParser from 'body-parser';
|
|
8
|
-
import { acl, roles, useMiddlewareWithCurrentContext } from '@unchainedshop/api';
|
|
9
|
-
import crypto from 'crypto';
|
|
10
|
-
import fetch from 'node-fetch';
|
|
11
|
-
import ClientOAuth2 from '@unchainedshop/client-oauth2';
|
|
12
|
-
import { Context } from '@unchainedshop/types/api';
|
|
13
|
-
import { BityModule } from './module/configureBityModule';
|
|
14
|
-
|
|
15
|
-
const logger = createLogger('unchained:core-payment:bity');
|
|
16
|
-
|
|
17
|
-
const { checkAction } = acl;
|
|
18
|
-
const { actions } = roles;
|
|
19
|
-
|
|
20
|
-
let currentToken;
|
|
21
|
-
|
|
22
|
-
const {
|
|
23
|
-
BITY_CLIENT_ID,
|
|
24
|
-
BITY_CLIENT_SECRET,
|
|
25
|
-
BITY_BANK_ACCOUNT_IBAN,
|
|
26
|
-
BITY_BANK_ACCOUNT_ADDRESS,
|
|
27
|
-
BITY_BANK_ACCOUNT_CITY,
|
|
28
|
-
BITY_BANK_ACCOUNT_COUNTRY,
|
|
29
|
-
BITY_BANK_ACCOUNT_NAME,
|
|
30
|
-
BITY_BANK_ACCOUNT_ZIP,
|
|
31
|
-
BITY_API_ENDPOINT = 'https://exchange.api.bity.com',
|
|
32
|
-
BITY_OAUTH_INIT_PATH = '/payment/bity-auth',
|
|
33
|
-
BITY_OAUTH_REDIRECT_URI = 'http://localhost:4010/payment/bity',
|
|
34
|
-
BITY_OAUTH_STATE = 'unchained',
|
|
35
|
-
BITY_OAUTH_PATH = '/payment/bity',
|
|
36
|
-
} = process.env;
|
|
37
|
-
|
|
38
|
-
const createBityAuth = () => {
|
|
39
|
-
if (!BITY_CLIENT_ID) throw new Error('Bity plugin is not setup');
|
|
40
|
-
|
|
41
|
-
return new ClientOAuth2({
|
|
42
|
-
clientId: BITY_CLIENT_ID,
|
|
43
|
-
clientSecret: BITY_CLIENT_SECRET,
|
|
44
|
-
accessTokenUri: 'https://connect.bity.com/oauth2/token',
|
|
45
|
-
authorizationUri: 'https://connect.bity.com/oauth2/auth',
|
|
46
|
-
redirectUri: BITY_OAUTH_REDIRECT_URI,
|
|
47
|
-
state: BITY_OAUTH_STATE,
|
|
48
|
-
scopes: [
|
|
49
|
-
'https://auth.bity.com/scopes/exchange.place',
|
|
50
|
-
'https://auth.bity.com/scopes/exchange.history',
|
|
51
|
-
'offline_access',
|
|
52
|
-
],
|
|
53
|
-
// eslint-disable-next-line
|
|
54
|
-
// @ts-ignore
|
|
55
|
-
sendClientCredentialsInBody: true,
|
|
56
|
-
});
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const upsertBityCredentials = async (user, context: Context) => {
|
|
60
|
-
currentToken = user;
|
|
61
|
-
|
|
62
|
-
const iv = crypto.randomBytes(16);
|
|
63
|
-
const key = crypto
|
|
64
|
-
.createHash('sha256')
|
|
65
|
-
.update(String(BITY_CLIENT_SECRET))
|
|
66
|
-
.digest('base64')
|
|
67
|
-
.substring(0, 32);
|
|
68
|
-
|
|
69
|
-
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
|
70
|
-
let encrypted = cipher.update(JSON.stringify(user.data));
|
|
71
|
-
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
72
|
-
|
|
73
|
-
const externalId = `${BITY_CLIENT_ID}-${BITY_OAUTH_REDIRECT_URI}-${BITY_OAUTH_STATE}`;
|
|
74
|
-
const doc = {
|
|
75
|
-
externalId,
|
|
76
|
-
data: {
|
|
77
|
-
iv: iv.toString('hex'),
|
|
78
|
-
encryptedData: encrypted.toString('hex'),
|
|
79
|
-
},
|
|
80
|
-
expires: user.expires,
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const bityModule = (context.modules as any).bity as BityModule;
|
|
84
|
-
await bityModule.upsertCredentials(doc, context.userId);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const getTokenFromDb = async (bityAuth, context: Context) => {
|
|
88
|
-
const bityModule = (context.modules as any).bity as BityModule;
|
|
89
|
-
const credentials = await bityModule.findBityCredentials({
|
|
90
|
-
externalId: `${BITY_CLIENT_ID}-${BITY_OAUTH_REDIRECT_URI}-${BITY_OAUTH_STATE}`,
|
|
91
|
-
});
|
|
92
|
-
if (!credentials?.data) return null;
|
|
93
|
-
|
|
94
|
-
const iv = Buffer.from(credentials.data.iv, 'hex');
|
|
95
|
-
const encryptedText = Buffer.from(credentials.data.encryptedData, 'hex');
|
|
96
|
-
const key = crypto
|
|
97
|
-
.createHash('sha256')
|
|
98
|
-
.update(String(BITY_CLIENT_SECRET))
|
|
99
|
-
.digest('base64')
|
|
100
|
-
.substr(0, 32);
|
|
101
|
-
|
|
102
|
-
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
|
|
103
|
-
let decrypted = decipher.update(encryptedText);
|
|
104
|
-
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
105
|
-
const data = JSON.parse(decrypted.toString());
|
|
106
|
-
|
|
107
|
-
const token = bityAuth.createToken(data.access_token, data.refresh_token, data.token_type, { data });
|
|
108
|
-
return token;
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const refreshBityUser = async (context: Context) => {
|
|
112
|
-
if (currentToken) {
|
|
113
|
-
const newToken = await currentToken.refresh();
|
|
114
|
-
if (newToken) {
|
|
115
|
-
await upsertBityCredentials(newToken, context);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const signPayload = (...args) => {
|
|
121
|
-
const resultString = args.filter(Boolean).join('');
|
|
122
|
-
const signKeyInBytes = Buffer.from(BITY_CLIENT_ID, 'hex');
|
|
123
|
-
|
|
124
|
-
const signedString = crypto.createHmac('sha256', signKeyInBytes).update(resultString).digest('hex');
|
|
125
|
-
return signedString;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const bityExchangeFetch = async (params: { path: string; data?: any }, context: Context) => {
|
|
129
|
-
const body = params.data && JSON.stringify(params.data);
|
|
130
|
-
const doFetch = async () => {
|
|
131
|
-
const response = await fetch(`${BITY_API_ENDPOINT}${params.path}`, {
|
|
132
|
-
method: body ? 'POST' : 'GET',
|
|
133
|
-
body: body || undefined,
|
|
134
|
-
headers: {
|
|
135
|
-
Authorization: `Bearer ${currentToken.accessToken}`,
|
|
136
|
-
'Content-Type': 'application/json',
|
|
137
|
-
},
|
|
138
|
-
});
|
|
139
|
-
return response;
|
|
140
|
-
};
|
|
141
|
-
const response = await doFetch();
|
|
142
|
-
if (response.status === 401) {
|
|
143
|
-
await refreshBityUser(context);
|
|
144
|
-
return doFetch();
|
|
145
|
-
}
|
|
146
|
-
return response;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const createBityOrder = async (data: any, context: Context) => {
|
|
150
|
-
const response = await bityExchangeFetch(
|
|
151
|
-
{
|
|
152
|
-
path: '/v2/orders',
|
|
153
|
-
data,
|
|
154
|
-
},
|
|
155
|
-
context,
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
if (response?.status !== 201) {
|
|
159
|
-
logger.error('Bity Plugin: Response invalid', {
|
|
160
|
-
data,
|
|
161
|
-
route: '/orders',
|
|
162
|
-
response,
|
|
163
|
-
});
|
|
164
|
-
throw new Error('Could not create Bity Order');
|
|
165
|
-
}
|
|
166
|
-
return response.headers.get('Location');
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// eslint-disable-next-line
|
|
170
|
-
const estimateBityOrder = async (data: any, context: Context) => {
|
|
171
|
-
const response = await bityExchangeFetch(
|
|
172
|
-
{
|
|
173
|
-
path: '/v2/orders/estimate',
|
|
174
|
-
data,
|
|
175
|
-
},
|
|
176
|
-
context,
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
if (response?.status !== 200) {
|
|
180
|
-
logger.error('Bity Plugin: Response invalid', {
|
|
181
|
-
data,
|
|
182
|
-
route: '/orders/estimate',
|
|
183
|
-
response,
|
|
184
|
-
});
|
|
185
|
-
throw new Error('Could not estimate Bity Currency Conversion');
|
|
186
|
-
}
|
|
187
|
-
return response.json();
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
export default (app) => {
|
|
191
|
-
useMiddlewareWithCurrentContext(app, BITY_OAUTH_INIT_PATH, async (req, res) => {
|
|
192
|
-
if (req.method === 'GET') {
|
|
193
|
-
try {
|
|
194
|
-
const resolvedContext = req.unchainedContext;
|
|
195
|
-
await checkAction(resolvedContext, (actions as any).managePaymentProviders);
|
|
196
|
-
|
|
197
|
-
const bityAuthClient = createBityAuth();
|
|
198
|
-
const uri = bityAuthClient.code.getUri();
|
|
199
|
-
logger.info(`Bity Webhook: Login ${uri}`);
|
|
200
|
-
res.writeHead(302, {
|
|
201
|
-
Location: uri,
|
|
202
|
-
});
|
|
203
|
-
res.end();
|
|
204
|
-
return;
|
|
205
|
-
} catch (e) {
|
|
206
|
-
logger.warn(`Bity Webhook: Failed with ${e.message}`);
|
|
207
|
-
res.writeHead(503);
|
|
208
|
-
res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
res.writeHead(404);
|
|
213
|
-
res.end();
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
useMiddlewareWithCurrentContext(app, BITY_OAUTH_PATH, async (req, res, next) => {
|
|
217
|
-
bodyParser.urlencoded({ extended: false })(req, res, next);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
useMiddlewareWithCurrentContext(app, BITY_OAUTH_PATH, async (req, res) => {
|
|
221
|
-
if (req.method === 'GET') {
|
|
222
|
-
try {
|
|
223
|
-
const resolvedContext = req.unchainedContext as Context;
|
|
224
|
-
await checkAction(resolvedContext, (actions as any).managePaymentProviders);
|
|
225
|
-
const bityAuthClient = createBityAuth();
|
|
226
|
-
const user = await bityAuthClient.code.getToken(req.originalUrl);
|
|
227
|
-
await upsertBityCredentials(user, resolvedContext);
|
|
228
|
-
res.writeHead(200);
|
|
229
|
-
res.end('Bity Credentials Setup Complete');
|
|
230
|
-
return;
|
|
231
|
-
} catch (e) {
|
|
232
|
-
logger.warn(`Bity Webhook: Failed with ${e.message}`);
|
|
233
|
-
res.writeHead(503);
|
|
234
|
-
res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
res.writeHead(404);
|
|
239
|
-
res.end();
|
|
240
|
-
});
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
let bityAuthClient;
|
|
244
|
-
const loadToken = async (context: Context) => {
|
|
245
|
-
if (currentToken) return currentToken;
|
|
246
|
-
|
|
247
|
-
if (!bityAuthClient) {
|
|
248
|
-
bityAuthClient = createBityAuth();
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (bityAuthClient) {
|
|
252
|
-
currentToken = await getTokenFromDb(bityAuthClient, context);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return currentToken;
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
let token;
|
|
259
|
-
|
|
260
|
-
const Bity: IPaymentAdapter = {
|
|
261
|
-
...PaymentAdapter,
|
|
262
|
-
|
|
263
|
-
key: 'shop.unchained.payment.bity',
|
|
264
|
-
label: 'Bity',
|
|
265
|
-
version: '1.0.0',
|
|
266
|
-
|
|
267
|
-
initialConfiguration: [],
|
|
268
|
-
|
|
269
|
-
typeSupported: (type) => {
|
|
270
|
-
return type === 'GENERIC';
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
actions: (params) => {
|
|
274
|
-
loadToken(params.context).then((t) => {
|
|
275
|
-
token = t;
|
|
276
|
-
});
|
|
277
|
-
const adapter = {
|
|
278
|
-
...PaymentAdapter.actions(params),
|
|
279
|
-
|
|
280
|
-
configurationError: () => {
|
|
281
|
-
if (!token) {
|
|
282
|
-
return PaymentError.INCOMPLETE_CONFIGURATION;
|
|
283
|
-
}
|
|
284
|
-
return null;
|
|
285
|
-
},
|
|
286
|
-
|
|
287
|
-
isActive: () => {
|
|
288
|
-
if (adapter.configurationError() === null) return true;
|
|
289
|
-
return false;
|
|
290
|
-
},
|
|
291
|
-
|
|
292
|
-
isPayLaterAllowed() {
|
|
293
|
-
return false;
|
|
294
|
-
},
|
|
295
|
-
|
|
296
|
-
sign: async (transactionContext = {}) => {
|
|
297
|
-
// Signing the order will estimate a new order in bity and sign it with private data
|
|
298
|
-
logger.info(`Bity Plugin: Sign ${JSON.stringify(transactionContext)}`);
|
|
299
|
-
|
|
300
|
-
const { orderPayment } = params.paymentContext;
|
|
301
|
-
|
|
302
|
-
const order = await params.context.modules.orders.findOrder({
|
|
303
|
-
orderId: orderPayment.orderId,
|
|
304
|
-
});
|
|
305
|
-
const pricing = OrderPricingSheet({
|
|
306
|
-
calculation: order.calculation,
|
|
307
|
-
currency: order.currency,
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
if (!pricing) {
|
|
311
|
-
throw new Error('Price calculation of order invalid');
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
const totalAmount = Math.round(pricing.total({ useNetPrice: false }).amount / 10 || 0) * 10;
|
|
315
|
-
|
|
316
|
-
const payload = await estimateBityOrder(
|
|
317
|
-
{
|
|
318
|
-
output: {
|
|
319
|
-
currency: 'EUR',
|
|
320
|
-
amount: `${totalAmount / 100}`,
|
|
321
|
-
},
|
|
322
|
-
input: {
|
|
323
|
-
currency: 'BTC',
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
params.context,
|
|
327
|
-
);
|
|
328
|
-
|
|
329
|
-
const signature = signPayload(
|
|
330
|
-
JSON.stringify(payload),
|
|
331
|
-
order._id,
|
|
332
|
-
totalAmount,
|
|
333
|
-
BITY_CLIENT_SECRET,
|
|
334
|
-
);
|
|
335
|
-
|
|
336
|
-
return JSON.stringify({
|
|
337
|
-
payload,
|
|
338
|
-
signature,
|
|
339
|
-
});
|
|
340
|
-
},
|
|
341
|
-
|
|
342
|
-
charge: async (): Promise<false> => {
|
|
343
|
-
const { order } = params.paymentContext;
|
|
344
|
-
const { bityPayload, bitySignature } = order?.context || {};
|
|
345
|
-
|
|
346
|
-
const pricing = OrderPricingSheet({
|
|
347
|
-
calculation: order.calculation,
|
|
348
|
-
currency: order.currency,
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
if (!pricing) {
|
|
352
|
-
throw new Error('Price calculation of order invalid');
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const totalAmount =
|
|
356
|
-
Math.round(
|
|
357
|
-
pricing.total({
|
|
358
|
-
useNetPrice: false,
|
|
359
|
-
}).amount / 10 || 0,
|
|
360
|
-
) * 10;
|
|
361
|
-
|
|
362
|
-
const signature = signPayload(
|
|
363
|
-
JSON.stringify(bityPayload),
|
|
364
|
-
order._id,
|
|
365
|
-
totalAmount,
|
|
366
|
-
BITY_CLIENT_SECRET,
|
|
367
|
-
);
|
|
368
|
-
if (bitySignature !== signature) {
|
|
369
|
-
logger.warn(`Bity Plugin: Signature Mismatch ${JSON.stringify(bityPayload)} ${bitySignature}`);
|
|
370
|
-
throw new Error('Signature Mismatch');
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const path = await createBityOrder(
|
|
374
|
-
{
|
|
375
|
-
input: {
|
|
376
|
-
amount: bityPayload.input.amount,
|
|
377
|
-
currency: bityPayload.input.currency,
|
|
378
|
-
},
|
|
379
|
-
output: {
|
|
380
|
-
currency: bityPayload.output.currency,
|
|
381
|
-
type: 'bank_account',
|
|
382
|
-
iban: BITY_BANK_ACCOUNT_IBAN,
|
|
383
|
-
reference: order._id,
|
|
384
|
-
owner: {
|
|
385
|
-
address: BITY_BANK_ACCOUNT_ADDRESS,
|
|
386
|
-
city: BITY_BANK_ACCOUNT_CITY,
|
|
387
|
-
country: BITY_BANK_ACCOUNT_COUNTRY,
|
|
388
|
-
name: BITY_BANK_ACCOUNT_NAME,
|
|
389
|
-
zip: BITY_BANK_ACCOUNT_ZIP,
|
|
390
|
-
},
|
|
391
|
-
},
|
|
392
|
-
},
|
|
393
|
-
params.context,
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
logger.info(`Bity Plugin: Prepared Bity Order`, path);
|
|
397
|
-
const response = await bityExchangeFetch({ path }, params.context);
|
|
398
|
-
|
|
399
|
-
const bityOrder = await response?.json();
|
|
400
|
-
if (!bityOrder) {
|
|
401
|
-
logger.warn(`Bity Plugin: Bity Order not found ${JSON.stringify(path)} ${bitySignature}`);
|
|
402
|
-
throw new Error('Bity Order not Found');
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
await params.context.modules.orders.updateContext(
|
|
406
|
-
order._id,
|
|
407
|
-
{
|
|
408
|
-
bityOrder,
|
|
409
|
-
},
|
|
410
|
-
params.context,
|
|
411
|
-
);
|
|
412
|
-
|
|
413
|
-
return false;
|
|
414
|
-
},
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
return adapter;
|
|
418
|
-
},
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
PaymentDirector.registerAdapter(Bity);
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Db, TimestampFields, _ID } from '@unchainedshop/types/common';
|
|
2
|
-
|
|
3
|
-
export type BityCredentialsType = {
|
|
4
|
-
_id?: _ID;
|
|
5
|
-
externalId: string;
|
|
6
|
-
data: {
|
|
7
|
-
iv: string;
|
|
8
|
-
encryptedData: string;
|
|
9
|
-
};
|
|
10
|
-
expires: Date;
|
|
11
|
-
} & TimestampFields;
|
|
12
|
-
|
|
13
|
-
export const BityCredentialsCollection = (db: Db) => {
|
|
14
|
-
const BityCredentials = db.collection<BityCredentialsType>('bity_credentials');
|
|
15
|
-
|
|
16
|
-
return BityCredentials;
|
|
17
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Db } from '@unchainedshop/types/common';
|
|
2
|
-
import { generateDbObjectId } from '@unchainedshop/utils';
|
|
3
|
-
import { BityCredentialsCollection, BityCredentialsType } from '../db/BityCredentialsCollection';
|
|
4
|
-
|
|
5
|
-
export interface BityModule {
|
|
6
|
-
findBityCredentials: (query: { externalId: string }) => Promise<BityCredentialsType>;
|
|
7
|
-
|
|
8
|
-
upsertCredentials: (doc: BityCredentialsType, userId: string) => Promise<string | null>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const configureBityModule = ({ db }: { db: Db }): BityModule => {
|
|
12
|
-
const BityCredentials = BityCredentialsCollection(db);
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
findBityCredentials: async ({ externalId }) => {
|
|
16
|
-
return BityCredentials.findOne({ externalId });
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
upsertCredentials: async (doc, userId) => {
|
|
20
|
-
await BityCredentials.updateOne(
|
|
21
|
-
{
|
|
22
|
-
externalId: doc.externalId,
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
$set: {
|
|
26
|
-
data: {
|
|
27
|
-
iv: doc.data.iv,
|
|
28
|
-
encryptedData: doc.data.encryptedData,
|
|
29
|
-
},
|
|
30
|
-
expires: doc.expires,
|
|
31
|
-
updated: new Date(),
|
|
32
|
-
updatedBy: userId,
|
|
33
|
-
},
|
|
34
|
-
$setOnInsert: {
|
|
35
|
-
_id: generateDbObjectId(),
|
|
36
|
-
externalId: doc.externalId,
|
|
37
|
-
created: new Date(),
|
|
38
|
-
createdBy: userId,
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
return doc.externalId;
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
};
|