@opengis/pay 1.2.0 → 1.2.2
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/package.json +1 -1
- package/server/routes/liqpay/controllers/liqpay.redirect.js +19 -20
- package/server/routes/liqpay/controllers/liqpay.status.js +38 -21
- package/server/routes/liqpay/index.mjs +8 -0
- package/server/routes/liqpay/utils/check.status.js +34 -0
- package/server/routes/portmone/controllers/payment.info.js +46 -1
package/package.json
CHANGED
|
@@ -23,27 +23,27 @@ export default async function liqpayRedirect(req, reply) {
|
|
|
23
23
|
|
|
24
24
|
const domain = req.hostname.split(':').shift();
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const paymentData = query.id ? await pg.query('select payment_id, account_id, payment_amount, payment_status from billing.payments where payment_id=$1', [query.id])
|
|
27
27
|
.then(el => el.rows?.[0] || {}) : {};
|
|
28
28
|
|
|
29
|
-
if (
|
|
29
|
+
if (paymentData.payment_status && paymentData.payment_status === 'success') {
|
|
30
30
|
return { message: 'already processed', status: 400 };
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const paymentAmount =
|
|
33
|
+
const paymentAmount = paymentData.payment_amount || query.price;
|
|
34
34
|
|
|
35
35
|
if (!paymentAmount) {
|
|
36
36
|
return { message: 'price is required', status: 400 };
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const accountId =
|
|
39
|
+
const accountId = paymentData.account_id
|
|
40
40
|
|| (user?.uid ? await pg.query('select account_id from billing.account_user where user_id=$1 limit 1', [user?.uid]).then(el => el.rows?.[0]?.account_id) : null);
|
|
41
41
|
|
|
42
42
|
if (!accountId) {
|
|
43
43
|
return { message: 'account_id is required', status: 400 };
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const { payment_id: paymentId } = !
|
|
46
|
+
const { payment_id: paymentId } = !paymentData.payment_id
|
|
47
47
|
? await dataInsert({
|
|
48
48
|
table: 'billing.payments',
|
|
49
49
|
data: {
|
|
@@ -54,7 +54,7 @@ export default async function liqpayRedirect(req, reply) {
|
|
|
54
54
|
},
|
|
55
55
|
uid: user?.uid || '0',
|
|
56
56
|
}).then(el => el.rows?.[0] || {})
|
|
57
|
-
: { payment_id:
|
|
57
|
+
: { payment_id: paymentData.payment_id };
|
|
58
58
|
|
|
59
59
|
if (!paymentId) {
|
|
60
60
|
return { message: 'payment not found', status: 404 };
|
|
@@ -71,23 +71,26 @@ export default async function liqpayRedirect(req, reply) {
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
const protocol = headers?.referer?.split?.('://')?.shift?.() || req.protocol || 'https';
|
|
74
|
-
const rootPageUrl = `${protocol || 'https'}://${domain}
|
|
74
|
+
const rootPageUrl = `${protocol || 'https'}://${domain}`;
|
|
75
75
|
|
|
76
|
-
const resultUrl = paymentRedirect
|
|
76
|
+
/* const resultUrl = paymentRedirect
|
|
77
77
|
? `${rootPageUrl}${handlebarsSync.compile(paymentRedirect)({ id: paymentId })}`
|
|
78
|
-
: headers?.referer || `${rootPageUrl}`;
|
|
78
|
+
: headers?.referer || `${rootPageUrl}`; */
|
|
79
|
+
|
|
80
|
+
// redirect to api to check payment status and redirect user to page afterwards
|
|
79
81
|
const serverUrl = `${rootPageUrl}${prefix}/liqpay/${paymentId}/success`;
|
|
80
82
|
|
|
81
|
-
const
|
|
83
|
+
const paymentOptions = {
|
|
82
84
|
action: 'pay',
|
|
83
85
|
amount: paymentAmount,
|
|
84
86
|
currency: 'UAH',
|
|
85
87
|
description: 'regular payment',
|
|
86
88
|
order_id: paymentId,
|
|
87
89
|
version: '3',
|
|
88
|
-
server_url: serverUrl, // update payment info - api url
|
|
89
|
-
result_url:
|
|
90
|
-
}
|
|
90
|
+
// server_url: serverUrl, // update payment info - api url, does not work on sdk package out of the box
|
|
91
|
+
result_url: serverUrl, // redirect user after payment - page url
|
|
92
|
+
};
|
|
93
|
+
const { data, signature } = liqpay.cnb_object(paymentOptions) || {};
|
|
91
94
|
|
|
92
95
|
const logObj = {
|
|
93
96
|
type: 'redirect',
|
|
@@ -96,25 +99,21 @@ export default async function liqpayRedirect(req, reply) {
|
|
|
96
99
|
price: paymentAmount,
|
|
97
100
|
service: 'liqpay',
|
|
98
101
|
domain,
|
|
99
|
-
paymentRedirectUrl:
|
|
102
|
+
paymentRedirectUrl: serverUrl,
|
|
100
103
|
serverUrl,
|
|
101
104
|
uid: user?.uid || '0',
|
|
102
105
|
};
|
|
103
106
|
|
|
104
107
|
if (config.debug && query?.debug) {
|
|
108
|
+
const html = liqpay.cnb_form(paymentOptions);
|
|
105
109
|
return reply.status(302).headers({ 'Content-Type': 'text/html' }).send(html);
|
|
106
110
|
}
|
|
107
111
|
|
|
108
|
-
const body = {
|
|
109
|
-
data: html.match(/<input type="hidden" name="data" value="([^"]+)"/)?.[1],
|
|
110
|
-
signature: html.match(/<input type="hidden" name="signature" value="([^"]+)"/)?.[1],
|
|
111
|
-
};
|
|
112
|
-
|
|
113
112
|
try {
|
|
114
113
|
const response = await request({
|
|
115
114
|
url: `${host}/api/3/checkout`,
|
|
116
115
|
method: 'POST',
|
|
117
|
-
form:
|
|
116
|
+
form: { data, signature },
|
|
118
117
|
followAllRedirects: false,
|
|
119
118
|
jar: true,
|
|
120
119
|
timeout: 6000,
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
|
|
7
7
|
import { sendNotification } from '@opengis/admin/utils.js';
|
|
8
8
|
|
|
9
|
+
import checkStatus from '../utils/check.status.js';
|
|
10
|
+
|
|
9
11
|
const newDate = () => {
|
|
10
12
|
const date = new Date();
|
|
11
13
|
const tzOffset = date.getTimezoneOffset();
|
|
@@ -42,29 +44,44 @@ export default async function liqpayStatus(req, reply) {
|
|
|
42
44
|
return reply.status(400).send('invalid liqpay integration settings');
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
if (!body?.data || !body?.signature) {
|
|
46
|
-
return reply.status(400).send('not enough body params: data, signature');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const sign = liqpay.str_to_sign(
|
|
50
|
-
privateKey
|
|
51
|
-
+ body.data
|
|
52
|
-
+ privateKey,
|
|
53
|
-
);
|
|
54
|
-
|
|
55
47
|
const origin = headers?.origin || headers?.referer;
|
|
56
48
|
const { status: responseStatus, id: paymentId } = params;
|
|
57
49
|
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
if (!paymentId) {
|
|
51
|
+
return reply.status(400).send('not enough params: id');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (req.method === 'GET') {
|
|
55
|
+
const result = await checkStatus(params.id) || {};
|
|
56
|
+
const { status, err_description: err } = result;
|
|
57
|
+
if (status !== 'success' && !unittest) {
|
|
58
|
+
return reply.status(400).send(err || 'Помилка перевірки статусу платежу');
|
|
59
|
+
}
|
|
60
|
+
Object.assign(body, result);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (req.method === 'POST') {
|
|
64
|
+
if (!body?.data || !body?.signature) {
|
|
65
|
+
return reply.status(400).send('not enough body params: data, signature');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const sign = liqpay.str_to_sign(
|
|
69
|
+
privateKey
|
|
70
|
+
+ body.data
|
|
71
|
+
+ privateKey,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (body.signature !== sign) {
|
|
75
|
+
logger.file('payments/warn', {
|
|
76
|
+
type: 'status',
|
|
77
|
+
service: 'liqpay',
|
|
78
|
+
paymentId,
|
|
79
|
+
origin,
|
|
80
|
+
uid: user?.uid || '0',
|
|
81
|
+
message: 'Transaction signature does not match',
|
|
82
|
+
});
|
|
83
|
+
return reply.status(403).send('access restricted: signature mismatch');
|
|
84
|
+
}
|
|
68
85
|
}
|
|
69
86
|
|
|
70
87
|
const data = await pg.query('select * from billing.payments where payment_id=$1', [paymentId])
|
|
@@ -121,7 +138,7 @@ export default async function liqpayStatus(req, reply) {
|
|
|
121
138
|
table: 'billing.payments',
|
|
122
139
|
data: {
|
|
123
140
|
payment_data: body,
|
|
124
|
-
payment_status: responseStatus,
|
|
141
|
+
payment_status: body.status || responseStatus,
|
|
125
142
|
total_balance: +refillSum + +totalBalance,
|
|
126
143
|
success_date: newDate(),
|
|
127
144
|
},
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import LiqPay from 'liqpayjs-sdk';
|
|
2
|
+
import request from 'request-promise';
|
|
3
|
+
|
|
4
|
+
import { config } from '@opengis/fastify-table/utils.js';
|
|
5
|
+
|
|
6
|
+
const { publicKey, privateKey } = config.integrations?.liqpay || {};
|
|
7
|
+
|
|
8
|
+
const liqpay = new LiqPay(publicKey, privateKey);
|
|
9
|
+
const host = 'https://www.liqpay.ua';
|
|
10
|
+
|
|
11
|
+
export default async function liqpayCheckStatus(id) {
|
|
12
|
+
if (!publicKey || !privateKey) return {};
|
|
13
|
+
|
|
14
|
+
const options = {
|
|
15
|
+
public_key: publicKey, // in case of liqpay.api is auto-assigned
|
|
16
|
+
action: 'status',
|
|
17
|
+
version: '3',
|
|
18
|
+
order_id: id,
|
|
19
|
+
};
|
|
20
|
+
/* const result = liqpay.api('request', options); */
|
|
21
|
+
|
|
22
|
+
const data = Buffer.from(JSON.stringify(options)).toString('base64');
|
|
23
|
+
const signature = liqpay.str_to_sign(privateKey + data + privateKey);
|
|
24
|
+
|
|
25
|
+
const response = await request(`${host}/api/request`, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
form: { data, signature },
|
|
28
|
+
headers: {
|
|
29
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const result = response?.startsWith?.('{') ? JSON.parse(response) : response;
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import { metaFormat, pgClients } from '@opengis/fastify-table/utils.js';
|
|
1
|
+
import { dataUpdate, metaFormat, pgClients } from '@opengis/fastify-table/utils.js';
|
|
2
|
+
|
|
3
|
+
import liqpayCheckStatus from '../../liqpay/utils/check.status.js';
|
|
4
|
+
|
|
5
|
+
const newDate = (dateNum) => {
|
|
6
|
+
const date = dateNum ? new Date(dateNum) : new Date();
|
|
7
|
+
const tzOffset = date.getTimezoneOffset();
|
|
8
|
+
const currentTimeWithTimezome = date - tzOffset * 60 * 1000;
|
|
9
|
+
return new Date(currentTimeWithTimezome).toISOString();
|
|
10
|
+
};
|
|
2
11
|
|
|
3
12
|
/**
|
|
4
13
|
* Апі для отримання інформації за ID
|
|
@@ -30,6 +39,8 @@ export default async function paymentInfo({
|
|
|
30
39
|
payment_status,
|
|
31
40
|
total_balance,
|
|
32
41
|
payment_num,
|
|
42
|
+
payment_service,
|
|
43
|
+
payment_data,
|
|
33
44
|
subscription_id
|
|
34
45
|
from billing.payments
|
|
35
46
|
where payment_id = $1
|
|
@@ -39,6 +50,40 @@ export default async function paymentInfo({
|
|
|
39
50
|
return { message: 'payment not found', status: 404 };
|
|
40
51
|
}
|
|
41
52
|
|
|
53
|
+
const {
|
|
54
|
+
account_id: accountId,
|
|
55
|
+
payment_service: service,
|
|
56
|
+
payment_status: status,
|
|
57
|
+
|
|
58
|
+
} = rows[0];
|
|
59
|
+
|
|
60
|
+
if (status !== 'success' && service === 'liqpay') {
|
|
61
|
+
const result = await liqpayCheckStatus(params.id);
|
|
62
|
+
const { amount = 0 } = result;
|
|
63
|
+
|
|
64
|
+
const { total_balance: totalBalance = 0 } = await pg.query(`select total_balance from billing.payments
|
|
65
|
+
where account_id=$1
|
|
66
|
+
and payment_status in ('success', 'error')
|
|
67
|
+
and total_balance is not null
|
|
68
|
+
order by cdate desc limit 1`, [accountId]).then(el => el.rows?.[0] || {});
|
|
69
|
+
|
|
70
|
+
const res = await dataUpdate({
|
|
71
|
+
pg,
|
|
72
|
+
table: 'billing.payments',
|
|
73
|
+
id: params.id,
|
|
74
|
+
data: {
|
|
75
|
+
payment_data: result,
|
|
76
|
+
payment_status: 'success',
|
|
77
|
+
total_balance: +amount + +totalBalance,
|
|
78
|
+
success_date: newDate(result.end_date),
|
|
79
|
+
},
|
|
80
|
+
uid: user?.uid,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const res1 = await metaFormat({ rows: [res].filter(el => el), cls: { account_id: 'billing.account_id', payment_status: 'billing.payment_status', subscription_id: 'billing.subscription_id' } });
|
|
84
|
+
return res1;
|
|
85
|
+
}
|
|
86
|
+
|
|
42
87
|
await metaFormat({ rows, cls: { account_id: 'billing.account_id', payment_status: 'billing.payment_status', subscription_id: 'billing.subscription_id' } });
|
|
43
88
|
|
|
44
89
|
return rows[0];
|