gamemoney 5.0.0 → 7.0.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.
- package/LICENSE +21 -0
- package/README.md +66 -6
- package/dist/certificate.d.ts +1 -0
- package/{certs/gm.crt → dist/certificate.js} +2 -1
- package/{index.d.ts → dist/index.d.ts} +109 -40
- package/{index.js → dist/index.js} +52 -23
- package/{utils.d.ts → dist/utils.d.ts} +6 -5
- package/dist/utils.js +77 -0
- package/package.json +75 -84
- package/utils.js +0 -51
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Maxim Makarov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
[GameMoney](https://gmpays.com/) API wrapper for Node.js
|
|
4
4
|
|
|
5
5
|
Full API documentation [here](https://cp.gmpays.com/apidoc)
|
|
6
6
|
|
|
7
|
-
## Installation
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
8
9
|
```sh
|
|
9
10
|
$ npm install gamemoney
|
|
10
11
|
```
|
|
11
12
|
|
|
13
|
+
The package is ESM-only (there is no CommonJS build) and has no runtime dependencies. It requires Node.js `>=22.12.0`, where ES modules can also be loaded with `require()`.
|
|
14
|
+
|
|
12
15
|
## Usage
|
|
13
16
|
|
|
14
17
|
### Initialization
|
|
18
|
+
|
|
15
19
|
```typescript
|
|
16
|
-
import fs from 'fs'
|
|
17
|
-
import GameMoney from 'gamemoney'
|
|
20
|
+
import fs from 'node:fs'
|
|
21
|
+
import { GameMoney } from 'gamemoney'
|
|
18
22
|
|
|
19
23
|
const gm = new GameMoney({
|
|
20
24
|
project: 42,
|
|
@@ -23,7 +27,7 @@ const gm = new GameMoney({
|
|
|
23
27
|
// Optional. But to make checkouts must be specified
|
|
24
28
|
rsaPrivateKey: {
|
|
25
29
|
key: fs.readFileSync('./private.pem').toString(),
|
|
26
|
-
passphrase: '123' // Optional
|
|
30
|
+
passphrase: '123', // Optional
|
|
27
31
|
},
|
|
28
32
|
|
|
29
33
|
// OR:
|
|
@@ -31,8 +35,64 @@ const gm = new GameMoney({
|
|
|
31
35
|
// process.env.GM_RSA_PRIVATE_KEY ?? '',
|
|
32
36
|
// 'base64',
|
|
33
37
|
// )
|
|
38
|
+
|
|
39
|
+
// Optional. API host from the project settings. Default: https://paygate.gamemoney.com
|
|
40
|
+
apiUrl: 'https://paygate.gamemoney.com',
|
|
41
|
+
|
|
42
|
+
// Optional. GameMoney certificate or public key from the project settings,
|
|
43
|
+
// used to verify signatures of responses and notifications.
|
|
44
|
+
// Default: the certificate bundled with the package
|
|
45
|
+
gameMoneyPublicKey: fs.readFileSync('./gm.crt'),
|
|
46
|
+
|
|
47
|
+
// Optional. Request timeout in milliseconds. Default: no timeout
|
|
48
|
+
timeout: 30_000,
|
|
34
49
|
})
|
|
35
50
|
```
|
|
36
51
|
|
|
52
|
+
From CommonJS code, via Node's built-in [`require(esm)`](https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require):
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
const { GameMoney, verifyRsaSignature } = require('gamemoney')
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Errors
|
|
59
|
+
|
|
60
|
+
- `GameMoneyError`: GameMoney responded with `"state": "error"`, the error text is in `message`.
|
|
61
|
+
- `GameMoneyHttpError`: GameMoney responded with a non-2xx HTTP status, available in `status`.
|
|
62
|
+
- `TimeoutError`: the request did not complete within `timeout`. GameMoney may still process it, so check the operation status (for example, with `getCheckoutStatus`) before retrying.
|
|
63
|
+
- `Error` with `Response signature mismatch` or `Wrong rand parameter`: the response failed verification and must not be trusted.
|
|
64
|
+
|
|
65
|
+
### Notifications
|
|
66
|
+
|
|
67
|
+
GameMoney resends payment and payout notifications for 24 hours until the project responds with `{"success": "true"}`:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
if (!gm.verifyRsaSignature(notification)) {
|
|
71
|
+
response.send({ success: 'error', error: 'signature mismatch' })
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
response.send({ success: 'true' })
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Transfer notifications are answered with the created invoice signed with HMAC, see [the example](https://github.com/gamemoney-ps/gamemoney-node-sdk/tree/master/src/examples/transfer/callback.ts).
|
|
79
|
+
|
|
80
|
+
### Signatures
|
|
81
|
+
|
|
82
|
+
`parametersToString`, `generateHmacSignature`, `generateRsaSignature` and `verifyRsaSignature` implement the [GameMoney signature algorithm](https://cp.gmpays.com/apidoc#sign_general) and are exported for custom integrations and tests, for example to sign responses of a GameMoney mock.
|
|
83
|
+
|
|
84
|
+
### Other API methods
|
|
85
|
+
|
|
86
|
+
Any API method can be called with a signed request:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const response = await gm.request('exchange/rate', { from: 'USD', to: 'RUB' })
|
|
90
|
+
```
|
|
91
|
+
|
|
37
92
|
### Examples
|
|
38
|
-
|
|
93
|
+
|
|
94
|
+
See examples in [src/examples](https://github.com/gamemoney-ps/gamemoney-node-sdk/tree/master/src/examples) directory. They read the credentials from `GAMEMONEY_PROJECT_ID`, `GAMEMONEY_HMAC_PRIVATE_KEY` and `GAMEMONEY_RSA_PRIVATE_KEY` (base64) and can be run directly:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
$ node --env-file=.env src/examples/statistics/balance.ts
|
|
98
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const gameMoneyCertificate = "-----BEGIN CERTIFICATE-----\nMIID3TCCAsWgAwIBAgIJANtAJ3UMiGLZMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYD\nVQQGEwJDUjERMA8GA1UECAwIU2FuIEpvc2UxEjAQBgNVBAcMCVNhbnRhIEFuYTET\nMBEGA1UECgwKSUJTIFMuUi5MLjEeMBwGA1UEAwwVY2hlY2tpbi5nYW1lbW9uZXku\nY29tMRkwFwYJKoZIhvcNAQkBFgpjZW9AaWJzLmNyMB4XDTE2MDkwNDA3MjY0OVoX\nDTI2MDkwNjA3MjY0OVowgYQxCzAJBgNVBAYTAkNSMREwDwYDVQQIDAhTYW4gSm9z\nZTESMBAGA1UEBwwJU2FudGEgQW5hMRMwEQYDVQQKDApJQlMgUy5SLkwuMR4wHAYD\nVQQDDBVjaGVja2luLmdhbWVtb25leS5jb20xGTAXBgkqhkiG9w0BCQEWCmNlb0Bp\nYnMuY3IwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPK9ODW+BcqZ5P\nYlQWziyLzKImuE8EDn7XuE9ZDmpKiJxwDUKZHSQYH4QtHyx0qYAbIqIGrKemfTu1\nnvW9+O8yKLFLLcaXVaSLU7mpp8uSWasGbkLqE7xVLqxQZq1zrBSEPnKR1/dNxD83\n5pNzMLx7ki02t1J01MAj0FvQ3GemIAQU15m+w+9YKX8cUYEBm+h2KuY6uziLhJTM\nBAQRIXO3z4fkZhUi/0wpiy5Zxi2jbh07gab7me5dpxxwOs/Dt10S6J8qu+AAH0DE\n3diqQS4OcaCYJuIo/kJVxrn8TO2WKzSf2CBMWMzKtA2lOIMokC79gsrTFAasRM8j\nBQkvD5/TAgMBAAGjUDBOMB0GA1UdDgQWBBTqyL+faltohjM5faVuKxRUBCG25DAf\nBgNVHSMEGDAWgBTqyL+faltohjM5faVuKxRUBCG25DAMBgNVHRMEBTADAQH/MA0G\nCSqGSIb3DQEBCwUAA4IBAQBpnItyLrXE1RWdGE+xoJ2YEbjNtgEfzaypFPpVuMO0\nhvCV1rJJDS3zs/P1uSF0akqN4weSGOeFuFyGf3v2j40M1T1XdllOA8ucBv7Rfy2W\nl1rR2aU+Hd6rl0E/7lhtx3VUobgPVKZn8k7NMKkSMtF/f2cS9jI4i6gsJfFImMr9\ngWjEZAlmwQcnilZ6ZUhhn+0yHFbCoX8fETH/sZlofZOnN8EkETyqyfThIpTX41XH\ngeivrSfScNQH1mWJuE0DXMobNrhyJpxHRJwXXQyck6TiDM8OETki4PBzjKk/Gsyc\n61gqP9VPE2AVVwKypWOJidMxMZ03n4+MlyTbz3mnBXL9\n-----END CERTIFICATE-----\n";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export const gameMoneyCertificate = `-----BEGIN CERTIFICATE-----
|
|
2
2
|
MIID3TCCAsWgAwIBAgIJANtAJ3UMiGLZMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYD
|
|
3
3
|
VQQGEwJDUjERMA8GA1UECAwIU2FuIEpvc2UxEjAQBgNVBAcMCVNhbnRhIEFuYTET
|
|
4
4
|
MBEGA1UECgwKSUJTIFMuUi5MLjEeMBwGA1UEAwwVY2hlY2tpbi5nYW1lbW9uZXku
|
|
@@ -21,3 +21,4 @@ gWjEZAlmwQcnilZ6ZUhhn+0yHFbCoX8fETH/sZlofZOnN8EkETyqyfThIpTX41XH
|
|
|
21
21
|
geivrSfScNQH1mWJuE0DXMobNrhyJpxHRJwXXQyck6TiDM8OETki4PBzjKk/Gsyc
|
|
22
22
|
61gqP9VPE2AVVwKypWOJidMxMZ03n4+MlyTbz3mnBXL9
|
|
23
23
|
-----END CERTIFICATE-----
|
|
24
|
+
`;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { type RsaKey, type HmacKey } from './utils.
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
'
|
|
5
|
-
|
|
1
|
+
import { type RsaKey, type RsaPublicKey, type HmacKey } from './utils.ts';
|
|
2
|
+
export { generateHmacSignature, generateRsaSignature, parametersToString, verifyRsaSignature, } from './utils.ts';
|
|
3
|
+
export declare const SignType: {
|
|
4
|
+
readonly HMAC: 'HMAC';
|
|
5
|
+
readonly RSA: 'RSA';
|
|
6
|
+
};
|
|
7
|
+
export type SignType = (typeof SignType)[keyof typeof SignType];
|
|
6
8
|
export type GenericRequest = {
|
|
7
9
|
[key: string]: any;
|
|
8
10
|
rand?: string;
|
|
@@ -21,9 +23,12 @@ export type Config = {
|
|
|
21
23
|
rsaPrivateKey?: RsaKey;
|
|
22
24
|
hmacPrivateKey: HmacKey;
|
|
23
25
|
project: number;
|
|
26
|
+
apiUrl?: string;
|
|
27
|
+
gameMoneyPublicKey?: RsaPublicKey;
|
|
28
|
+
timeout?: number;
|
|
24
29
|
};
|
|
25
30
|
export type CreateInvoiceRequest = {
|
|
26
|
-
[key: string]:
|
|
31
|
+
[key: string]: unknown;
|
|
27
32
|
type: string;
|
|
28
33
|
user: string;
|
|
29
34
|
ip: string;
|
|
@@ -40,6 +45,8 @@ export type CreateInvoiceRequest = {
|
|
|
40
45
|
return_mode?: 'skip';
|
|
41
46
|
recurring?: 'yes';
|
|
42
47
|
recurrent_token?: string;
|
|
48
|
+
payment_token?: string;
|
|
49
|
+
theme?: 'dark' | 'light';
|
|
43
50
|
};
|
|
44
51
|
export type CreateInvoiceResponse = {
|
|
45
52
|
invoice: number;
|
|
@@ -47,11 +54,11 @@ export type CreateInvoiceResponse = {
|
|
|
47
54
|
data: string;
|
|
48
55
|
};
|
|
49
56
|
export type GetInvoiceStatusRequestWithProjectInvoiceId = {
|
|
50
|
-
[key: string]:
|
|
57
|
+
[key: string]: unknown;
|
|
51
58
|
invoice: number;
|
|
52
59
|
};
|
|
53
60
|
export type GetInvoiceStatusRequestWithGamemoneyInvoiceId = {
|
|
54
|
-
[key: string]:
|
|
61
|
+
[key: string]: unknown;
|
|
55
62
|
project_invoice: string;
|
|
56
63
|
};
|
|
57
64
|
export type GetInvoiceStatusRequest = GetInvoiceStatusRequestWithProjectInvoiceId | GetInvoiceStatusRequestWithGamemoneyInvoiceId;
|
|
@@ -77,7 +84,7 @@ export type GetInvoiceStatusResponse = {
|
|
|
77
84
|
txid?: string;
|
|
78
85
|
};
|
|
79
86
|
export type GetInvoiceListRequest = {
|
|
80
|
-
[key: string]:
|
|
87
|
+
[key: string]: unknown;
|
|
81
88
|
start: string;
|
|
82
89
|
finish: string;
|
|
83
90
|
status?: InvoiceStatus;
|
|
@@ -86,12 +93,34 @@ export type GetInvoiceListResponse = {
|
|
|
86
93
|
list: GetInvoiceStatusResponse[];
|
|
87
94
|
is_limit_exceeded: 'yes' | 'no';
|
|
88
95
|
};
|
|
96
|
+
export type AddTokenInvoiceRequest = {
|
|
97
|
+
[key: string]: unknown;
|
|
98
|
+
user: string;
|
|
99
|
+
};
|
|
100
|
+
export type AddTokenInvoiceResponse = {
|
|
101
|
+
token: string;
|
|
102
|
+
};
|
|
103
|
+
export type GetCardSessionStatusRequest = Record<string, unknown> & ({
|
|
104
|
+
invoice: string;
|
|
105
|
+
} | {
|
|
106
|
+
project_invoice: string;
|
|
107
|
+
});
|
|
108
|
+
export type WaitOrDeclineCardSessionStatusResponse = {
|
|
109
|
+
status: 'wait' | 'decline';
|
|
110
|
+
data: string;
|
|
111
|
+
};
|
|
112
|
+
export type FinishCardSessionStatusResponse = {
|
|
113
|
+
status: 'finish';
|
|
114
|
+
type: 'redirect';
|
|
115
|
+
data: string;
|
|
116
|
+
};
|
|
117
|
+
export type GetCardSessionStatusResponse = WaitOrDeclineCardSessionStatusResponse | FinishCardSessionStatusResponse;
|
|
89
118
|
export type CancelCheckoutRequest = {
|
|
90
|
-
[key: string]:
|
|
119
|
+
[key: string]: unknown;
|
|
91
120
|
projectId: string;
|
|
92
121
|
};
|
|
93
122
|
export type GetCheckoutStatusRequest = {
|
|
94
|
-
[key: string]:
|
|
123
|
+
[key: string]: unknown;
|
|
95
124
|
projectId: string;
|
|
96
125
|
};
|
|
97
126
|
export type Refund = {
|
|
@@ -121,7 +150,7 @@ export type GetCheckoutStatusResponse = {
|
|
|
121
150
|
txid?: string;
|
|
122
151
|
};
|
|
123
152
|
export type GetCheckoutListRequest = {
|
|
124
|
-
[key: string]:
|
|
153
|
+
[key: string]: unknown;
|
|
125
154
|
start: string;
|
|
126
155
|
finish: string;
|
|
127
156
|
};
|
|
@@ -130,7 +159,7 @@ export type GetCheckoutListResponse = {
|
|
|
130
159
|
is_limit_exceeded: 'yes' | 'no';
|
|
131
160
|
};
|
|
132
161
|
export type CreateCheckoutRequest = {
|
|
133
|
-
[key: string]:
|
|
162
|
+
[key: string]: unknown;
|
|
134
163
|
projectId: string;
|
|
135
164
|
user: string;
|
|
136
165
|
ip: string;
|
|
@@ -142,30 +171,52 @@ export type CreateCheckoutRequest = {
|
|
|
142
171
|
userCurrency?: string;
|
|
143
172
|
prepareToken?: string;
|
|
144
173
|
};
|
|
174
|
+
export type PrepareCheckoutRequest = Record<string, unknown> & {
|
|
175
|
+
type: string;
|
|
176
|
+
wallet?: string;
|
|
177
|
+
currency?: string;
|
|
178
|
+
userCurrency?: string;
|
|
179
|
+
} & ({
|
|
180
|
+
amount: number;
|
|
181
|
+
} | {
|
|
182
|
+
paid_amount: number;
|
|
183
|
+
});
|
|
184
|
+
export type PrepareCheckoutResponse = {
|
|
185
|
+
amount: number;
|
|
186
|
+
net_amount: number;
|
|
187
|
+
paid_amount: number;
|
|
188
|
+
currency_project: string;
|
|
189
|
+
currency_user: string;
|
|
190
|
+
token?: string;
|
|
191
|
+
rate?: number;
|
|
192
|
+
expire?: number;
|
|
193
|
+
};
|
|
145
194
|
export type AddCardRequest = {
|
|
146
|
-
[key: string]:
|
|
195
|
+
[key: string]: unknown;
|
|
147
196
|
user: string;
|
|
148
197
|
redirect: string;
|
|
198
|
+
language?: string;
|
|
199
|
+
theme?: 'dark' | 'light';
|
|
149
200
|
};
|
|
150
201
|
export type AddCardResponse = {
|
|
151
202
|
url: string;
|
|
152
203
|
};
|
|
153
204
|
export type AddTokenCardRequest = {
|
|
154
|
-
[key: string]:
|
|
205
|
+
[key: string]: unknown;
|
|
155
206
|
user: string;
|
|
156
207
|
};
|
|
157
208
|
export type AddTokenCardResponse = {
|
|
158
209
|
token: string;
|
|
159
210
|
};
|
|
160
211
|
export type GetCardListRequest = {
|
|
161
|
-
[key: string]:
|
|
212
|
+
[key: string]: unknown;
|
|
162
213
|
user: string;
|
|
163
214
|
};
|
|
164
215
|
export type GetCardListResponse = {
|
|
165
216
|
pans: string[];
|
|
166
217
|
};
|
|
167
218
|
export type GetCardFullListRequest = {
|
|
168
|
-
[key: string]:
|
|
219
|
+
[key: string]: unknown;
|
|
169
220
|
user: string;
|
|
170
221
|
};
|
|
171
222
|
export type GetCardFullListResponse = {
|
|
@@ -174,16 +225,17 @@ export type GetCardFullListResponse = {
|
|
|
174
225
|
expire_month: string;
|
|
175
226
|
expire_year: string;
|
|
176
227
|
cardholder: string;
|
|
228
|
+
country?: string;
|
|
177
229
|
}>;
|
|
178
230
|
};
|
|
179
231
|
export type DeleteCardRequest = {
|
|
180
|
-
[key: string]:
|
|
232
|
+
[key: string]: unknown;
|
|
181
233
|
user: string;
|
|
182
234
|
pan: string;
|
|
183
235
|
};
|
|
184
236
|
export type PrepareExchangeRequest = {
|
|
185
|
-
[key: string]:
|
|
186
|
-
externalId
|
|
237
|
+
[key: string]: unknown;
|
|
238
|
+
externalId?: string;
|
|
187
239
|
minAmount: number;
|
|
188
240
|
maxAmount: number;
|
|
189
241
|
from: string;
|
|
@@ -197,12 +249,12 @@ export type PrepareExchangeResponse = {
|
|
|
197
249
|
exchanged_amount_to: number;
|
|
198
250
|
};
|
|
199
251
|
export type ConvertExchangeRequest = {
|
|
200
|
-
[key: string]:
|
|
252
|
+
[key: string]: unknown;
|
|
201
253
|
id: number;
|
|
202
254
|
amount: number;
|
|
203
255
|
};
|
|
204
256
|
export type FastConvertExchangeRequest = {
|
|
205
|
-
[key: string]:
|
|
257
|
+
[key: string]: unknown;
|
|
206
258
|
amount: number;
|
|
207
259
|
from: string;
|
|
208
260
|
to: string;
|
|
@@ -212,7 +264,7 @@ export type FastConvertExchangeResponse = {
|
|
|
212
264
|
rate: number;
|
|
213
265
|
};
|
|
214
266
|
export type GetExchangeRateRequest = {
|
|
215
|
-
[key: string]:
|
|
267
|
+
[key: string]: unknown;
|
|
216
268
|
from: string;
|
|
217
269
|
to: string;
|
|
218
270
|
};
|
|
@@ -221,7 +273,7 @@ export type GetExchangeRateResponse = {
|
|
|
221
273
|
sell: number;
|
|
222
274
|
};
|
|
223
275
|
export type GetExchangeInfoRequest = {
|
|
224
|
-
[key: string]:
|
|
276
|
+
[key: string]: unknown;
|
|
225
277
|
minAmount: number;
|
|
226
278
|
maxAmount: number;
|
|
227
279
|
from: string;
|
|
@@ -235,7 +287,7 @@ export type GetExchangeInfoResponse = {
|
|
|
235
287
|
exchanged_amount_to: number;
|
|
236
288
|
};
|
|
237
289
|
export type GetExchangeStatusRequest = {
|
|
238
|
-
[key: string]:
|
|
290
|
+
[key: string]: unknown;
|
|
239
291
|
id?: number;
|
|
240
292
|
externalId?: string;
|
|
241
293
|
};
|
|
@@ -249,7 +301,7 @@ export type GetExchangeStatusResponse = {
|
|
|
249
301
|
status: string;
|
|
250
302
|
};
|
|
251
303
|
export type GetBalanceStatisticsRequest = {
|
|
252
|
-
[key: string]:
|
|
304
|
+
[key: string]: unknown;
|
|
253
305
|
currency: string;
|
|
254
306
|
};
|
|
255
307
|
export type GetBalanceStatisticsResponse = {
|
|
@@ -263,7 +315,7 @@ export type GetBalanceStatisticsResponse = {
|
|
|
263
315
|
contract_balance: number;
|
|
264
316
|
};
|
|
265
317
|
export type GetDaysBalanceStatisticsRequest = {
|
|
266
|
-
[key: string]:
|
|
318
|
+
[key: string]: unknown;
|
|
267
319
|
currency: string;
|
|
268
320
|
start: string;
|
|
269
321
|
finish: string;
|
|
@@ -294,7 +346,7 @@ export type GetPayTypesStatisticsResponse = {
|
|
|
294
346
|
checkout: PaySystem[];
|
|
295
347
|
};
|
|
296
348
|
export type CreateTerminalRequest = {
|
|
297
|
-
[key: string]:
|
|
349
|
+
[key: string]: unknown;
|
|
298
350
|
user: string;
|
|
299
351
|
amount?: number;
|
|
300
352
|
comment?: string;
|
|
@@ -304,21 +356,26 @@ export type CreateTerminalRequest = {
|
|
|
304
356
|
currency?: string;
|
|
305
357
|
use_user_select_currency?: 'yes' | 'no';
|
|
306
358
|
language?: string;
|
|
359
|
+
return_mode?: 'skip';
|
|
360
|
+
recurring?: 'yes';
|
|
307
361
|
terminal_allow_methods?: string[];
|
|
308
362
|
terminal_disable_methods?: string[];
|
|
363
|
+
terminal_livetime?: number;
|
|
364
|
+
terminal_country?: string;
|
|
365
|
+
terminal_theme?: 'dark' | 'light';
|
|
309
366
|
};
|
|
310
367
|
export type CreateTerminalResponse = {
|
|
311
368
|
url: string;
|
|
312
369
|
};
|
|
313
370
|
export type InvoiceStatus = 'New' | 'Processing' | 'Paid' | 'Chargeback' | 'Refund' | 'Chargeback_cancel' | 'Refused';
|
|
314
371
|
export type InvoiceNotification = {
|
|
315
|
-
project:
|
|
316
|
-
invoice:
|
|
372
|
+
project: string;
|
|
373
|
+
invoice: string;
|
|
317
374
|
status: InvoiceStatus;
|
|
318
|
-
amount:
|
|
319
|
-
net_amount:
|
|
320
|
-
recieved_amount:
|
|
321
|
-
rate?:
|
|
375
|
+
amount: string;
|
|
376
|
+
net_amount: string;
|
|
377
|
+
recieved_amount: string;
|
|
378
|
+
rate?: string;
|
|
322
379
|
user: string;
|
|
323
380
|
type: string;
|
|
324
381
|
wallet: string;
|
|
@@ -360,6 +417,7 @@ export type TransferNotification = {
|
|
|
360
417
|
currency: string;
|
|
361
418
|
user: string;
|
|
362
419
|
type: string;
|
|
420
|
+
project: number;
|
|
363
421
|
ip: string;
|
|
364
422
|
time: number;
|
|
365
423
|
comment: string;
|
|
@@ -369,21 +427,32 @@ type Payload = Record<string, unknown>;
|
|
|
369
427
|
export declare class GameMoneyError extends Error {
|
|
370
428
|
constructor(message: string);
|
|
371
429
|
}
|
|
372
|
-
export
|
|
430
|
+
export declare class GameMoneyHttpError extends Error {
|
|
431
|
+
readonly status: number;
|
|
432
|
+
constructor(status: number, statusText: string);
|
|
433
|
+
}
|
|
434
|
+
export declare class GameMoney {
|
|
373
435
|
private readonly config;
|
|
374
|
-
private readonly got;
|
|
375
436
|
constructor(config: Config);
|
|
376
437
|
request<T extends GenericResponse>(url: string, payload?: Payload, signType?: SignType): Promise<T>;
|
|
377
|
-
generateHmacSignature(body:
|
|
378
|
-
verifyRsaSignature(body:
|
|
438
|
+
generateHmacSignature(body: Record<string, unknown>): string;
|
|
439
|
+
verifyRsaSignature(body: unknown): boolean;
|
|
379
440
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#invoice_insert_api) */
|
|
380
441
|
createInvoice(body: CreateInvoiceRequest): Promise<CreateInvoiceResponse & GenericResponse>;
|
|
381
442
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#invoice_status) */
|
|
382
443
|
getInvoiceStatus(body: GetInvoiceStatusRequest): Promise<GetInvoiceStatusResponse & GenericResponse>;
|
|
383
444
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#invoice_list) */
|
|
384
445
|
getInvoiceList(body: GetInvoiceListRequest): Promise<GetInvoiceListResponse & GenericResponse>;
|
|
446
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#invoice_add_token) */
|
|
447
|
+
addTokenInvoice(body: AddTokenInvoiceRequest): Promise<AddTokenInvoiceResponse & GenericResponse>;
|
|
448
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#card_session_status) */
|
|
449
|
+
getCardSessionStatus(body: GetCardSessionStatusRequest): Promise<GetCardSessionStatusResponse & GenericResponse>;
|
|
385
450
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_insert) */
|
|
386
451
|
createCheckout(body: CreateCheckoutRequest): Promise<GenericResponse>;
|
|
452
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_prepare) */
|
|
453
|
+
prepareCheckout(body: PrepareCheckoutRequest): Promise<PrepareCheckoutResponse & GenericResponse>;
|
|
454
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_check) */
|
|
455
|
+
checkCheckout(body: CreateCheckoutRequest): Promise<GenericResponse>;
|
|
387
456
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_cancel) */
|
|
388
457
|
cancelCheckout(body: CancelCheckoutRequest): Promise<GenericResponse>;
|
|
389
458
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_status) */
|
|
@@ -398,7 +467,7 @@ export default class GameMoney {
|
|
|
398
467
|
getCardList(body: GetCardListRequest): Promise<GetCardListResponse & GenericResponse>;
|
|
399
468
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#card_fulllist) */
|
|
400
469
|
getCardFullList(body: GetCardFullListRequest): Promise<GetCardFullListResponse & GenericResponse>;
|
|
401
|
-
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#
|
|
470
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#card_delete) */
|
|
402
471
|
deleteCard(body: DeleteCardRequest): Promise<GenericResponse>;
|
|
403
472
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#exchange_prepare) */
|
|
404
473
|
prepareExchange(body: PrepareExchangeRequest): Promise<PrepareExchangeResponse & GenericResponse>;
|
|
@@ -421,4 +490,4 @@ export default class GameMoney {
|
|
|
421
490
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#invoice_api_terminal) */
|
|
422
491
|
createTerminal(body: CreateTerminalRequest): Promise<CreateTerminalResponse & GenericResponse>;
|
|
423
492
|
}
|
|
424
|
-
export
|
|
493
|
+
export default GameMoney;
|
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
})(SignType || (SignType = {}));
|
|
1
|
+
import { generateRsaSignature, generateHmacSignature, getRandomString, stringifyForm, verifyRsaSignature, } from './utils.js';
|
|
2
|
+
export { generateHmacSignature, generateRsaSignature, parametersToString, verifyRsaSignature, } from './utils.js';
|
|
3
|
+
export const SignType = {
|
|
4
|
+
HMAC: 'HMAC',
|
|
5
|
+
RSA: 'RSA',
|
|
6
|
+
};
|
|
8
7
|
export class GameMoneyError extends Error {
|
|
9
8
|
constructor(message) {
|
|
10
9
|
super(message);
|
|
11
10
|
this.name = 'GameMoneyError';
|
|
12
11
|
}
|
|
13
12
|
}
|
|
14
|
-
export
|
|
13
|
+
export class GameMoneyHttpError extends Error {
|
|
14
|
+
status;
|
|
15
|
+
constructor(status, statusText) {
|
|
16
|
+
super(`Response code ${status} (${statusText})`);
|
|
17
|
+
this.name = 'GameMoneyHttpError';
|
|
18
|
+
this.status = status;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class GameMoney {
|
|
15
22
|
config;
|
|
16
|
-
got = got.extend({
|
|
17
|
-
prefixUrl: 'https://paygate.gamemoney.com',
|
|
18
|
-
responseType: 'json',
|
|
19
|
-
});
|
|
20
23
|
constructor(config) {
|
|
21
24
|
this.config = config;
|
|
22
|
-
this.config = config;
|
|
23
25
|
}
|
|
24
26
|
async request(url, payload = {}, signType = SignType.HMAC) {
|
|
25
27
|
const form = {
|
|
26
|
-
rand: getRandomString(20),
|
|
27
|
-
project: this.config.project,
|
|
28
28
|
...payload,
|
|
29
|
+
project: payload.project ?? this.config.project,
|
|
30
|
+
rand: payload.rand ?? getRandomString(20),
|
|
29
31
|
};
|
|
30
32
|
if (signType === SignType.RSA) {
|
|
31
|
-
if (
|
|
33
|
+
if (this.config.rsaPrivateKey === undefined) {
|
|
32
34
|
throw new Error("To make requests with RSA sign type, 'rsaPrivateKey' must be provided");
|
|
33
35
|
}
|
|
34
36
|
form.signature = generateRsaSignature(form, this.config.rsaPrivateKey);
|
|
@@ -36,12 +38,22 @@ export default class GameMoney {
|
|
|
36
38
|
else {
|
|
37
39
|
form.signature = generateHmacSignature(form, this.config.hmacPrivateKey);
|
|
38
40
|
}
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const httpResponse = await fetch(new URL(url, this.config.apiUrl ?? 'https://paygate.gamemoney.com'), {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
accept: 'application/json',
|
|
45
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
46
|
+
},
|
|
47
|
+
body: stringifyForm(form),
|
|
48
|
+
signal: this.config.timeout === undefined
|
|
49
|
+
? null
|
|
50
|
+
: AbortSignal.timeout(this.config.timeout),
|
|
43
51
|
});
|
|
44
|
-
if (!
|
|
52
|
+
if (!httpResponse.ok) {
|
|
53
|
+
throw new GameMoneyHttpError(httpResponse.status, httpResponse.statusText);
|
|
54
|
+
}
|
|
55
|
+
const response = (await httpResponse.json());
|
|
56
|
+
if (!verifyRsaSignature(response, this.config.gameMoneyPublicKey)) {
|
|
45
57
|
throw new Error('Response signature mismatch');
|
|
46
58
|
}
|
|
47
59
|
if (form.rand !== response.rand) {
|
|
@@ -56,7 +68,7 @@ export default class GameMoney {
|
|
|
56
68
|
return generateHmacSignature(body, this.config.hmacPrivateKey);
|
|
57
69
|
}
|
|
58
70
|
verifyRsaSignature(body) {
|
|
59
|
-
return verifyRsaSignature(body);
|
|
71
|
+
return verifyRsaSignature(body, this.config.gameMoneyPublicKey);
|
|
60
72
|
}
|
|
61
73
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#invoice_insert_api) */
|
|
62
74
|
async createInvoice(body) {
|
|
@@ -70,10 +82,26 @@ export default class GameMoney {
|
|
|
70
82
|
async getInvoiceList(body) {
|
|
71
83
|
return this.request('invoice/list', body);
|
|
72
84
|
}
|
|
85
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#invoice_add_token) */
|
|
86
|
+
async addTokenInvoice(body) {
|
|
87
|
+
return this.request('invoice/addtoken', body);
|
|
88
|
+
}
|
|
89
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#card_session_status) */
|
|
90
|
+
async getCardSessionStatus(body) {
|
|
91
|
+
return this.request('invoice/cardsession/status', body);
|
|
92
|
+
}
|
|
73
93
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_insert) */
|
|
74
94
|
async createCheckout(body) {
|
|
75
95
|
return this.request('checkout/insert', body, SignType.RSA);
|
|
76
96
|
}
|
|
97
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_prepare) */
|
|
98
|
+
async prepareCheckout(body) {
|
|
99
|
+
return this.request('checkout/prepare', body);
|
|
100
|
+
}
|
|
101
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_check) */
|
|
102
|
+
async checkCheckout(body) {
|
|
103
|
+
return this.request('checkout/check', body, SignType.RSA);
|
|
104
|
+
}
|
|
77
105
|
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#checkout_cancel) */
|
|
78
106
|
async cancelCheckout(body) {
|
|
79
107
|
return this.request('checkout/cancel', body);
|
|
@@ -102,7 +130,7 @@ export default class GameMoney {
|
|
|
102
130
|
async getCardFullList(body) {
|
|
103
131
|
return this.request('card/fulllist', body);
|
|
104
132
|
}
|
|
105
|
-
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#
|
|
133
|
+
/** For more details and usage information see [docs](https://cp.gmpays.com/apidoc#card_delete) */
|
|
106
134
|
async deleteCard(body) {
|
|
107
135
|
return this.request('card/delete', body);
|
|
108
136
|
}
|
|
@@ -147,3 +175,4 @@ export default class GameMoney {
|
|
|
147
175
|
return this.request('terminal/create', body);
|
|
148
176
|
}
|
|
149
177
|
}
|
|
178
|
+
export default GameMoney;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import crypto from 'node:crypto';
|
|
3
2
|
export type RsaKey = Parameters<crypto.Sign['sign']>[0];
|
|
3
|
+
export type RsaPublicKey = Parameters<crypto.Verify['verify']>[0];
|
|
4
4
|
export type HmacKey = Parameters<typeof crypto.createHmac>[1];
|
|
5
5
|
type JsonPrimitive = number | number[] | string | string[] | undefined | null;
|
|
6
6
|
type Json = {
|
|
7
7
|
[key: string]: Json | JsonPrimitive;
|
|
8
8
|
};
|
|
9
|
-
type
|
|
10
|
-
|
|
11
|
-
}
|
|
9
|
+
type FormValue = string | number | boolean | bigint | undefined | null | FormValue[] | {
|
|
10
|
+
[key: string]: FormValue;
|
|
11
|
+
};
|
|
12
12
|
export declare function parametersToString(body: Json): string;
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function stringifyForm(form: Record<string, FormValue>): string;
|
|
14
|
+
export declare function verifyRsaSignature(body: unknown, publicKey?: RsaPublicKey): boolean;
|
|
14
15
|
export declare function generateRsaSignature(body: Json, key: RsaKey): string;
|
|
15
16
|
export declare function generateHmacSignature(body: Json, key: HmacKey): string;
|
|
16
17
|
export declare function getRandomString(length: number): string;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { gameMoneyCertificate } from './certificate.js';
|
|
3
|
+
export function parametersToString(body) {
|
|
4
|
+
let parametersString = '';
|
|
5
|
+
const keys = Object.keys(body).sort();
|
|
6
|
+
if (Array.isArray(body)) {
|
|
7
|
+
keys.sort((a, b) => Number(a) - Number(b));
|
|
8
|
+
}
|
|
9
|
+
for (const key of keys) {
|
|
10
|
+
let value = body[key];
|
|
11
|
+
if (key === 'signature') {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (value === null || value === undefined) {
|
|
15
|
+
value = '';
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === 'object' && value !== null) {
|
|
18
|
+
value = parametersToString(value);
|
|
19
|
+
}
|
|
20
|
+
parametersString += `${key}:${value};`;
|
|
21
|
+
}
|
|
22
|
+
return parametersString;
|
|
23
|
+
}
|
|
24
|
+
// Wire format of gamemoney@3 (request + qs): RFC 3986 escaping, nested values as `key[index]=value`
|
|
25
|
+
function encodeFormComponent(value) {
|
|
26
|
+
return encodeURIComponent(value).replaceAll(/[!'()*]/g, (char) => `%${char.codePointAt(0).toString(16).toUpperCase()}`);
|
|
27
|
+
}
|
|
28
|
+
function appendFormValue(pairs, key, value) {
|
|
29
|
+
if (value === undefined) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === 'object' && value !== null) {
|
|
33
|
+
for (const [nestedKey, nestedValue] of Object.entries(value)) {
|
|
34
|
+
appendFormValue(pairs, `${key}[${nestedKey}]`, nestedValue);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
pairs.push(`${encodeFormComponent(key)}=${encodeFormComponent(value === null ? '' : String(value))}`);
|
|
39
|
+
}
|
|
40
|
+
export function stringifyForm(form) {
|
|
41
|
+
const pairs = [];
|
|
42
|
+
for (const [key, value] of Object.entries(form)) {
|
|
43
|
+
appendFormValue(pairs, key, value);
|
|
44
|
+
}
|
|
45
|
+
return pairs.join('&');
|
|
46
|
+
}
|
|
47
|
+
export function verifyRsaSignature(body, publicKey = gameMoneyCertificate) {
|
|
48
|
+
if (typeof body !== 'object' ||
|
|
49
|
+
body === null ||
|
|
50
|
+
!('signature' in body) ||
|
|
51
|
+
typeof body.signature !== 'string' ||
|
|
52
|
+
body.signature === '') {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return crypto
|
|
56
|
+
.createVerify('RSA-SHA256')
|
|
57
|
+
.update(parametersToString(body), 'utf8')
|
|
58
|
+
.verify(publicKey, body.signature, 'base64');
|
|
59
|
+
}
|
|
60
|
+
export function generateRsaSignature(body, key) {
|
|
61
|
+
return crypto
|
|
62
|
+
.createSign('RSA-SHA256')
|
|
63
|
+
.update(parametersToString(body), 'utf8')
|
|
64
|
+
.sign(key, 'base64');
|
|
65
|
+
}
|
|
66
|
+
export function generateHmacSignature(body, key) {
|
|
67
|
+
return crypto
|
|
68
|
+
.createHmac('sha256', key)
|
|
69
|
+
.update(parametersToString(body), 'utf8')
|
|
70
|
+
.digest('hex');
|
|
71
|
+
}
|
|
72
|
+
export function getRandomString(length) {
|
|
73
|
+
return crypto
|
|
74
|
+
.randomBytes(Math.ceil(length / 2))
|
|
75
|
+
.toString('hex')
|
|
76
|
+
.slice(0, length);
|
|
77
|
+
}
|
package/package.json
CHANGED
|
@@ -1,85 +1,76 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"ts-jest": "^29.0.5",
|
|
78
|
-
"typescript": "^4.9.5",
|
|
79
|
-
"uuid": "^9.0.0",
|
|
80
|
-
"xo": "^0.53.1"
|
|
81
|
-
},
|
|
82
|
-
"dependencies": {
|
|
83
|
-
"got": "^12.5.3"
|
|
84
|
-
}
|
|
85
|
-
}
|
|
2
|
+
"name": "gamemoney",
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "GameMoney API wrapper for Node.js",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"gamemoney",
|
|
7
|
+
"gmpays",
|
|
8
|
+
"gm",
|
|
9
|
+
"merchant"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/gamemoney-ps/gamemoney-node-sdk#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/gamemoney-ps/gamemoney-node-sdk/issues",
|
|
14
|
+
"email": "maxpain@linux.com"
|
|
15
|
+
},
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "Max Makarov",
|
|
18
|
+
"email": "maxpain@linux.com"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/gamemoney-ps/gamemoney-node-sdk.git"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./package.json": "./package.json"
|
|
32
|
+
},
|
|
33
|
+
"main": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"sideEffects": false,
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22.12.0"
|
|
41
|
+
},
|
|
42
|
+
"devEngines": {
|
|
43
|
+
"runtime": {
|
|
44
|
+
"name": "node",
|
|
45
|
+
"version": ">=22.22.1",
|
|
46
|
+
"onFail": "error"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
51
|
+
"typecheck": "tsc",
|
|
52
|
+
"test": "node --test 'src/**/*.test.ts'",
|
|
53
|
+
"lint": "oxlint && oxfmt --check",
|
|
54
|
+
"lint:fix": "oxlint --fix && oxfmt",
|
|
55
|
+
"prepublishOnly": "npm run lint && npm run typecheck && npm test",
|
|
56
|
+
"prepack": "npm run build",
|
|
57
|
+
"prepare": "husky"
|
|
58
|
+
},
|
|
59
|
+
"lint-staged": {
|
|
60
|
+
"*.ts": "oxlint",
|
|
61
|
+
"*": "oxfmt --check --no-error-on-unmatched-pattern"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@types/body-parser": "^1.19.6",
|
|
65
|
+
"@types/express": "^5.0.6",
|
|
66
|
+
"@types/node": "^22.20.5",
|
|
67
|
+
"body-parser": "^2.4.0",
|
|
68
|
+
"express": "^5.3.0",
|
|
69
|
+
"husky": "^9.1.7",
|
|
70
|
+
"lint-staged": "^17.6.0",
|
|
71
|
+
"oxfmt": "^0.74.0",
|
|
72
|
+
"oxlint": "^1.89.0",
|
|
73
|
+
"oxlint-tsgolint": "^7.0.2005",
|
|
74
|
+
"typescript": "^7.0.2"
|
|
75
|
+
}
|
|
76
|
+
}
|
package/utils.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { URL } from 'node:url';
|
|
2
|
-
import crypto from 'node:crypto';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
const publicCert = fs
|
|
5
|
-
.readFileSync(new URL('certs/gm.crt', import.meta.url))
|
|
6
|
-
.toString();
|
|
7
|
-
export function parametersToString(body) {
|
|
8
|
-
let parametersString = '';
|
|
9
|
-
const keys = Object.keys(body).sort();
|
|
10
|
-
if (Array.isArray(body)) {
|
|
11
|
-
keys.sort((a, b) => Number(a) - Number(b));
|
|
12
|
-
}
|
|
13
|
-
for (const key of keys) {
|
|
14
|
-
let value = body[key];
|
|
15
|
-
if (key === 'signature') {
|
|
16
|
-
continue;
|
|
17
|
-
}
|
|
18
|
-
if (value === null || value === undefined) {
|
|
19
|
-
value = '';
|
|
20
|
-
}
|
|
21
|
-
if (typeof value === 'object' && value !== null) {
|
|
22
|
-
value = parametersToString(value);
|
|
23
|
-
}
|
|
24
|
-
parametersString += `${key}:${value};`;
|
|
25
|
-
}
|
|
26
|
-
return parametersString;
|
|
27
|
-
}
|
|
28
|
-
export function verifyRsaSignature(body) {
|
|
29
|
-
return crypto
|
|
30
|
-
.createVerify('RSA-SHA256')
|
|
31
|
-
.update(parametersToString(body), 'utf8')
|
|
32
|
-
.verify(publicCert, body.signature, 'base64');
|
|
33
|
-
}
|
|
34
|
-
export function generateRsaSignature(body, key) {
|
|
35
|
-
return crypto
|
|
36
|
-
.createSign('RSA-SHA256')
|
|
37
|
-
.update(parametersToString(body), 'utf8')
|
|
38
|
-
.sign(key, 'base64');
|
|
39
|
-
}
|
|
40
|
-
export function generateHmacSignature(body, key) {
|
|
41
|
-
return crypto
|
|
42
|
-
.createHmac('sha256', key)
|
|
43
|
-
.update(parametersToString(body), 'utf8')
|
|
44
|
-
.digest('hex');
|
|
45
|
-
}
|
|
46
|
-
export function getRandomString(length) {
|
|
47
|
-
return crypto
|
|
48
|
-
.randomBytes(Math.ceil(length / 2))
|
|
49
|
-
.toString('hex')
|
|
50
|
-
.slice(0, length);
|
|
51
|
-
}
|