Skip to content

Commit

Permalink
Using new payment api
Browse files Browse the repository at this point in the history
  • Loading branch information
edolganov committed Aug 22, 2024
1 parent ce7b712 commit bbbe0c4
Show file tree
Hide file tree
Showing 18 changed files with 449 additions and 288 deletions.
33 changes: 26 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@
"typescript": "^5.5.4"
},
"dependencies": {
"smartypay-client-model": "2.30.0"
"smartypay-client-model": "2.34.0"
}
}
11 changes: 7 additions & 4 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
SMARTy Pay Node SDK
@author Evgeny Dolganov <[email protected]>
*/

import { SmartyPayAPI } from './index';

import type { Currency } from 'smartypay-client-model';
Expand Down Expand Up @@ -82,7 +83,7 @@ function printHelp() {
}

function processPaymentReq(input?: string) {
if (input) {
if (input || input === '') {
const curKey = findEmptyPaymentKey();
if (curKey) {
setPaymentKey(curKey, input);
Expand Down Expand Up @@ -124,9 +125,11 @@ async function createPayment() {
const api = new SmartyPayAPI(cred);

const result = await api.payments.createPayment({
expiresAt: new Date(paymentReq.expiresAt!),
amount: paymentReq.amount!,
token: paymentReq.token! as Currency,
expiresAt: paymentReq.expiresAt ? new Date(paymentReq.expiresAt) : undefined,
amount: {
value: paymentReq.amount!,
currency: paymentReq.token! as Currency,
},
metadata: paymentReq.metadata,
});

Expand Down
19 changes: 19 additions & 0 deletions src/common/apiHost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
SMARTy Pay Node SDK
@author Evgeny Dolganov <[email protected]>
*/

import { removeEnd } from '../util';

import type { ApiOpt } from './type';

export function apiHost({ host, isStaging }: ApiOpt) {
// custom host
if (host) return removeEnd(host, '/');

// staging api
if (isStaging) return 'https://ncps-api.staging.mnxsc.tech';

// default prod api
return 'https://api.smartypay.io';
}
10 changes: 10 additions & 0 deletions src/common/getMessageSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
SMARTy Pay Node SDK
@author Evgeny Dolganov <[email protected]>
*/

import { CryptoUtil } from '../util/CryptoUtil';

export function getMessageSignature(message: string, secretKey: string): string {
return CryptoUtil.hmacSha256Hex(secretKey, message);
}
34 changes: 34 additions & 0 deletions src/common/getSignReq.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
SMARTy Pay Node SDK
@author Evgeny Dolganov <[email protected]>
*/

import { CryptoUtil } from '../util/CryptoUtil';
import { get } from '../util/NetUtil';

import { apiHost } from './apiHost';

import type { ApiOpt } from './type';

export async function getSignReq<T>(apiPath: string, apiOpt: ApiOpt): Promise<T> {
const { secretKey, publicKey, timeout } = apiOpt;

const now = Date.now();
const ts = Math.round(now / 1000).toString();
const messageToSign = `${ts}GET${apiPath}`;
const sig = CryptoUtil.hmacSha256Hex(secretKey, messageToSign);
const targetHost = apiHost(apiOpt);

const resp = await get(`${targetHost}${apiPath}`, undefined, {
headers: {
accept: 'application/json',
'content-type': 'application/json',
'x-api-key': publicKey,
'x-api-sig': sig,
'x-api-ts': ts,
},
timeout,
});

return JSON.parse(resp) as T;
}
14 changes: 14 additions & 0 deletions src/common/isValidSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
SMARTy Pay Node SDK
@author Evgeny Dolganov <[email protected]>
*/

import { getMessageSignature } from './getMessageSignature';

/**
* Check Sha256 signature.
* [Docs](https://docs.smartypay.io/api/webhooks)
*/
export function isValidSignature(message: string, signature: string, secretKey: string): boolean {
return getMessageSignature(message, secretKey) === signature;
}
35 changes: 35 additions & 0 deletions src/common/postSignReq.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
SMARTy Pay Node SDK
@author Evgeny Dolganov <[email protected]>
*/

import { CryptoUtil } from '../util/CryptoUtil';
import { post } from '../util/NetUtil';

import { apiHost } from './apiHost';

import type { ApiOpt } from './type';

export async function postSignReq<T>(apiPath: string, bodyData: any, signReq: ApiOpt): Promise<T> {
const { secretKey, publicKey, timeout } = signReq;

const now = Date.now();
const ts = Math.round(now / 1000).toString();
const body = JSON.stringify(bodyData);
const messageToSign = `${ts}POST${apiPath}${body}`;
const sig = CryptoUtil.hmacSha256Hex(secretKey, messageToSign);
const targetHost = apiHost(signReq);

const resp = await post(`${targetHost}${apiPath}`, body, {
headers: {
accept: 'application/json',
'content-type': 'application/json',
'x-api-key': publicKey,
'x-api-sig': sig,
'x-api-ts': ts,
},
timeout,
});

return JSON.parse(resp) as T;
}
21 changes: 21 additions & 0 deletions src/common/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
SMARTy Pay Node SDK
@author Evgeny Dolganov <[email protected]>
*/

import type { Currency } from 'smartypay-client-model';

export interface ApiOpt {
publicKey: string;
secretKey: string;
timeout?: number;
host?: string;
isStaging?: boolean;
}

export interface Amount {
value: string;
currency: Currency;
}

export const OneDayDelta = 1000 * 60 * 60 * 24;
46 changes: 36 additions & 10 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,59 @@ import { SmartyPayAPI } from './index';
import type { ApiOpt } from './index';

describe('SmartyPayAPI', () => {
// test access on stage
const PublicKey = 's5FGH1xnRMs6WGPEFX9oIlxYDYEYX4Sg';
const SecretKey = 'ltbUjBfqXqwJLf3hToVTTvHho5YRaR3SnL2Dh20x3P3f0A462gmMlUa4pfYq1ScM';

describe('utils', () => {
const api = SmartyPayAPI.utils;
const { utils } = SmartyPayAPI;

const message = 'test data';
const secret = 'test key';
// generated by https://www.devglan.com/online-tools/hmac-sha256-online
const signature = '4695788ca94015a246422be13bbd966ade571842efc3a39296bdb6f2377597ff';

test('getMessageSignature', () => {
expect(api.getMessageSignature(message, secret)).toBe(signature);
expect(api.getMessageSignature(`NOT-${message}`, secret)).not.toBe(signature);
expect(api.getMessageSignature(message, `NOT-${secret}`)).not.toBe(signature);
expect(utils.getMessageSignature(message, secret)).toBe(signature);
expect(utils.getMessageSignature(`NOT-${message}`, secret)).not.toBe(signature);
expect(utils.getMessageSignature(message, `NOT-${secret}`)).not.toBe(signature);
});

test('isValidSignature', () => {
expect(api.isValidSignature(message, signature, secret)).toBe(true);
expect(api.isValidSignature(`NOT-${message}`, signature, secret)).toBe(false);
expect(api.isValidSignature(message, `NOT-${signature}`, secret)).toBe(false);
expect(api.isValidSignature(message, signature, `NOT-${secret}`)).toBe(false);
expect(utils.isValidSignature(message, signature, secret)).toBe(true);
expect(utils.isValidSignature(`NOT-${message}`, signature, secret)).toBe(false);
expect(utils.isValidSignature(message, `NOT-${signature}`, secret)).toBe(false);
expect(utils.isValidSignature(message, signature, `NOT-${secret}`)).toBe(false);
});
});

describe('payments', () => {
const apiOpt: ApiOpt = {
isStaging: true,
publicKey: PublicKey,
secretKey: SecretKey,
};

const api = new SmartyPayAPI(apiOpt).payments;

test('createPayment', async () => {
const result = await api.createPayment({
amount: {
value: '1',
currency: 'btUSDTv2',
},
});

expect(result).not.toBeUndefined();
expect(result.status).toBe('Created');
});
});

describe('subscriptions', () => {
const apiOpt: ApiOpt = {
isStaging: true,
publicKey: 's5FGH1xnRMs6WGPEFX9oIlxYDYEYX4Sg',
secretKey: 'ltbUjBfqXqwJLf3hToVTTvHho5YRaR3SnL2Dh20x3P3f0A462gmMlUa4pfYq1ScM',
publicKey: PublicKey,
secretKey: SecretKey,
};

const api = new SmartyPayAPI(apiOpt).subscriptions;
Expand Down
Loading

0 comments on commit bbbe0c4

Please sign in to comment.