mirror of
https://github.com/valitydev/macho.git
synced 2024-11-06 00:15:18 +00:00
Initial import
This commit is contained in:
commit
80f11d1aca
9
.env
Normal file
9
.env
Normal file
@ -0,0 +1,9 @@
|
||||
#AUTH_ENDPOINT="http://auth.rbk.test:8080"
|
||||
#CAPI_ENDPOINT="http://api.rbk.test:8080"
|
||||
#ADMIN_ENDPOINT="http://iddqd.rbk.test:8080"
|
||||
#PROXY_ENDPOINT="http://wrapper.rbk.test:8080"
|
||||
#URL_SHORTENER_ENDPOINT="http://short.rbk.test:8080"
|
||||
#EXTERNAL_LOGIN="demo_merchant"
|
||||
#EXTERNAL_PASSWORD="test"
|
||||
#INTERNAL_LOGIN="manager"
|
||||
#INTERNAL_PASSWORD="manager"
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/build/
|
||||
/node_modules/
|
||||
/api/**/codegen/
|
||||
mocha-tests
|
6
.prettierignore
Normal file
6
.prettierignore
Normal file
@ -0,0 +1,6 @@
|
||||
package.json
|
||||
package-lock.json
|
||||
/node_modules/
|
||||
/lib/
|
||||
/api/**/codegen/
|
||||
/build/
|
8
.prettierrc
Normal file
8
.prettierrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"useTabs": false,
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"bracketSpacing": true
|
||||
}
|
120
Makefile
Normal file
120
Makefile
Normal file
@ -0,0 +1,120 @@
|
||||
.SUFFIXES:
|
||||
|
||||
NPM = $(shell which npm 2>/dev/null || exit 1)
|
||||
TSC = ./node_modules/.bin/tsc
|
||||
PKG = ./node_modules/.bin/pkg
|
||||
|
||||
PKG_CACHE_PATH = $(HOME)/.cache/pkg
|
||||
export PKG_CACHE_PATH
|
||||
|
||||
TESTS_ARGS = \
|
||||
--external-login '$(TT_LOGIN)' \
|
||||
--external-password '$(TT_PASSWORD)' \
|
||||
--internal-login '$(TT_INTERNAL_LOGIN)' \
|
||||
--internal-password '$(TT_INTERNAL_PASSWORD)' \
|
||||
--capi-endpoint $(TT_CAPI_ENDPOINT) \
|
||||
--url-shortener-endpoint $(TT_URLSHORT_ENDPOINT) \
|
||||
--test-webhook-receiver-endpoint $(TT_TEST_WEBHOOK_RECEIVER_ENDPOINT) \
|
||||
--auth-endpoint $(TT_AUTH_ENDPOINT) \
|
||||
--admin-endpoint $(TT_ADMIN_ENDPOINT) \
|
||||
--proxy-endpoint $(TT_PROXY_ENDPOINT)
|
||||
|
||||
SWAG_V2 = ../../schemes/swag/v2/swagger.json
|
||||
SWAG_ANALYTICS = ../../schemes/swag-analytics/swagger.json
|
||||
SWAG_BINBASE = ../../schemes/swag-binbase/swagger.json
|
||||
SWAG_URL_SHORTENER_V1 = ../../schemes/swag-url-shortener/v1/swagger.json
|
||||
SWAG_WAPI_PAYRES_V0 = ../../schemes/swag-wallets/v0/api/payres/swagger.json
|
||||
SWAG_WAPI_PRIVDOC_V0 = ../../schemes/swag-wallets/v0/api/privdoc/swagger.json
|
||||
SWAG_WAPI_WALLET_V0 = ../../schemes/swag-wallets/v0/api/wallet/swagger.json
|
||||
|
||||
GEN_SWAG_V2 = ./api/capi-v2/codegen
|
||||
GEN_SWAG_ANAL = ./api/anapi/codegen
|
||||
GEN_SWAG_BINBASE = ./api/binapi/codegen
|
||||
GEN_SWAG_URL_SHORTENER_V1 = ./api/url-shortener-v1/codegen
|
||||
GEN_SWAG_WAPI_PAYRES_V0 = ./api/wapi-v0/payres/codegen
|
||||
GEN_SWAG_WAPI_PRIVDOC_V0 = ./api/wapi-v0/privdoc/codegen
|
||||
GEN_SWAG_WAPI_WALLET_V0 = ./api/wapi-v0/wallet/codegen
|
||||
GEN_SWAG = \
|
||||
$(GEN_SWAG_V2) \
|
||||
$(GEN_SWAG_ANAL) \
|
||||
$(GEN_SWAG_BINBASE) \
|
||||
$(GEN_SWAG_URL_SHORTENER_V1) \
|
||||
$(GEN_SWAG_WAPI_PAYRES_V0) \
|
||||
$(GEN_SWAG_WAPI_PRIVDOC_V0) \
|
||||
$(GEN_SWAG_WAPI_WALLET_V0)
|
||||
|
||||
.PHONY: mocha-tests mocha-tests.tar.gz distclean
|
||||
|
||||
# XXX node_modules dir is here to fix import errors in test files
|
||||
mocha-tests.tar.gz: mocha-tests
|
||||
tar zcf mocha-tests.tar.gz -C build . -C .. $^ node_modules
|
||||
|
||||
# XXX not installing pkg globally to avoid issues with permissions and bin path
|
||||
mocha-tests: $(TSC) $(PKG) $(GEN_SWAG)
|
||||
$(TSC)
|
||||
$(PKG) -t node8-linux-x64 mocha-tests.js -o $@
|
||||
|
||||
$(GEN_SWAG_V2): $(SWAG_V2)
|
||||
$(call swagger-codegen,$<,$@)
|
||||
|
||||
$(GEN_SWAG_ANAL): $(SWAG_ANALYTICS)
|
||||
$(call swagger-codegen,$<,$@)
|
||||
|
||||
$(GEN_SWAG_BINBASE): $(SWAG_BINBASE)
|
||||
$(call swagger-codegen,$<,$@)
|
||||
|
||||
$(GEN_SWAG_URL_SHORTENER_V1): $(SWAG_URL_SHORTENER_V1)
|
||||
$(call swagger-codegen,$<,$@)
|
||||
|
||||
$(GEN_SWAG_WAPI_PAYRES_V0): $(SWAG_WAPI_PAYRES_V0)
|
||||
$(call swagger-codegen,$<,$@)
|
||||
|
||||
$(GEN_SWAG_WAPI_PRIVDOC_V0): $(SWAG_WAPI_PRIVDOC_V0)
|
||||
$(call swagger-codegen,$<,$@)
|
||||
|
||||
$(GEN_SWAG_WAPI_WALLET_V0): $(SWAG_WAPI_WALLET_V0)
|
||||
$(call swagger-codegen,$<,$@)
|
||||
|
||||
$(TSC):
|
||||
$(NPM) i
|
||||
|
||||
$(PKG):
|
||||
$(NPM) i pkg
|
||||
|
||||
distclean:
|
||||
rm -rf ./node_modules ./build ./mocha-tests ./api/**/codegen
|
||||
|
||||
# tests
|
||||
|
||||
.PHONY: test test.suite test.transaction
|
||||
|
||||
test: test.suite test.transaction
|
||||
|
||||
test.suite: mocha-tests
|
||||
./mocha-tests $(TESTS_ARGS)
|
||||
|
||||
test.transaction: mocha-tests
|
||||
./mocha-tests --tt --timeout $(TT_TIMEOUT) \
|
||||
$(TESTS_ARGS) \
|
||||
--test-shop-id $(TT_SHOP_ID) --create-test-shop \
|
||||
--login-warn $(TT_LOGIN_WARN) \
|
||||
--get-my-party-warn $(TT_GET_MY_PARTY_WARN) \
|
||||
--create-invoice-warn $(TT_CREATE_INVOICE_WARN) \
|
||||
--tokenize-card-warn $(TT_TOKENIZE_CARD_WARN) \
|
||||
--create-payment-warn $(TT_CREATE_PAYMENT_WARN) \
|
||||
--fulfill-invoice-warn $(TT_FULFILL_INVOICE_WARN)
|
||||
|
||||
# swagger-codegen
|
||||
|
||||
SWAGGER_CODEGEN = swagger-codegen-cli-2.3.1.jar
|
||||
SWAGGER_CODEGEN_PREFIX = https://oss.sonatype.org/content/repositories/releases
|
||||
SWAGGER_CODEGEN_URL := $(SWAGGER_CODEGEN_PREFIX)/io/swagger/swagger-codegen-cli/2.3.1/$(SWAGGER_CODEGEN)
|
||||
|
||||
define swagger-codegen
|
||||
$(MAKE) $(SWAGGER_CODEGEN)
|
||||
java -jar $(SWAGGER_CODEGEN) generate -l typescript-fetch -i $(1) -o $(2)
|
||||
touch $(2)
|
||||
endef
|
||||
|
||||
$(SWAGGER_CODEGEN):
|
||||
wget $(SWAGGER_CODEGEN_URL)
|
79
README.md
Normal file
79
README.md
Normal file
@ -0,0 +1,79 @@
|
||||
# Тесты на Mocha
|
||||
|
||||
## Запуск
|
||||
|
||||
```
|
||||
make test
|
||||
```
|
||||
|
||||
## Локальная разработка
|
||||
|
||||
### Установка зависимостей и генерация swagger клиента
|
||||
|
||||
1. Установка зависимостей: `npm i`
|
||||
1. Генерация swagger typescript. Необходим swagger codegen версии **2.3.1**:
|
||||
- CAPI:
|
||||
- v2: `swagger-codegen generate -i ../../schemes/swag/v2/swagger.json -l typescript-fetch -o api/capi-v2/codegen`
|
||||
- Url shortener: `swagger-codegen generate -i ../../schemes/swag-url-shortener/v1/swagger.json -l typescript-fetch -o api/url-shortener-v1/codegen`
|
||||
- WAPI:
|
||||
- payres: `swagger-codegen generate -i ../../schemes/swag-wallets/v0/api/payres/swagger.json -l typescript-fetch -o api/wapi-v0/payres/codegen`
|
||||
- privdoc `swagger-codegen generate -i ../../schemes/swag-wallets/v0/api/privdoc/swagger.json -l typescript-fetch -o api/wapi-v0/privdoc/codegen`
|
||||
- wallet `swagger-codegen generate -i ../../schemes/swag-wallets/v0/api/wallet/swagger.json -l typescript-fetch -o api/wapi-v0/wallet/codegen`
|
||||
|
||||
### Вариант 1. Запуск использованием командной строки
|
||||
|
||||
Компиляция typescript после изменений в коде тестов: `./node_modules/.bin/tsc`
|
||||
|
||||
Запуск тестов: `node mocha-tests.js [options]`
|
||||
|
||||
`-h --help` - описание параметров запуска.
|
||||
|
||||
Пример:
|
||||
|
||||
```
|
||||
node mocha-tests.js --auth-endpoint http://auth.rbk.test:8080 --external-login demo_merchant --external-password test --capi-endpoint http://api.rbk.test:8080 --admin-endpoint http://iddqd.rbk.test:8080 --internal-login manager --internal-password manager --url-shortener-endpoint http://short.rbk.test:8080 --proxy-endpoint http://wrapper.rbk.test:8080 --test-webhook-receiver-endpoint http://test-webhook-receiver.rbk.test:8080
|
||||
```
|
||||
|
||||
### Вариант 2. Запуск и отладка с использованием Intellij IDEA, WebStorm
|
||||
|
||||
Настройка параметров тестов производится в [.env](.env)
|
||||
|
||||
В Run/Debug Configuration, необходимо настроить "Defaults" конфигурацию Mocha:
|
||||
|
||||
- Extra Mocha options: `--require ts-node/register --timeout 25000`
|
||||
- Выбрать File patterns, со значением: `test/**/*.spec.ts`
|
||||
- Working directory: `<...>/wetkitty/test/mocha`
|
||||
|
||||
Далее можно добавлять новую Mocha конфигурацию и запускать / отлаживать тесты
|
||||
|
||||
## Тестовая транзакция
|
||||
|
||||
### Сборка
|
||||
|
||||
`make mocha-tests`
|
||||
|
||||
В ходе этого собирается отдельный исполняемый файл пригодный для использования без nodejs на хостах, с которых идут тестовые транзакции на продакшн.
|
||||
|
||||
### Запуск
|
||||
|
||||
`--tt` - признак проведения тестовой транзакции
|
||||
|
||||
Если указан `--tt`, необходимо задать warning тайминги:
|
||||
|
||||
`--auth-warn <ms>`
|
||||
|
||||
`--create-invoice-warn <ms>`
|
||||
|
||||
`--create-payment-resource-warn <ms>`
|
||||
|
||||
`--create-payment-warn <ms>`
|
||||
|
||||
`--polling-warn <ms>`
|
||||
|
||||
`--fulfill-invoice-warn <ms>`
|
||||
|
||||
Пример:
|
||||
|
||||
```
|
||||
node mocha-tests.js --tt --create-invoice-warn 200 --create-payment-resource-warn 200 --create-payment-warn 200 --polling-warn 5000 --fullfill-invoice-warn 100 --auth-endpoint http://auth.rbk.test:8080 --external-login demo_merchant --external-password test --capi-endpoint http://api.rbk.test:8080 --internal-login manager --internal-password manager --admin-endpoint http://iddqd.rbk.test:8080 --proxy-endpoint http://wrapper.rbk.test:8080 --url-shortener-endpoint http://short.rbk.test:8080 --test-webhook-receiver-endpoint http://test-webhook-receiver.rbk.test:8080
|
||||
```
|
1
actions/anapi/index.ts
Normal file
1
actions/anapi/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './search-actions';
|
231
actions/anapi/search-actions.ts
Normal file
231
actions/anapi/search-actions.ts
Normal file
@ -0,0 +1,231 @@
|
||||
import * as chai from 'chai';
|
||||
import { Moment } from 'moment';
|
||||
import {
|
||||
SearchApiFp,
|
||||
InlineResponse2001,
|
||||
InlineResponse200,
|
||||
InlineResponse2003,
|
||||
InlineResponse2002
|
||||
} from '../../api/anapi/codegen';
|
||||
import guid from '../../utils/guid';
|
||||
import { anapiEndpoint } from '../../settings';
|
||||
import { handleResponseError } from '../../utils';
|
||||
import { AuthActions } from '../auth-actions';
|
||||
|
||||
chai.should();
|
||||
|
||||
const anapi_version = 'v1';
|
||||
|
||||
export class AnapiSearchActions {
|
||||
private api;
|
||||
private static instance: AnapiSearchActions;
|
||||
|
||||
static async getInstance(): Promise<AnapiSearchActions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new AnapiSearchActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
private constructor(exToken: string) {
|
||||
this.api = SearchApiFp({
|
||||
apiKey: `Bearer ${exToken}`
|
||||
});
|
||||
}
|
||||
|
||||
searchPayments(
|
||||
partyID: string,
|
||||
fromTime: Moment,
|
||||
toTime: Moment,
|
||||
limit: number,
|
||||
shopID?: string,
|
||||
paymentStatus?: string,
|
||||
paymentFlow?: string,
|
||||
paymentMethod?: string,
|
||||
paymentTerminalProvider?: string,
|
||||
invoiceID?: string,
|
||||
paymentID?: string,
|
||||
payerEmail?: string,
|
||||
payerIP?: string,
|
||||
payerFingerprint?: string,
|
||||
customerID?: string,
|
||||
first6?: string,
|
||||
last4?: string,
|
||||
rrn?: string,
|
||||
approvalCode?: string,
|
||||
bankCardTokenProvider?: string,
|
||||
bankCardPaymentSystem?: string,
|
||||
paymentAmountTo?: number,
|
||||
paymentAmountFrom?: number,
|
||||
excludedShops?: Array<string>,
|
||||
continuationToken?: string
|
||||
): Promise<InlineResponse2001> {
|
||||
const xRequestID = guid();
|
||||
const xRequestDeadline = undefined;
|
||||
const shopIDs = undefined;
|
||||
const paymentInstitutionRealm = undefined;
|
||||
const invoiceIDs = undefined;
|
||||
const externalID = undefined;
|
||||
return this.api
|
||||
.searchPayments(
|
||||
xRequestID,
|
||||
partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
xRequestDeadline,
|
||||
shopID,
|
||||
shopIDs,
|
||||
paymentInstitutionRealm,
|
||||
invoiceIDs,
|
||||
paymentStatus,
|
||||
paymentFlow,
|
||||
paymentMethod,
|
||||
paymentTerminalProvider,
|
||||
invoiceID,
|
||||
paymentID,
|
||||
externalID,
|
||||
payerEmail,
|
||||
payerIP,
|
||||
payerFingerprint,
|
||||
customerID,
|
||||
first6,
|
||||
last4,
|
||||
rrn,
|
||||
approvalCode,
|
||||
bankCardTokenProvider,
|
||||
bankCardPaymentSystem,
|
||||
paymentAmountFrom,
|
||||
paymentAmountTo,
|
||||
excludedShops,
|
||||
continuationToken
|
||||
)(undefined, `${anapiEndpoint}/${anapi_version}`)
|
||||
.catch(ex => handleResponseError(ex, xRequestID));
|
||||
}
|
||||
|
||||
searchInvoices(
|
||||
partyID: string,
|
||||
fromTime: Moment,
|
||||
toTime: Moment,
|
||||
limit: number,
|
||||
shopID?: string,
|
||||
invoiceStatus?: string,
|
||||
invoiceID?: string,
|
||||
invoiceAmountFrom?: number,
|
||||
invoiceAmountTo?: number,
|
||||
excludedShops?: Array<string>,
|
||||
continuationToken?: string
|
||||
): Promise<InlineResponse200> {
|
||||
const xRequestID = guid();
|
||||
const xRequestDeadline = undefined;
|
||||
const shopIDs = undefined;
|
||||
const paymentInstitutionRealm = undefined;
|
||||
const invoiceIDs = undefined;
|
||||
const externalID = undefined;
|
||||
return this.api
|
||||
.searchInvoices(
|
||||
xRequestID,
|
||||
partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
xRequestDeadline,
|
||||
shopID,
|
||||
shopIDs,
|
||||
paymentInstitutionRealm,
|
||||
invoiceIDs,
|
||||
invoiceStatus,
|
||||
invoiceID,
|
||||
externalID,
|
||||
invoiceAmountFrom,
|
||||
invoiceAmountTo,
|
||||
excludedShops,
|
||||
continuationToken
|
||||
)(undefined, `${anapiEndpoint}/${anapi_version}`)
|
||||
.catch(ex => handleResponseError(ex, xRequestID));
|
||||
}
|
||||
|
||||
searchRefunds(
|
||||
partyID: string,
|
||||
fromTime: Moment,
|
||||
toTime: Moment,
|
||||
limit: number,
|
||||
shopID?: string,
|
||||
offset?: number,
|
||||
invoiceID?: string,
|
||||
paymentID?: string,
|
||||
refundID?: string,
|
||||
refundStatus?: string,
|
||||
excludedShops?: Array<string>,
|
||||
continuationToken?: string
|
||||
): Promise<InlineResponse2003> {
|
||||
const xRequestID = guid();
|
||||
const xRequestDeadline = undefined;
|
||||
const shopIDs = undefined;
|
||||
const paymentInstitutionRealm = undefined;
|
||||
const invoiceIDs = undefined;
|
||||
const externalID = undefined;
|
||||
return this.api
|
||||
.searchRefunds(
|
||||
xRequestID,
|
||||
partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
xRequestDeadline,
|
||||
shopID,
|
||||
shopIDs,
|
||||
paymentInstitutionRealm,
|
||||
offset,
|
||||
invoiceIDs,
|
||||
invoiceID,
|
||||
paymentID,
|
||||
refundID,
|
||||
externalID,
|
||||
refundStatus,
|
||||
excludedShops,
|
||||
continuationToken
|
||||
)(undefined, `${anapiEndpoint}/${anapi_version}`)
|
||||
.catch(ex => handleResponseError(ex, xRequestID));
|
||||
}
|
||||
|
||||
searchPayouts(
|
||||
partyID: string,
|
||||
fromTime: Moment,
|
||||
toTime: Moment,
|
||||
limit: number,
|
||||
shopID?: string,
|
||||
offset?: number,
|
||||
payoutID?: string,
|
||||
payoutToolType?: string,
|
||||
excludedShops?: Array<string>,
|
||||
continuationToken?: string
|
||||
): Promise<InlineResponse2002> {
|
||||
const xRequestID = guid();
|
||||
const xRequestDeadline = undefined;
|
||||
const shopIDs = undefined;
|
||||
const paymentInstitutionRealm = undefined;
|
||||
const invoiceIDs = undefined;
|
||||
const externalID = undefined;
|
||||
return this.api
|
||||
.searchPayouts(
|
||||
xRequestID,
|
||||
partyID,
|
||||
fromTime,
|
||||
toTime,
|
||||
limit,
|
||||
xRequestDeadline,
|
||||
shopID,
|
||||
shopIDs,
|
||||
paymentInstitutionRealm,
|
||||
offset,
|
||||
payoutID,
|
||||
payoutToolType,
|
||||
excludedShops,
|
||||
continuationToken
|
||||
)(undefined, `${anapiEndpoint}/${anapi_version}`)
|
||||
.catch(ex => handleResponseError(ex, xRequestID));
|
||||
}
|
||||
}
|
61
actions/auth-actions.ts
Normal file
61
actions/auth-actions.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { getAccessToken } from '../api';
|
||||
import { externalLogin, externalPassword, internalLogin, internalPassword } from '../settings';
|
||||
|
||||
export class AuthActions {
|
||||
private externalAccessToken: string;
|
||||
private internalAccessToken: string;
|
||||
|
||||
private static instance: AuthActions;
|
||||
|
||||
getExternalAccessToken(): Promise<string> {
|
||||
return this.externalAccessToken
|
||||
? Promise.resolve(this.externalAccessToken)
|
||||
: this.createExternalAccessToken();
|
||||
}
|
||||
|
||||
getInternalAccessToken(): Promise<string> {
|
||||
return this.internalAccessToken
|
||||
? Promise.resolve(this.internalAccessToken)
|
||||
: this.createInternalAccessToken();
|
||||
}
|
||||
|
||||
private createExternalAccessToken(): Promise<string> {
|
||||
return AuthActions.authExternal().then(externalAccessToken => {
|
||||
this.externalAccessToken = externalAccessToken;
|
||||
return externalAccessToken;
|
||||
});
|
||||
}
|
||||
|
||||
private createInternalAccessToken(): Promise<string> {
|
||||
return AuthActions.authInternal().then(internalAccessToken => {
|
||||
this.internalAccessToken = internalAccessToken;
|
||||
return internalAccessToken;
|
||||
});
|
||||
}
|
||||
|
||||
static authExternal(clientID?: string): Promise<string> {
|
||||
return getAccessToken(
|
||||
'external',
|
||||
externalLogin,
|
||||
externalPassword,
|
||||
clientID ? clientID : 'common-api'
|
||||
);
|
||||
}
|
||||
|
||||
static authInternal(clientID?: string): Promise<string> {
|
||||
return getAccessToken(
|
||||
'internal',
|
||||
internalLogin,
|
||||
internalPassword,
|
||||
clientID ? clientID : 'private-api'
|
||||
);
|
||||
}
|
||||
|
||||
static getInstance() {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
this.instance = new AuthActions();
|
||||
return this.instance;
|
||||
}
|
||||
}
|
1
actions/binapi/index.ts
Normal file
1
actions/binapi/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './lookup-actions';
|
44
actions/binapi/lookup-actions.ts
Normal file
44
actions/binapi/lookup-actions.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import * as chai from 'chai';
|
||||
import { CardInfo, CardNumber, SearchApiFp } from '../../api/binapi/codegen';
|
||||
import guid from '../../utils/guid';
|
||||
import { binapiEndpoint } from '../../settings';
|
||||
import { handleResponseError } from '../../utils';
|
||||
import { AuthActions } from '../auth-actions';
|
||||
|
||||
chai.should();
|
||||
|
||||
const binapi_version = 'v1';
|
||||
|
||||
export class BinapiLookupActions {
|
||||
private api;
|
||||
private static instance: BinapiLookupActions;
|
||||
|
||||
static async getInstance(): Promise<BinapiLookupActions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new BinapiLookupActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor(exToken: string) {
|
||||
this.api = SearchApiFp({
|
||||
apiKey: `Bearer ${exToken}`
|
||||
});
|
||||
}
|
||||
|
||||
lookupCardInfo(cardNumber?: string): Promise<CardInfo> {
|
||||
const xRequestID = guid();
|
||||
const xRequestDeadline = undefined;
|
||||
const cardData: CardNumber = {
|
||||
cardNumber
|
||||
};
|
||||
return this.api
|
||||
.lookupCardInfo(cardData, xRequestDeadline)(
|
||||
undefined,
|
||||
`${binapiEndpoint}/${binapi_version}`
|
||||
)
|
||||
.catch(ex => handleResponseError(ex, xRequestID));
|
||||
}
|
||||
}
|
126
actions/capi-v2/claims-actions.ts
Normal file
126
actions/capi-v2/claims-actions.ts
Normal file
@ -0,0 +1,126 @@
|
||||
import * as chai from 'chai';
|
||||
import {
|
||||
createWalletPayoutToolClaimChangeset,
|
||||
createPayoutToolClaimChangeset,
|
||||
liveShopClaimChangeset,
|
||||
testShopClaimChangeset
|
||||
} from '../../api/capi-v2';
|
||||
import { shopPayoutScheduleChange } from '../../api/capi-v2/params/claim-params/default-claim-params';
|
||||
import { Claim, ClaimsApiFp } from '../../api/capi-v2/codegen';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
import { AuthActions } from '../auth-actions';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class ClaimsActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
private static instance: ClaimsActions;
|
||||
|
||||
static async getInstance() {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new ClaimsActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = ClaimsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
createClaimForTestShop(testShopID?: string): Promise<Claim> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createClaim, testShopClaimChangeset(testShopID))
|
||||
.then(claim => {
|
||||
claim.should.to.deep.include({
|
||||
revision: 2,
|
||||
status: 'ClaimAccepted'
|
||||
});
|
||||
claim.should.to.have.property('id').to.be.a('number');
|
||||
return claim;
|
||||
});
|
||||
}
|
||||
|
||||
createClaimForLiveShop(liveShopID?: string): Promise<Claim> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createClaim, liveShopClaimChangeset(liveShopID))
|
||||
.then(claim => {
|
||||
claim.should.to.deep.include({
|
||||
revision: 1,
|
||||
status: 'ClaimPending'
|
||||
});
|
||||
claim.should.to.have.property('id').to.be.a('number');
|
||||
return claim;
|
||||
});
|
||||
}
|
||||
|
||||
createWalletPayoutToolClaimForLiveShop(
|
||||
liveContractID: string,
|
||||
walletID: string
|
||||
): Promise<Claim> {
|
||||
return this.dispatcher
|
||||
.callMethod(
|
||||
this.api.createClaim,
|
||||
createWalletPayoutToolClaimChangeset(liveContractID, walletID)
|
||||
)
|
||||
.then(claim => {
|
||||
claim.should.to.deep.include({
|
||||
revision: 1,
|
||||
status: 'ClaimPending'
|
||||
});
|
||||
claim.should.to.have.property('id').to.be.a('number');
|
||||
return claim;
|
||||
});
|
||||
}
|
||||
|
||||
createPayoutToolClaimForLiveShop(liveContractID: string): Promise<Claim> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createClaim, createPayoutToolClaimChangeset(liveContractID))
|
||||
.then(claim => {
|
||||
claim.should.to.deep.include({
|
||||
revision: 1,
|
||||
status: 'ClaimPending'
|
||||
});
|
||||
claim.should.to.have.property('id').to.be.a('number');
|
||||
return claim;
|
||||
});
|
||||
}
|
||||
|
||||
createClaimForLiveShopWithSchedule(liveShopID?: string, scheduleID?: number): Promise<Claim> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createClaim, [shopPayoutScheduleChange(liveShopID, scheduleID)])
|
||||
.then(claim => {
|
||||
claim.should.to.deep.include({
|
||||
revision: 1,
|
||||
status: 'ClaimPending'
|
||||
});
|
||||
claim.should.to.have.property('id').to.be.a('number');
|
||||
return claim;
|
||||
});
|
||||
}
|
||||
|
||||
getPendingClaimByID(claimID: number): Promise<Claim> {
|
||||
return this.dispatcher.callMethod(this.api.getClaimByID, claimID).then(claim => {
|
||||
claim.should.to.deep.include({
|
||||
id: claimID,
|
||||
status: 'ClaimPending'
|
||||
});
|
||||
return claim;
|
||||
});
|
||||
}
|
||||
|
||||
getAcceptedClaimByID(claimID: number): Promise<Claim> {
|
||||
return this.dispatcher.callMethod(this.api.getClaimByID, claimID).then(claim => {
|
||||
claim.should.to.deep.include({
|
||||
id: claimID,
|
||||
status: 'ClaimAccepted'
|
||||
});
|
||||
return claim;
|
||||
});
|
||||
}
|
||||
}
|
7
actions/capi-v2/index.ts
Normal file
7
actions/capi-v2/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './invoices-actions';
|
||||
export * from './tokens-actions';
|
||||
export * from './payments-actions';
|
||||
export * from './parties-actions';
|
||||
export * from './claims-actions';
|
||||
export * from './shops-actions';
|
||||
export * from './invoice-event-actions';
|
75
actions/capi-v2/invoice-event-actions/conditions.ts
Normal file
75
actions/capi-v2/invoice-event-actions/conditions.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import {
|
||||
InvoiceChange,
|
||||
InvoiceStatus,
|
||||
InvoiceStatusChanged,
|
||||
PaymentStatus,
|
||||
PaymentStatusChanged,
|
||||
RefundStatus,
|
||||
RefundStatusChanged
|
||||
} from '../../../api/capi-v2/codegen';
|
||||
import InvoiceChangeType = InvoiceChange.ChangeTypeEnum;
|
||||
import InvoiceStatusType = InvoiceStatus.StatusEnum;
|
||||
import PaymentStatusType = PaymentStatus.StatusEnum;
|
||||
import RefundStatusType = RefundStatus.StatusEnum;
|
||||
|
||||
export type ChangeInvoiceCondition = (change: InvoiceChange) => boolean;
|
||||
|
||||
export function isInvoicePaid(): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.InvoiceStatusChanged &&
|
||||
(change as InvoiceStatusChanged).status === InvoiceStatusType.Paid;
|
||||
}
|
||||
|
||||
export function isInvoiceUnpaid(): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.InvoiceStatusChanged &&
|
||||
(change as InvoiceStatusChanged).status === InvoiceStatusType.Unpaid;
|
||||
}
|
||||
|
||||
export function isInvoiceInteracted(): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.PaymentInteractionRequested;
|
||||
}
|
||||
|
||||
export function isPaymentCaptured(paymentID: string): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.PaymentStatusChanged &&
|
||||
(change as PaymentStatusChanged).paymentID === paymentID &&
|
||||
(change as PaymentStatusChanged).status === PaymentStatusType.Captured;
|
||||
}
|
||||
|
||||
export function isPaymentFailed(paymentID: string): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.PaymentStatusChanged &&
|
||||
(change as PaymentStatusChanged).paymentID === paymentID &&
|
||||
(change as PaymentStatusChanged).status === PaymentStatusType.Failed;
|
||||
}
|
||||
|
||||
export function isPaymentPending(paymentID: string): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.PaymentStatusChanged &&
|
||||
(change as PaymentStatusChanged).paymentID === paymentID &&
|
||||
(change as PaymentStatusChanged).status === PaymentStatusType.Pending;
|
||||
}
|
||||
|
||||
export function isPaymentProcessed(paymentID: string): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.PaymentStatusChanged &&
|
||||
(change as PaymentStatusChanged).paymentID === paymentID &&
|
||||
(change as PaymentStatusChanged).status === PaymentStatusType.Processed;
|
||||
}
|
||||
|
||||
export function isPaymentRefunded(paymentID: string): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.PaymentStatusChanged &&
|
||||
(change as PaymentStatusChanged).paymentID === paymentID &&
|
||||
(change as PaymentStatusChanged).status === PaymentStatusType.Refunded;
|
||||
}
|
||||
|
||||
export function isRefundSucceeded(paymentID: string, refundID: string): ChangeInvoiceCondition {
|
||||
return (change: InvoiceChange) =>
|
||||
change.changeType === InvoiceChangeType.RefundStatusChanged &&
|
||||
(change as RefundStatusChanged).paymentID === paymentID &&
|
||||
(change as RefundStatusChanged).refundID === refundID &&
|
||||
(change as RefundStatusChanged).status === RefundStatusType.Succeeded;
|
||||
}
|
2
actions/capi-v2/invoice-event-actions/index.ts
Normal file
2
actions/capi-v2/invoice-event-actions/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './invoice-event-actions';
|
||||
export * from './conditions';
|
@ -0,0 +1,35 @@
|
||||
import { InvoiceEvent, InvoicesApiFp } from '../../../api/capi-v2/codegen';
|
||||
import { CAPIDispatcher } from '../../../utils/codegen-utils';
|
||||
import { EventActions } from '../../event-actions';
|
||||
import { AuthActions } from '../../auth-actions';
|
||||
|
||||
export class InvoicesEventActions extends EventActions {
|
||||
private static instance: InvoicesEventActions;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
|
||||
static async getInstance(): Promise<InvoicesEventActions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new InvoicesEventActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor(accessToken: string) {
|
||||
super();
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = InvoicesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async getEvents(invoiceID: string): Promise<InvoiceEvent[]> {
|
||||
return await this.dispatcher.callMethod(
|
||||
this.api.getInvoiceEvents,
|
||||
invoiceID,
|
||||
1000,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
}
|
99
actions/capi-v2/invoice-templates-actions.ts
Normal file
99
actions/capi-v2/invoice-templates-actions.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import {
|
||||
InvoiceAndToken,
|
||||
InvoiceTemplate,
|
||||
InvoiceTemplateAndToken,
|
||||
InvoiceTemplateCreateParams,
|
||||
InvoiceTemplatesApiFp,
|
||||
PaymentMethod
|
||||
} from '../../api/capi-v2/codegen';
|
||||
import {
|
||||
assertSimpleInvoiceTemplate,
|
||||
assertSimpleInvoiceWithTemplate,
|
||||
simpleInvoiceTemplateParams
|
||||
} from '../../api/capi-v2/params/invoice-template-params/invoice-template-params';
|
||||
import { invoiceParamsWithTemplate } from '../../api/capi-v2/params';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
|
||||
export class InvoiceTemplatesActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = InvoiceTemplatesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
createSimpleInvoiceTemplate(shopID: string): Promise<InvoiceTemplateAndToken> {
|
||||
let templateParams: InvoiceTemplateCreateParams = simpleInvoiceTemplateParams(shopID);
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createInvoiceTemplate, templateParams)
|
||||
.then(invoiceTemplateAndToken => {
|
||||
invoiceTemplateAndToken.should.to.have.property('invoiceTemplate');
|
||||
invoiceTemplateAndToken.should.to.have.property('invoiceTemplateAccessToken');
|
||||
const invoiceTemplate = invoiceTemplateAndToken.invoiceTemplate;
|
||||
assertSimpleInvoiceTemplate(invoiceTemplate, shopID);
|
||||
return invoiceTemplateAndToken;
|
||||
});
|
||||
}
|
||||
|
||||
createInvoiceWithTemplate(invoiceTemplateID: string, shopID: string): Promise<InvoiceAndToken> {
|
||||
return this.dispatcher
|
||||
.callMethod(
|
||||
this.api.createInvoiceWithTemplate,
|
||||
invoiceTemplateID,
|
||||
invoiceParamsWithTemplate()
|
||||
)
|
||||
.then(invoiceAndToken => {
|
||||
invoiceAndToken.should.to.have.property('invoice');
|
||||
invoiceAndToken.should.to.have.property('invoiceAccessToken');
|
||||
const invoice = invoiceAndToken.invoice;
|
||||
assertSimpleInvoiceWithTemplate(
|
||||
invoice,
|
||||
invoiceParamsWithTemplate().amount,
|
||||
shopID
|
||||
);
|
||||
return invoiceAndToken;
|
||||
});
|
||||
}
|
||||
|
||||
getInvoiceTemplateById(invoiceTemplateID: string, shopID: string): Promise<InvoiceTemplate> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.getInvoiceTemplateByID, invoiceTemplateID)
|
||||
.then(invoiceTemplate => {
|
||||
assertSimpleInvoiceTemplate(invoiceTemplate, shopID);
|
||||
return invoiceTemplate;
|
||||
});
|
||||
}
|
||||
|
||||
updateInvoiceTemplate(
|
||||
invoiceTemplateCreateParams: InvoiceTemplateCreateParams,
|
||||
invoiceTemplateID: string,
|
||||
shopID: string,
|
||||
assertParams?: {}
|
||||
): Promise<InvoiceTemplate> {
|
||||
return this.dispatcher
|
||||
.callMethod(
|
||||
this.api.updateInvoiceTemplate,
|
||||
invoiceTemplateID,
|
||||
invoiceTemplateCreateParams
|
||||
)
|
||||
.then(invoiceTemplate => {
|
||||
assertSimpleInvoiceTemplate(invoiceTemplate, shopID, assertParams);
|
||||
return invoiceTemplate;
|
||||
});
|
||||
}
|
||||
|
||||
deleteInvoiceTemplate(invoiceTemplateID: string): Promise<void> {
|
||||
return this.dispatcher.callMethod(this.api.deleteInvoiceTemplate, invoiceTemplateID);
|
||||
}
|
||||
|
||||
getInvoicePaymentMethodsByTemplateID(invoiceTemplateID: string): Promise<PaymentMethod[]> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.getInvoicePaymentMethodsByTemplateID, invoiceTemplateID)
|
||||
.then(paymentMethods => {
|
||||
return paymentMethods;
|
||||
});
|
||||
}
|
||||
}
|
137
actions/capi-v2/invoices-actions.ts
Normal file
137
actions/capi-v2/invoices-actions.ts
Normal file
@ -0,0 +1,137 @@
|
||||
import * as chai from 'chai';
|
||||
import * as moment from 'moment';
|
||||
import {
|
||||
AccessToken,
|
||||
Invoice,
|
||||
InvoiceAndToken,
|
||||
InvoiceParams,
|
||||
InvoicesApiFp,
|
||||
LogicError,
|
||||
PaymentMethod,
|
||||
Reason
|
||||
} from '../../api/capi-v2/codegen';
|
||||
import { assertSimpleInvoice, simpleInvoiceParams } from '../../api/capi-v2/params';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class InvoicesActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = InvoicesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
createSimpleInvoice(
|
||||
shopID: string = 'TEST',
|
||||
amount: number = 10000,
|
||||
params?: {}
|
||||
): Promise<InvoiceAndToken> {
|
||||
let invoiceParams = simpleInvoiceParams(shopID, params);
|
||||
invoiceParams = {
|
||||
...invoiceParams,
|
||||
amount,
|
||||
cart: [
|
||||
{
|
||||
...invoiceParams.cart[0],
|
||||
price: amount
|
||||
}
|
||||
]
|
||||
};
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createInvoice, invoiceParams)
|
||||
.then(invoiceAndToken => {
|
||||
invoiceAndToken.should.to.have.property('invoice');
|
||||
const invoice = invoiceAndToken.invoice;
|
||||
assertSimpleInvoice(invoice, amount, shopID);
|
||||
invoice.should.to.have.property('dueDate').to.eq(invoiceParams.dueDate);
|
||||
invoiceAndToken.should.to.have.nested
|
||||
.property('invoiceAccessToken.payload')
|
||||
.to.be.a('string');
|
||||
return invoiceAndToken;
|
||||
});
|
||||
}
|
||||
|
||||
getCreateInvoiceError(shopID: string, params?: {}): Promise<LogicError> {
|
||||
let invoiceParams: InvoiceParams = simpleInvoiceParams(shopID, params);
|
||||
return this.dispatcher.callMethod(this.api.createInvoice, invoiceParams).catch(error => {
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
createInvoiceWithoutCart(shopID: string = 'TEST'): Promise<LogicError> {
|
||||
let invoiceParams: InvoiceParams = simpleInvoiceParams(shopID, { cart: [] });
|
||||
return this.dispatcher.callMethod(this.api.createInvoice, invoiceParams).catch(error => {
|
||||
error.message.should.to.include({
|
||||
code: 'invalidInvoiceCart',
|
||||
message: 'Wrong size. Path to item: cart'
|
||||
});
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
createInvoiceWithWrongShopID(shopID: string = 'TEST'): Promise<LogicError> {
|
||||
let invoiceParams: InvoiceParams = simpleInvoiceParams(shopID);
|
||||
return this.dispatcher.callMethod(this.api.createInvoice, invoiceParams).catch(error => {
|
||||
error.message.should.to.include({
|
||||
code: 'invalidShopID',
|
||||
message: 'Shop not found'
|
||||
});
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
createInvoiceWithWrongDueDate(shopID: string = 'TEST'): Promise<LogicError> {
|
||||
let invoiceParams: InvoiceParams = simpleInvoiceParams(shopID, {
|
||||
dueDate: moment()
|
||||
.subtract(15, 'days')
|
||||
.utc()
|
||||
.format() as any
|
||||
});
|
||||
return this.dispatcher.callMethod(this.api.createInvoice, invoiceParams).catch(error => {
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
createInvoiceAccessToken(invoiceID: string): Promise<AccessToken> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createInvoiceAccessToken, invoiceID)
|
||||
.then(response => {
|
||||
response.should.to.have.property('payload').to.be.a('string');
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
fulfillInvoice(invoiceID: string): Promise<void> {
|
||||
return this.dispatcher.callMethod(this.api.fulfillInvoice, invoiceID, {
|
||||
reason: 'test reason'
|
||||
});
|
||||
}
|
||||
|
||||
rescindInvoice(invoiceID: string, reason: Reason): Promise<Response> {
|
||||
return this.dispatcher.callMethod(this.api.rescindInvoice, invoiceID, reason);
|
||||
}
|
||||
|
||||
getInvoiceById(invoiceID: string): Promise<Invoice> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.getInvoiceByID, invoiceID)
|
||||
.then(invoice => invoice);
|
||||
}
|
||||
|
||||
getInvoicePaymentMethods(invoiceID: string): Promise<PaymentMethod[]> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.getInvoicePaymentMethods, invoiceID)
|
||||
.then(methods => {
|
||||
methods.should.to.deep.members([
|
||||
{ method: 'BankCard', paymentSystems: ['mastercard', 'nspkmir', 'visa'] },
|
||||
{ method: 'DigitalWallet', providers: ['qiwi'] },
|
||||
{ method: 'PaymentTerminal', providers: ['euroset'] }
|
||||
]);
|
||||
return methods;
|
||||
});
|
||||
}
|
||||
}
|
12
actions/capi-v2/params/payout-params.ts
Normal file
12
actions/capi-v2/params/payout-params.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { PayoutParams } from '../../../api/capi-v2/codegen';
|
||||
import guid from '../../../utils/guid';
|
||||
|
||||
export function getPayoutParams(shopID: string, payoutToolID: string): PayoutParams {
|
||||
return {
|
||||
id: guid(),
|
||||
shopID,
|
||||
payoutToolID,
|
||||
amount: 100,
|
||||
currency: 'RUB'
|
||||
};
|
||||
}
|
43
actions/capi-v2/parties-actions.ts
Normal file
43
actions/capi-v2/parties-actions.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import * as chai from 'chai';
|
||||
import { PartiesApiFp, Party } from '../../api/capi-v2/codegen';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
import { AuthActions } from '../auth-actions';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class PartiesActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
private static instance: PartiesActions;
|
||||
|
||||
static async getInstance(): Promise<PartiesActions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new PartiesActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({
|
||||
headers: {
|
||||
origin: 'https://dashboard.rbk.money'
|
||||
}
|
||||
});
|
||||
this.api = PartiesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
getActiveParty(): Promise<Party> {
|
||||
return this.dispatcher.callMethod(this.api.getMyParty).then(party => {
|
||||
party.should.to.deep.include({
|
||||
isBlocked: false,
|
||||
isSuspended: false
|
||||
});
|
||||
party.should.to.have.property('id').to.be.a('string');
|
||||
return party;
|
||||
});
|
||||
}
|
||||
}
|
211
actions/capi-v2/payments-actions.ts
Normal file
211
actions/capi-v2/payments-actions.ts
Normal file
@ -0,0 +1,211 @@
|
||||
import * as chai from 'chai';
|
||||
import {
|
||||
captureParams,
|
||||
Payment,
|
||||
PaymentFlow,
|
||||
paymentParams,
|
||||
PaymentRecurrentParent,
|
||||
PaymentResource,
|
||||
paymentResourcePayer,
|
||||
PaymentsApiFp,
|
||||
recurrentPayer,
|
||||
LogicError,
|
||||
Refund,
|
||||
RefundParams,
|
||||
SearchApiFp
|
||||
} from '../../api/capi-v2';
|
||||
import { assertPayment } from '../../api/capi-v2/params';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
import delay from '../../utils/delay';
|
||||
import moment = require('moment');
|
||||
|
||||
chai.should();
|
||||
|
||||
export class PaymentsActions {
|
||||
private api;
|
||||
private searchApi;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = PaymentsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
this.searchApi = SearchApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
createInstantPayment(
|
||||
invoiceID: string,
|
||||
paymentResource: PaymentResource,
|
||||
amount = 10000,
|
||||
externalID?: string,
|
||||
metadata?: object
|
||||
): Promise<Payment> {
|
||||
const payer = paymentResourcePayer(paymentResource);
|
||||
let params = paymentParams(
|
||||
payer,
|
||||
PaymentFlow.TypeEnum.PaymentFlowInstant,
|
||||
false,
|
||||
undefined,
|
||||
externalID,
|
||||
metadata
|
||||
);
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPayment, invoiceID, params)
|
||||
.then(payment => {
|
||||
assertPayment(
|
||||
payment,
|
||||
amount,
|
||||
PaymentFlow.TypeEnum.PaymentFlowInstant,
|
||||
undefined,
|
||||
metadata
|
||||
);
|
||||
return payment;
|
||||
});
|
||||
}
|
||||
|
||||
createHoldPayment(
|
||||
invoiceID: string,
|
||||
paymentResource: PaymentResource,
|
||||
holdType?: string,
|
||||
amount = 10000
|
||||
): Promise<Payment> {
|
||||
const payer = paymentResourcePayer(paymentResource);
|
||||
const params = paymentParams(payer, PaymentFlow.TypeEnum.PaymentFlowHold, false, holdType);
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPayment, invoiceID, params)
|
||||
.then(payment => {
|
||||
assertPayment(payment, amount, PaymentFlow.TypeEnum.PaymentFlowHold, holdType);
|
||||
return payment;
|
||||
});
|
||||
}
|
||||
|
||||
createFirstRecurrentPayment(
|
||||
invoiceID: string,
|
||||
paymentResource: PaymentResource
|
||||
): Promise<Payment> {
|
||||
const payer = paymentResourcePayer(paymentResource);
|
||||
const params = paymentParams(payer, PaymentFlow.TypeEnum.PaymentFlowInstant, true);
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPayment, invoiceID, params)
|
||||
.then(payment => {
|
||||
assertPayment(payment, 10000, PaymentFlow.TypeEnum.PaymentFlowInstant);
|
||||
return payment;
|
||||
});
|
||||
}
|
||||
|
||||
createRecurrentPayment(invoiceID: string, parent: PaymentRecurrentParent): Promise<Payment> {
|
||||
const payer = recurrentPayer(parent);
|
||||
const params = paymentParams(payer, PaymentFlow.TypeEnum.PaymentFlowInstant, true);
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPayment, invoiceID, params)
|
||||
.then(payment => {
|
||||
assertPayment(payment, 10000, PaymentFlow.TypeEnum.PaymentFlowInstant);
|
||||
return payment;
|
||||
});
|
||||
}
|
||||
|
||||
createRefund(
|
||||
invoiceID: string,
|
||||
paymentID: string,
|
||||
refundParams: RefundParams
|
||||
): Promise<Refund> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createRefund, invoiceID, paymentID, refundParams)
|
||||
.then(refund => {
|
||||
refund.should.to.have.property('id').to.be.a('string');
|
||||
refund.should.to.have.property('createdAt').to.be.a('string');
|
||||
refund.should.to.have.property('amount').to.be.a('number');
|
||||
refund.should.to.have.property('currency').to.be.a('string');
|
||||
refund.should.to.have.property('reason').to.be.a('string');
|
||||
refund.should.to.have.property('status').to.equal('pending');
|
||||
return refund;
|
||||
});
|
||||
}
|
||||
|
||||
createRefundError(
|
||||
invoiceID: string,
|
||||
paymentID: string,
|
||||
refundParams: RefundParams
|
||||
): Promise<LogicError> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createRefund, invoiceID, paymentID, refundParams)
|
||||
.catch(error => {
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
getPaymentByID(
|
||||
invoiceID: string,
|
||||
paymentID: string,
|
||||
paymentType: PaymentFlow.TypeEnum
|
||||
): Promise<Payment> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.getPaymentByID, invoiceID, paymentID)
|
||||
.then(payment => {
|
||||
assertPayment(payment, 10000, paymentType);
|
||||
return payment;
|
||||
});
|
||||
}
|
||||
|
||||
capturePayment(invoiceID: string, paymentID: string, amount?: number): Promise<Response> {
|
||||
const params = captureParams(amount);
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.capturePayment, invoiceID, paymentID, params)
|
||||
.then(resp => {
|
||||
return resp;
|
||||
});
|
||||
}
|
||||
|
||||
async searchPayments(shopID: string) {
|
||||
return await this.dispatcher.callMethod(
|
||||
this.searchApi.searchPayments,
|
||||
shopID,
|
||||
moment().add(-1, 'minutes'),
|
||||
moment(),
|
||||
1000,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
async waitPayment(paymentID: string, shopID: string) {
|
||||
const result = await Promise.race([this.pollPayment(paymentID, shopID), delay(25000)]);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
throw new Error(`payments event polling timeout`);
|
||||
}
|
||||
|
||||
private async pollPayment(paymentID: string, shopID: string) {
|
||||
let paymentFound = false;
|
||||
while (!paymentFound) {
|
||||
await delay(2000);
|
||||
const payments = (await this.searchPayments(shopID)).result;
|
||||
const foundPayments = payments.filter(payment => payment.id === paymentID);
|
||||
paymentFound =
|
||||
payments.length > 0 &&
|
||||
foundPayments.length > 0 &&
|
||||
foundPayments[0].status === 'captured';
|
||||
}
|
||||
return paymentFound;
|
||||
}
|
||||
}
|
22
actions/capi-v2/payout-actions.ts
Normal file
22
actions/capi-v2/payout-actions.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
import { Payout, PayoutsApiFp } from '../../api/capi-v2/codegen';
|
||||
import { getPayoutParams } from './params/payout-params';
|
||||
|
||||
export class PayoutActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = PayoutsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
createPayout(shopID: string, payoutToolID: string): Promise<Payout> {
|
||||
const params = getPayoutParams(shopID, payoutToolID);
|
||||
return this.dispatcher.callMethod(this.api.createPayout, params).then(payout => {
|
||||
return payout;
|
||||
});
|
||||
}
|
||||
}
|
36
actions/capi-v2/shops-actions.ts
Normal file
36
actions/capi-v2/shops-actions.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import * as chai from 'chai';
|
||||
import { Shop, ShopsApiFp } from '../../api/capi-v2/codegen';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class ShopsActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = ShopsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
getFirstShop(): Promise<Shop> {
|
||||
return this.dispatcher.callMethod(this.api.getShops).then(shops => {
|
||||
shops.should.to.be.an('array').that.is.not.empty;
|
||||
const shop = shops[0];
|
||||
shop.should.to.deep.include({
|
||||
isBlocked: false,
|
||||
isSuspended: false
|
||||
});
|
||||
return shop;
|
||||
});
|
||||
}
|
||||
|
||||
getShopByID(shopID: string = 'TEST'): Promise<Shop> {
|
||||
return this.dispatcher.callMethod(this.api.getShopByID, shopID).then(shop => {
|
||||
shop.should.to.have.property('id').to.be.a('string');
|
||||
return shop;
|
||||
});
|
||||
}
|
||||
}
|
149
actions/capi-v2/tokens-actions.ts
Normal file
149
actions/capi-v2/tokens-actions.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import * as chai from 'chai';
|
||||
import {
|
||||
insufficientFundsVisaTool,
|
||||
cryptoPaymentTool,
|
||||
qiwiPaymentTool,
|
||||
saneVisaPaymentTool,
|
||||
CryptoWalletData
|
||||
} from '../../api/capi-v2';
|
||||
import {
|
||||
ClientInfo,
|
||||
PaymentResource,
|
||||
PaymentTerminalDetails,
|
||||
PaymentToolDetails,
|
||||
PaymentToolDetailsBankCard,
|
||||
PaymentToolDetailsDigitalWallet,
|
||||
TokensApiFp,
|
||||
LogicError,
|
||||
PaymentResourceParams
|
||||
} from '../../api/capi-v2/codegen';
|
||||
import { secureVisaPaymentTool } from '../../api/capi-v2/params';
|
||||
import { secureEmptyCVVVisaPaymentTool } from '../../api/capi-v2/params';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
import DigitalWalletDetailsType = PaymentToolDetailsDigitalWallet.DigitalWalletDetailsTypeEnum;
|
||||
|
||||
chai.should();
|
||||
|
||||
export class TokensActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = TokensApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
createPaymentResource(paymentTool: PaymentResourceParams): Promise<PaymentResource> {
|
||||
return this.dispatcher.callMethod(this.api.createPaymentResource, paymentTool);
|
||||
}
|
||||
|
||||
createPaymentResourceError(paymentTool: PaymentResourceParams): Promise<LogicError> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPaymentResource, paymentTool)
|
||||
.catch(error => {
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
createSaneVisaPaymentResource(): Promise<PaymentResource> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPaymentResource, saneVisaPaymentTool)
|
||||
.then(resource => {
|
||||
this.assertPaymentResource(resource, {
|
||||
cardNumberMask: '424242******4242',
|
||||
last4: '4242',
|
||||
first6: '424242',
|
||||
detailsType: 'PaymentToolDetailsBankCard',
|
||||
paymentSystem: 'visa'
|
||||
} as PaymentToolDetails);
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
|
||||
createInsufficientFundsVisaPaymentResource(): Promise<PaymentResource> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPaymentResource, insufficientFundsVisaTool)
|
||||
.then(resource => {
|
||||
this.assertPaymentResource(resource, {
|
||||
cardNumberMask: '400000******0002',
|
||||
last4: '0002',
|
||||
first6: '400000',
|
||||
detailsType: 'PaymentToolDetailsBankCard',
|
||||
paymentSystem: 'visa'
|
||||
} as PaymentToolDetails);
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
|
||||
createSecureVisaPaymentResource(): Promise<PaymentResource> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPaymentResource, secureVisaPaymentTool)
|
||||
.then(resource => {
|
||||
this.assertPaymentResource(resource, {
|
||||
cardNumberMask: '401288******1881',
|
||||
last4: '1881',
|
||||
first6: '401288',
|
||||
detailsType: 'PaymentToolDetailsBankCard',
|
||||
paymentSystem: 'visa'
|
||||
} as PaymentToolDetails);
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
|
||||
createSecureEmptyCVVVisaPaymentResource(): Promise<PaymentResource> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPaymentResource, secureEmptyCVVVisaPaymentTool)
|
||||
.then(resource => {
|
||||
this.assertPaymentResource(resource, {
|
||||
cardNumberMask: '401288******1881',
|
||||
last4: '1881',
|
||||
first6: '401288',
|
||||
detailsType: 'PaymentToolDetailsBankCard',
|
||||
paymentSystem: 'visa'
|
||||
} as PaymentToolDetails);
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
|
||||
createQIWIPaymentResource(): Promise<PaymentResource> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPaymentResource, qiwiPaymentTool)
|
||||
.then(resource => {
|
||||
this.assertPaymentResource(resource, {
|
||||
detailsType: 'PaymentToolDetailsDigitalWallet',
|
||||
digitalWalletDetailsType: DigitalWalletDetailsType.DigitalWalletDetailsQIWI,
|
||||
phoneNumberMask: '+7*****1111'
|
||||
} as PaymentToolDetails);
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
|
||||
createCryptoPaymentResource(): Promise<PaymentResource> {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createPaymentResource, cryptoPaymentTool)
|
||||
.then(resource => {
|
||||
this.assertPaymentResource(resource, {
|
||||
detailsType: 'PaymentToolDetailsCryptoWallet',
|
||||
cryptoCurrency: 'bitcoinCash'
|
||||
} as PaymentToolDetails);
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
|
||||
private assertPaymentResource(
|
||||
resource: PaymentResource,
|
||||
assertionPaymentToolDetails: PaymentToolDetails
|
||||
) {
|
||||
resource.should.to.have.property('paymentToolToken').to.be.a('string');
|
||||
resource.should.to.have.property('paymentSession').to.be.a('string');
|
||||
resource.should.to.have.property('clientInfo').to.be.a('object');
|
||||
resource.should.to.have.property('paymentToolDetails').to.be.a('object');
|
||||
const clientInfo = resource['clientInfo'] as ClientInfo; // TODO swagger multi inheritance bug
|
||||
clientInfo.should.to.have.property('fingerprint').to.be.a('string');
|
||||
clientInfo.should.to.have.property('ip').to.be.a('string');
|
||||
const paymentToolDetails = resource.paymentToolDetails;
|
||||
paymentToolDetails.should.to.deep.eq(assertionPaymentToolDetails);
|
||||
}
|
||||
}
|
60
actions/capi-v2/webhooks-actions.ts
Normal file
60
actions/capi-v2/webhooks-actions.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import * as chai from 'chai';
|
||||
import { InvoicesTopic, Webhook, WebhooksApiFp, WebhookScope } from '../../api/capi-v2/codegen';
|
||||
import { AuthActions } from '../auth-actions';
|
||||
import { countEvents, getEvents, webhookParams } from '../../api/capi-v2/params';
|
||||
import { CAPIDispatcher } from '../../utils/codegen-utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class WebhooksActions {
|
||||
private api;
|
||||
private dispatcher: CAPIDispatcher;
|
||||
private static instance: WebhooksActions;
|
||||
|
||||
static async getInstance(): Promise<WebhooksActions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new WebhooksActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
private constructor(exToken: string) {
|
||||
this.dispatcher = new CAPIDispatcher({});
|
||||
this.api = WebhooksApiFp({
|
||||
apiKey: `Bearer ${exToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async createWebhook(
|
||||
shopID: string = 'TEST',
|
||||
testId: string,
|
||||
eventTypes: Array<InvoicesTopic.EventTypesEnum>
|
||||
): Promise<Webhook> {
|
||||
return this.dispatcher
|
||||
.callMethod(
|
||||
this.api.createWebhook,
|
||||
webhookParams(
|
||||
{
|
||||
topic: WebhookScope.TopicEnum.InvoicesTopic,
|
||||
shopID: shopID,
|
||||
eventTypes: eventTypes
|
||||
} as InvoicesTopic,
|
||||
testId
|
||||
)
|
||||
)
|
||||
.then(webhook => {
|
||||
webhook.should.to.have.property('active').to.eq(true);
|
||||
return webhook;
|
||||
});
|
||||
}
|
||||
|
||||
countEvents(testId: string): Promise<number> {
|
||||
return countEvents(testId);
|
||||
}
|
||||
|
||||
getEvents(testId: string): Promise<string> {
|
||||
return getEvents(testId);
|
||||
}
|
||||
}
|
60
actions/event-actions.ts
Normal file
60
actions/event-actions.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { ChangeIdentityCondition } from './wapi-v0/wallet/identities-event-actions';
|
||||
import {
|
||||
IdentityChallengeEvent,
|
||||
IdentityChallengeStatusChanged,
|
||||
WithdrawalEvent,
|
||||
WithdrawalStatus
|
||||
} from '../api/wapi-v0/wallet/codegen';
|
||||
import { InvoiceChange, InvoiceEvent } from '../api/capi-v2/codegen';
|
||||
import { ChangeInvoiceCondition } from './capi-v2/invoice-event-actions';
|
||||
import { ChangeWithdrawalCondition } from './wapi-v0/wallet/withdrawals-event-actions';
|
||||
import delay from '../utils/delay';
|
||||
|
||||
type ChangeCondition = ChangeIdentityCondition | ChangeInvoiceCondition | ChangeWithdrawalCondition;
|
||||
type EventStatusChanged = IdentityChallengeStatusChanged | InvoiceChange | WithdrawalStatus;
|
||||
type Event = IdentityChallengeEvent | InvoiceEvent | WithdrawalEvent;
|
||||
|
||||
export abstract class EventActions {
|
||||
protected api;
|
||||
|
||||
protected constructor() {}
|
||||
|
||||
async waitConditions(
|
||||
conditions: ChangeCondition[],
|
||||
...args: any[]
|
||||
): Promise<EventStatusChanged[]> {
|
||||
const result = await Promise.race([this.pollEvents(conditions, ...args), delay(20000)]);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
throw new Error(`event polling timeout`);
|
||||
}
|
||||
|
||||
private async pollEvents(
|
||||
conditions: ChangeCondition[],
|
||||
...args: any[]
|
||||
): Promise<EventStatusChanged[]> {
|
||||
let events = [];
|
||||
let foundChanges;
|
||||
while (!foundChanges || foundChanges.length !== conditions.length) {
|
||||
await delay(1000);
|
||||
events = await this.getEvents(...args);
|
||||
foundChanges = this.findChanges(events, conditions);
|
||||
}
|
||||
return foundChanges;
|
||||
}
|
||||
|
||||
private findChanges(events: Event[], conditions: ChangeCondition[]): EventStatusChanged[] {
|
||||
const result = [];
|
||||
for (const { changes } of events) {
|
||||
for (const condition of conditions) {
|
||||
// @ts-ignore
|
||||
const found = changes.find(change => condition(change));
|
||||
found !== undefined && result.push(found);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
abstract async getEvents(...args: any[]): Promise<Event[]>;
|
||||
}
|
6
actions/index.ts
Normal file
6
actions/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export * from './capi-v2';
|
||||
export * from './papi-v1';
|
||||
export * from './auth-actions';
|
||||
export * from './wapi-v0';
|
||||
export * from './anapi';
|
||||
export * from './binapi';
|
27
actions/papi-v1/claims-actions.ts
Normal file
27
actions/papi-v1/claims-actions.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import * as chai from 'chai';
|
||||
import { ClaimsApiForTests, PapiFactory } from '../../api/papi-v1';
|
||||
import { AuthActions } from '../auth-actions';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class PapiClaimsActions {
|
||||
private api;
|
||||
private static instance: PapiClaimsActions;
|
||||
|
||||
static async getInstance() {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getInternalAccessToken();
|
||||
this.instance = new PapiClaimsActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.api = PapiFactory.getInstance(ClaimsApiForTests.name, accessToken);
|
||||
}
|
||||
|
||||
acceptClaimByID(partyID: string, claimID: number, claimRevision: number): Promise<void> {
|
||||
return this.api.acceptClaimByIDForTests(partyID, claimID, claimRevision);
|
||||
}
|
||||
}
|
2
actions/papi-v1/index.ts
Normal file
2
actions/papi-v1/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './claims-actions';
|
||||
export * from './payouts-actions';
|
52
actions/papi-v1/payouts-actions.ts
Normal file
52
actions/papi-v1/payouts-actions.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import * as chai from 'chai';
|
||||
import { PapiFactory, Payout, PayoutsApiForTests } from '../../api/papi-v1';
|
||||
import { AuthActions } from '../auth-actions';
|
||||
import delay from '../../utils/delay';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class PapiPayoutsActions {
|
||||
private api: PayoutsApiForTests;
|
||||
private static instance: PapiPayoutsActions;
|
||||
|
||||
static async getInstance(): Promise<PapiPayoutsActions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getInternalAccessToken();
|
||||
this.instance = new PapiPayoutsActions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.api = PapiFactory.getInstance(PayoutsApiForTests.name, accessToken);
|
||||
}
|
||||
|
||||
async getPayoutWhenPresent(partyID: string, shopID: string): Promise<Payout> {
|
||||
const payout = await Promise.race([delay(20000), this.pollSearchPayouts(partyID, shopID)]);
|
||||
if (!payout) {
|
||||
throw new Error('Wait searchPayouts result timeout');
|
||||
}
|
||||
return payout;
|
||||
}
|
||||
|
||||
pay(payoutIds: string[]) {
|
||||
return this.api.pay(payoutIds);
|
||||
}
|
||||
|
||||
confirmPayouts(payoutIds: string[]) {
|
||||
return this.api.confirmPayouts(payoutIds);
|
||||
}
|
||||
|
||||
private async pollSearchPayouts(partyID: string, shopID: string): Promise<Payout> {
|
||||
let result;
|
||||
while (!result) {
|
||||
const payouts = await this.api.searchPayoutsForTests();
|
||||
result = payouts.find(
|
||||
({ partyId, shopId }) => partyId === partyID && shopId === shopID
|
||||
);
|
||||
await delay(1000);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
3
actions/wapi-v0/index.ts
Normal file
3
actions/wapi-v0/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './wallet';
|
||||
export * from './payres/payres-actions';
|
||||
export * from './privdoc/privdoc-actions';
|
25
actions/wapi-v0/payres/payres-actions.ts
Normal file
25
actions/wapi-v0/payres/payres-actions.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import * as chai from 'chai';
|
||||
import { PaymentResourcesApiFp } from '../../../api/wapi-v0/payres/codegen';
|
||||
import { getBankCardParams } from '../../../api/wapi-v0/payres/params/payres-params';
|
||||
import { WapiPayresDispatcher } from '../../../utils/codegen-utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class PayresActions {
|
||||
private api;
|
||||
private dispatcher: WapiPayresDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new WapiPayresDispatcher({});
|
||||
this.api = PaymentResourcesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async storeBankCard() {
|
||||
const cardParams = getBankCardParams();
|
||||
const card = await this.dispatcher.callMethod(this.api.storeBankCard, cardParams);
|
||||
card.should.contain.keys('token', 'validUntil');
|
||||
return card;
|
||||
}
|
||||
}
|
39
actions/wapi-v0/privdoc/privdoc-actions.ts
Normal file
39
actions/wapi-v0/privdoc/privdoc-actions.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { WapiPrivdocDispatcher } from '../../../utils/codegen-utils';
|
||||
import { PrivateDocumentsApiFp } from '../../../api/wapi-v0/privdoc/codegen';
|
||||
import {
|
||||
getPassportParams,
|
||||
getRICParams
|
||||
} from '../../../api/wapi-v0/privdoc/params/privdoc-params';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class PrivdocActions {
|
||||
private api;
|
||||
private dispatcher: WapiPrivdocDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new WapiPrivdocDispatcher({});
|
||||
this.api = PrivateDocumentsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async savePassport() {
|
||||
const passport = getPassportParams();
|
||||
const storedPassport = await this.dispatcher.callMethod(
|
||||
this.api.storePrivateDocument,
|
||||
passport
|
||||
);
|
||||
storedPassport.should.contain.key('token');
|
||||
return storedPassport;
|
||||
}
|
||||
|
||||
async saveRIC() {
|
||||
const ric = getRICParams();
|
||||
const createdRIC = await this.dispatcher.callMethod(this.api.storePrivateDocument, ric);
|
||||
createdRIC.should.contain.key('token');
|
||||
return createdRIC;
|
||||
}
|
||||
}
|
116
actions/wapi-v0/wallet/identities-actions.ts
Normal file
116
actions/wapi-v0/wallet/identities-actions.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import * as chai from 'chai';
|
||||
import { IdentitiesApiFp, IdentityChallenge } from '../../../api/wapi-v0/wallet/codegen';
|
||||
import { getSimpleIdentityParams } from '../../../api/wapi-v0/wallet/params/identities-params/simple-identity-params';
|
||||
import { WAPIDispatcher } from '../../../utils/codegen-utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class IdentitiesActions {
|
||||
private api;
|
||||
private dispatcher: WAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new WAPIDispatcher({});
|
||||
this.api = IdentitiesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async createIdentity() {
|
||||
const simpleIdentity = getSimpleIdentityParams();
|
||||
const createdIdentity = await this.dispatcher.callMethod(
|
||||
this.api.createIdentity,
|
||||
simpleIdentity,
|
||||
undefined
|
||||
);
|
||||
createdIdentity.should.contain.keys('class', 'name', 'provider');
|
||||
return createdIdentity;
|
||||
}
|
||||
|
||||
async getIdentity(identityID: string) {
|
||||
const identity = await this.dispatcher.callMethod(
|
||||
this.api.getIdentity,
|
||||
identityID,
|
||||
undefined
|
||||
);
|
||||
identity.should.contain.keys('name', 'provider', 'class');
|
||||
return identity;
|
||||
}
|
||||
|
||||
async listIdentityChallenges(identityID: string) {
|
||||
const challenges = await this.dispatcher.callMethod(
|
||||
this.api.listIdentityChallenges,
|
||||
identityID,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
challenges.should.be.a('array');
|
||||
return challenges;
|
||||
}
|
||||
|
||||
async startIdentityChallenge(identityID: string, challenge: IdentityChallenge) {
|
||||
return await this.dispatcher.callMethod(
|
||||
this.api.startIdentityChallenge,
|
||||
identityID,
|
||||
challenge,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
async getIdentityChallenge(identityID: string, challengeID: string) {
|
||||
const identityChallenge = await this.dispatcher.callMethod(
|
||||
this.api.getIdentityChallenge,
|
||||
identityID,
|
||||
challengeID,
|
||||
undefined
|
||||
);
|
||||
identityChallenge.should.contain.keys('type', 'proofs');
|
||||
return identityChallenge;
|
||||
}
|
||||
|
||||
async listIdentities(
|
||||
limit: number,
|
||||
providerID?: string,
|
||||
classID?: string,
|
||||
levelID?: string,
|
||||
continuationToken?: string
|
||||
) {
|
||||
const identities = await this.dispatcher.callMethod(
|
||||
this.api.listIdentities,
|
||||
limit,
|
||||
providerID,
|
||||
classID,
|
||||
levelID,
|
||||
continuationToken,
|
||||
undefined
|
||||
);
|
||||
identities.should.contain.keys('result');
|
||||
return identities;
|
||||
}
|
||||
|
||||
async pollIdentityChallengeEvents(identityID: string, challengeID: string) {
|
||||
const events = await this.dispatcher.callMethod(
|
||||
this.api.pollIdentityChallengeEvents,
|
||||
identityID,
|
||||
challengeID,
|
||||
1000,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
events.should.property('length').not.equal(0);
|
||||
events[0].should.contain.keys('eventID', 'occuredAt', 'changes');
|
||||
return events;
|
||||
}
|
||||
|
||||
async getIdentityChallengeEvent(identityID: string, challengeID: string, eventID: string) {
|
||||
const event = await this.dispatcher.callMethod(
|
||||
this.api.getIdentityChallengeEvent,
|
||||
identityID,
|
||||
challengeID,
|
||||
eventID,
|
||||
undefined
|
||||
);
|
||||
event.should.contain.keys('changes', 'eventID', 'occuredAt');
|
||||
return event;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import {
|
||||
IdentityChallengeStatus,
|
||||
IdentityChallengeStatusChanged
|
||||
} from '../../../../api/wapi-v0/wallet/codegen';
|
||||
|
||||
import IdentityChallengeStatusType = IdentityChallengeStatus.StatusEnum;
|
||||
|
||||
export type ChangeIdentityCondition = (change: IdentityChallengeStatusChanged) => boolean;
|
||||
|
||||
export function isIdentityChallengeCompleted(): ChangeIdentityCondition {
|
||||
return (change: IdentityChallengeStatusChanged) =>
|
||||
change.status === IdentityChallengeStatusType.Completed;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { WAPIDispatcher } from '../../../../utils/codegen-utils';
|
||||
import { IdentitiesApiFp, IdentityChallengeEvent } from '../../../../api/wapi-v0/wallet/codegen';
|
||||
import { EventActions } from '../../../event-actions';
|
||||
|
||||
export class IdentitiesEventActions extends EventActions {
|
||||
private dispatcher: WAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
super();
|
||||
this.dispatcher = new WAPIDispatcher({});
|
||||
this.api = IdentitiesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async getEvents(...args: any[]): Promise<IdentityChallengeEvent[]> {
|
||||
return await this.dispatcher.callMethod(
|
||||
this.api.pollIdentityChallengeEvents,
|
||||
...args,
|
||||
1000,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
}
|
2
actions/wapi-v0/wallet/identities-event-actions/index.ts
Normal file
2
actions/wapi-v0/wallet/identities-event-actions/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './identities-event-actions';
|
||||
export * from './conditions';
|
4
actions/wapi-v0/wallet/index.ts
Normal file
4
actions/wapi-v0/wallet/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './identities-event-actions';
|
||||
export * from './identities-actions';
|
||||
export * from './providers-actions';
|
||||
export * from './wallets-actions';
|
130
actions/wapi-v0/wallet/providers-actions.ts
Normal file
130
actions/wapi-v0/wallet/providers-actions.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import * as chai from 'chai';
|
||||
import {
|
||||
CurrenciesApiFp,
|
||||
ProvidersApiFp,
|
||||
ResidencesApiFp
|
||||
} from '../../../api/wapi-v0/wallet/codegen';
|
||||
import { WAPIDispatcher } from '../../../utils/codegen-utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class ProvidersActions {
|
||||
private api;
|
||||
private residenceAPI;
|
||||
private currenciesAPI;
|
||||
private dispatcher: WAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new WAPIDispatcher({});
|
||||
this.api = ProvidersApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
this.residenceAPI = ResidencesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
this.currenciesAPI = CurrenciesApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async listProviders(residence?: string) {
|
||||
const providers = await this.dispatcher.callMethod(
|
||||
this.api.listProviders,
|
||||
undefined,
|
||||
residence
|
||||
);
|
||||
providers.should.property('length').not.equal(0);
|
||||
providers[0].should.contain.keys('id', 'name', 'residences');
|
||||
return providers;
|
||||
}
|
||||
|
||||
async getProvider(providerID: string) {
|
||||
const provider = await this.dispatcher.callMethod(
|
||||
this.api.getProvider,
|
||||
providerID,
|
||||
undefined
|
||||
);
|
||||
provider.should.contain.keys('id', 'name', 'residences');
|
||||
return provider;
|
||||
}
|
||||
|
||||
async listProviderIdentityClasses(providerID: string) {
|
||||
const classes = await this.dispatcher.callMethod(
|
||||
this.api.listProviderIdentityClasses,
|
||||
providerID,
|
||||
undefined
|
||||
);
|
||||
classes.should.property('length').not.equal(0);
|
||||
classes[0].should.contain.keys('id', 'name');
|
||||
return classes;
|
||||
}
|
||||
|
||||
async getProviderIdentityClass(providerID: string, identityClassID: string) {
|
||||
const identityClass = await this.dispatcher.callMethod(
|
||||
this.api.getProviderIdentityClass,
|
||||
providerID,
|
||||
identityClassID,
|
||||
undefined
|
||||
);
|
||||
identityClass.should.contain.keys('id', 'name');
|
||||
return identityClass;
|
||||
}
|
||||
|
||||
async listProviderIdentityLevels(providerID: string, identityClassID: string) {
|
||||
try {
|
||||
const levels = await this.dispatcher.callMethod(
|
||||
this.api.listProviderIdentityLevels,
|
||||
providerID,
|
||||
identityClassID,
|
||||
undefined
|
||||
);
|
||||
levels.should.property('length').not.equal(0);
|
||||
levels[0].should.contain.keys('id', 'name', 'challenges');
|
||||
return levels;
|
||||
} catch (e) {
|
||||
e.status.should.equal(501);
|
||||
e.statusText.should.equal('Not Implemented');
|
||||
}
|
||||
}
|
||||
|
||||
async getProviderIdentityLevel(
|
||||
providerID: string,
|
||||
identityClassID: string,
|
||||
identityLevelID: string
|
||||
) {
|
||||
try {
|
||||
const level = await this.dispatcher.callMethod(
|
||||
this.api.getProviderIdentityLevel,
|
||||
providerID,
|
||||
identityClassID,
|
||||
identityLevelID,
|
||||
undefined
|
||||
);
|
||||
level.should.contain.keys('id', 'name', 'challenges');
|
||||
return level;
|
||||
} catch (e) {
|
||||
e.status.should.equal(501);
|
||||
e.statusText.should.equal('Not Implemented');
|
||||
}
|
||||
}
|
||||
|
||||
async getResidence(residenceID: string) {
|
||||
const residence = await this.dispatcher.callMethod(
|
||||
this.residenceAPI.getResidence,
|
||||
residenceID,
|
||||
undefined
|
||||
);
|
||||
residence.should.contain.keys('id', 'name');
|
||||
return residence;
|
||||
}
|
||||
|
||||
async getCurrency(currencyID: string) {
|
||||
const currency = await this.dispatcher.callMethod(
|
||||
this.currenciesAPI.getCurrency,
|
||||
currencyID,
|
||||
undefined
|
||||
);
|
||||
currency.should.contain.keys('id', 'numericCode', 'name', 'exponent');
|
||||
return currency;
|
||||
}
|
||||
}
|
87
actions/wapi-v0/wallet/wallets-actions.ts
Normal file
87
actions/wapi-v0/wallet/wallets-actions.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import * as chai from 'chai';
|
||||
import { Wallet, WalletsApiFp } from '../../../api/wapi-v0/wallet/codegen';
|
||||
import { WAPIDispatcher } from '../../../utils/codegen-utils';
|
||||
import { getSimpleWalletParams } from '../../../api/wapi-v0/wallet/params/wallets-params/simple-wallet-params';
|
||||
import { getWalletGrantParams } from '../../../api/wapi-v0/wallet/params/wallets-params/grant-params';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class WalletsActions {
|
||||
private api;
|
||||
private dispatcher: WAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new WAPIDispatcher({});
|
||||
this.api = WalletsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async createNewWallet(
|
||||
identity: string,
|
||||
name: string = 'Test wallet name',
|
||||
currency: string = 'RUB'
|
||||
): Promise<Wallet> {
|
||||
const walletParams = getSimpleWalletParams(identity, name, currency);
|
||||
const createdWallet = await this.dispatcher.callMethod(
|
||||
this.api.createWallet,
|
||||
walletParams,
|
||||
undefined
|
||||
);
|
||||
createdWallet.should.contain.keys('name', 'currency', 'identity');
|
||||
return createdWallet;
|
||||
}
|
||||
|
||||
getWallet(walletID: string): Promise<Wallet> {
|
||||
return this.dispatcher.callMethod(this.api.getWallet, walletID, undefined);
|
||||
}
|
||||
|
||||
async listWallets(identityID?: string) {
|
||||
const wallets = await Promise.race([
|
||||
this.pollWallets(identityID),
|
||||
new Promise(res => setTimeout(res, 20000))
|
||||
]);
|
||||
if (wallets) {
|
||||
return wallets;
|
||||
}
|
||||
throw new Error('list wallets polling timeout');
|
||||
}
|
||||
|
||||
async getWalletAccount(walletID: string) {
|
||||
const walletAccount = await this.dispatcher.callMethod(
|
||||
this.api.getWalletAccount,
|
||||
walletID,
|
||||
undefined
|
||||
);
|
||||
walletAccount.should.contain.keys('available', 'own');
|
||||
return walletAccount;
|
||||
}
|
||||
|
||||
async issueWalletGrant(walletID: string) {
|
||||
const grantParams = getWalletGrantParams();
|
||||
const grant = await this.dispatcher.callMethod(
|
||||
this.api.issueWalletGrant,
|
||||
walletID,
|
||||
grantParams,
|
||||
undefined
|
||||
);
|
||||
grant.should.contain.keys('token', 'validUntil', 'asset');
|
||||
return grant;
|
||||
}
|
||||
|
||||
async pollWallets(identityID?: string) {
|
||||
let result;
|
||||
while (!result || result.length === 0) {
|
||||
result = (await this.dispatcher.callMethod(
|
||||
this.api.listWallets,
|
||||
1000,
|
||||
undefined,
|
||||
identityID,
|
||||
undefined,
|
||||
undefined
|
||||
)).result;
|
||||
await new Promise(res => setTimeout(res, 3000));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
187
actions/wapi-v0/wallet/withdrawals-actions.ts
Normal file
187
actions/wapi-v0/wallet/withdrawals-actions.ts
Normal file
@ -0,0 +1,187 @@
|
||||
import * as chai from 'chai';
|
||||
import {
|
||||
Destination,
|
||||
WithdrawalParameters,
|
||||
WithdrawalsApiFp
|
||||
} from '../../../api/wapi-v0/wallet/codegen';
|
||||
import { WAPIDispatcher } from '../../../utils/codegen-utils';
|
||||
import { getWithdrawalGrantParams } from '../../../api/wapi-v0/wallet/params/wallets-params/grant-params';
|
||||
import delay from '../../../utils/delay';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class WithdrawalsActions {
|
||||
private api;
|
||||
private dispatcher: WAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.dispatcher = new WAPIDispatcher({});
|
||||
this.api = WithdrawalsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async listDestinations(
|
||||
limit: number,
|
||||
identityID?: string,
|
||||
currencyID?: string,
|
||||
continuationToken?: string
|
||||
) {
|
||||
const destination = await this.dispatcher.callMethod(
|
||||
this.api.listDestinations,
|
||||
limit,
|
||||
identityID,
|
||||
currencyID,
|
||||
continuationToken,
|
||||
undefined
|
||||
);
|
||||
destination.should.contain.keys('result');
|
||||
return destination;
|
||||
}
|
||||
|
||||
async createDestination(destination: Destination) {
|
||||
const dest = await this.dispatcher.callMethod(
|
||||
this.api.createDestination,
|
||||
destination,
|
||||
undefined
|
||||
);
|
||||
dest.should.contain.keys('name', 'identity', 'currency', 'resource');
|
||||
return dest;
|
||||
}
|
||||
|
||||
async createDestinationError(destination: Destination) {
|
||||
return this.dispatcher
|
||||
.callMethod(this.api.createDestination, destination, undefined)
|
||||
.catch(error => {
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
async listWithdrawals(
|
||||
limit: number,
|
||||
walletID?: string,
|
||||
identityID?: string,
|
||||
withdrawalID?: string,
|
||||
destinationID?: string,
|
||||
status?: string,
|
||||
createdAtFrom?: Date,
|
||||
createdAtTo?: Date,
|
||||
amountFrom?: number,
|
||||
amountTo?: number,
|
||||
currencyID?: string,
|
||||
continuationToken?: string
|
||||
) {
|
||||
const withdrawals = await this.dispatcher.callMethod(
|
||||
this.api.listWithdrawals,
|
||||
limit,
|
||||
undefined,
|
||||
walletID,
|
||||
identityID,
|
||||
withdrawalID,
|
||||
destinationID,
|
||||
status,
|
||||
createdAtFrom,
|
||||
createdAtTo,
|
||||
amountFrom,
|
||||
amountTo,
|
||||
currencyID,
|
||||
continuationToken
|
||||
);
|
||||
withdrawals.should.contain.keys('result');
|
||||
return withdrawals;
|
||||
}
|
||||
|
||||
async createWithdrawal(withdrawalParams: WithdrawalParameters) {
|
||||
return await this.dispatcher.callMethod(
|
||||
this.api.createWithdrawal,
|
||||
withdrawalParams,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
async getDestination(destinationID: string) {
|
||||
const destination = await this.dispatcher.callMethod(
|
||||
this.api.getDestination,
|
||||
destinationID,
|
||||
undefined
|
||||
);
|
||||
destination.should.contain.keys('name', 'identity', 'currency', 'resource');
|
||||
return destination;
|
||||
}
|
||||
|
||||
async issueDestinationGrant(destinationID: string) {
|
||||
const grantParams = getWithdrawalGrantParams();
|
||||
const grant = await this.dispatcher.callMethod(
|
||||
this.api.issueDestinationGrant,
|
||||
destinationID,
|
||||
grantParams,
|
||||
undefined
|
||||
);
|
||||
grant.should.contain.keys('token', 'validUntil');
|
||||
return grant;
|
||||
}
|
||||
|
||||
async getWithdrawal(withdrawalID: string) {
|
||||
const withdrawal = await this.dispatcher.callMethod(
|
||||
this.api.getWithdrawal,
|
||||
withdrawalID,
|
||||
undefined
|
||||
);
|
||||
withdrawal.should.contain.keys('wallet', 'destination', 'body');
|
||||
return withdrawal;
|
||||
}
|
||||
|
||||
async getWithdrawalByExternal(externalID: string) {
|
||||
const withdrawal = await this.dispatcher.callMethod(
|
||||
this.api.getWithdrawalByExternalID,
|
||||
externalID,
|
||||
undefined
|
||||
);
|
||||
withdrawal.should.contain.keys('wallet', 'destination', 'body', 'externalID');
|
||||
return withdrawal;
|
||||
}
|
||||
|
||||
async pollWithdrawalEvents(withdrawalID: string) {
|
||||
const events = await this.dispatcher.callMethod(
|
||||
this.api.pollWithdrawalEvents,
|
||||
withdrawalID,
|
||||
1000,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
events.should.property('length').not.equal(0);
|
||||
events[0].should.contain.keys('eventID', 'occuredAt', 'changes');
|
||||
return events;
|
||||
}
|
||||
|
||||
async getWithdrawalEvents(withdrawalID: string, eventID: string) {
|
||||
const event = await this.dispatcher.callMethod(
|
||||
this.api.getWithdrawalEvents,
|
||||
withdrawalID,
|
||||
eventID,
|
||||
undefined
|
||||
);
|
||||
event.should.contain.keys('changes', 'eventID', 'occuredAt');
|
||||
return event;
|
||||
}
|
||||
|
||||
async waitDestinationCreate(destinationID: string) {
|
||||
let result = await Promise.race([
|
||||
new Promise(res => setTimeout(res, 10000)),
|
||||
this.pollDestinationCreation(destinationID)
|
||||
]);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
throw 'poll destination create timeout';
|
||||
}
|
||||
|
||||
async pollDestinationCreation(destinationID: string) {
|
||||
let isCreated;
|
||||
while (!isCreated) {
|
||||
isCreated = (await this.getDestination(destinationID)).id;
|
||||
await delay(1500);
|
||||
}
|
||||
return isCreated;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import { WithdrawalStatus } from '../../../../api/wapi-v0/wallet/codegen';
|
||||
|
||||
import WithdrawalStatusType = WithdrawalStatus.StatusEnum;
|
||||
|
||||
export type ChangeWithdrawalCondition = (change: WithdrawalStatus) => boolean;
|
||||
|
||||
// TODO: fix failed withdrawal
|
||||
export function isWithdrawalSucceeded(): ChangeWithdrawalCondition {
|
||||
return (change: WithdrawalStatus) => change.status === WithdrawalStatusType.Failed;
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export * from './withdrawals-event-actions';
|
||||
export * from './conditions';
|
@ -0,0 +1,25 @@
|
||||
import { WAPIDispatcher } from '../../../../utils/codegen-utils';
|
||||
import { WithdrawalEvent, WithdrawalsApiFp } from '../../../../api/wapi-v0/wallet/codegen';
|
||||
import { EventActions } from '../../../event-actions';
|
||||
|
||||
export class WithdrawalsEventActions extends EventActions {
|
||||
private dispatcher: WAPIDispatcher;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
super();
|
||||
this.dispatcher = new WAPIDispatcher({});
|
||||
this.api = WithdrawalsApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
async getEvents(...args: any[]): Promise<WithdrawalEvent[]> {
|
||||
return await this.dispatcher.callMethod(
|
||||
this.api.pollWithdrawalEvents,
|
||||
...args,
|
||||
1000,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
}
|
33
api/auth/get-access-token.ts
Normal file
33
api/auth/get-access-token.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import * as chai from 'chai';
|
||||
import { authEndpoint } from '../../settings';
|
||||
import request = require('request');
|
||||
|
||||
chai.should();
|
||||
|
||||
export function getAccessToken(
|
||||
realm: string,
|
||||
login: string,
|
||||
password: string,
|
||||
clientID: string
|
||||
): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post(
|
||||
{
|
||||
url: `${authEndpoint}/auth/realms/${realm}/protocol/openid-connect/token`,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
Host: process.env.AUTH_HOST
|
||||
},
|
||||
body: `username=${login}&password=${password}&client_id=${clientID}&grant_type=password`
|
||||
},
|
||||
(err, response, body) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
response.statusCode.should.eq(200);
|
||||
resolve(JSON.parse(body).access_token);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
2
api/capi-v2/index.ts
Normal file
2
api/capi-v2/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './codegen/api';
|
||||
export * from './params';
|
184
api/capi-v2/params/claim-params/default-claim-params.ts
Normal file
184
api/capi-v2/params/claim-params/default-claim-params.ts
Normal file
@ -0,0 +1,184 @@
|
||||
import * as moment from 'moment';
|
||||
import {
|
||||
PartyModification,
|
||||
ContractModification,
|
||||
ContractCreation,
|
||||
Contractor,
|
||||
LegalEntity,
|
||||
BankAccount,
|
||||
ContractPayoutToolCreation,
|
||||
PayoutToolDetails,
|
||||
PayoutToolDetailsBankAccount,
|
||||
ContractLegalAgreementBinding,
|
||||
LegalAgreement,
|
||||
ShopModification,
|
||||
ShopCreation,
|
||||
ShopCategoryChange,
|
||||
ShopPayoutScheduleChange,
|
||||
ShopAccountCreation,
|
||||
ShopLocationUrl,
|
||||
ShopDetails,
|
||||
PayoutToolDetailsWalletInfo
|
||||
} from '../../codegen';
|
||||
|
||||
import PartyModificationType = PartyModification.PartyModificationTypeEnum;
|
||||
import ContractModificationType = ContractModification.ContractModificationTypeEnum;
|
||||
import ShopModificationType = ShopModification.ShopModificationTypeEnum;
|
||||
|
||||
/* Contract changes and defaults */
|
||||
|
||||
export const defaultContractor = {
|
||||
contractorType: Contractor.ContractorTypeEnum.LegalEntity,
|
||||
entityType: LegalEntity.EntityTypeEnum.RussianLegalEntity,
|
||||
registeredName: 'ООО Иванов Иван Иванович',
|
||||
registeredNumber: '1117800008336',
|
||||
inn: '7840290139',
|
||||
actualAddress:
|
||||
'191040, г Санкт-Петербург, Центральный р-н, Лиговский пр-кт, д 87 стр а, оф 15Н',
|
||||
postAddress: '191040, г Санкт-Петербург, Центральный р-н, Лиговский пр-кт, д 87 стр а, оф 509',
|
||||
representativePosition: 'Директор',
|
||||
representativeFullName: 'Кочетков Игорь Викторович',
|
||||
representativeDocument:
|
||||
'паспорт 4012688115, 28.02.2013, ТП №71 отдела УФМС России по Санкт-Петербургу и Ленинградской обл. в Пушкинском р-не гор. Санкт-Петербурга',
|
||||
bankAccount: {
|
||||
account: '40703810432060000034',
|
||||
bankName: 'ФИЛИАЛ "САНКТ-ПЕТЕРБУРГСКИЙ" АО "АЛЬФА-БАНК"',
|
||||
bankPostAccount: '30101810600000000786',
|
||||
bankBik: '044030786'
|
||||
} as BankAccount
|
||||
} as Contractor;
|
||||
|
||||
export function contractCreationChange(
|
||||
contractID: string,
|
||||
paymentInstitutionID: number,
|
||||
contractor?: Contractor
|
||||
): ContractCreation {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ContractModification,
|
||||
contractID: contractID,
|
||||
contractModificationType: ContractModificationType.ContractCreation,
|
||||
paymentInstitutionID: paymentInstitutionID,
|
||||
contractor: contractor || defaultContractor
|
||||
} as ContractCreation;
|
||||
}
|
||||
|
||||
export const defaultPayoutToolDetails = {
|
||||
detailsType: 'PayoutToolDetailsBankAccount',
|
||||
account: '40703810432060000034',
|
||||
bankName: 'ФИЛИАЛ "САНКТ-ПЕТЕРБУРГСКИЙ" АО "АЛЬФА-БАНК"',
|
||||
bankPostAccount: '30101810600000000786',
|
||||
bankBik: '044030786'
|
||||
} as PayoutToolDetailsBankAccount;
|
||||
|
||||
export function contractPayoutToolCreationChange(
|
||||
contractID: string,
|
||||
payoutToolID: string,
|
||||
currency: string,
|
||||
details?: PayoutToolDetails
|
||||
): ContractPayoutToolCreation {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ContractModification,
|
||||
contractID: contractID,
|
||||
contractModificationType: ContractModificationType.ContractPayoutToolCreation,
|
||||
payoutToolID: payoutToolID,
|
||||
currency: currency,
|
||||
details: details || defaultPayoutToolDetails
|
||||
} as ContractPayoutToolCreation;
|
||||
}
|
||||
|
||||
export function getDefaultWalletInfo(walletID?: string): PayoutToolDetailsWalletInfo {
|
||||
return {
|
||||
detailsType: 'PayoutToolDetailsWalletInfo',
|
||||
walletID: walletID || '1'
|
||||
};
|
||||
}
|
||||
|
||||
export function contractPayoutToolWalletCreationChange(
|
||||
contractID: string,
|
||||
payoutToolID: string,
|
||||
currency: string,
|
||||
walletID?: string
|
||||
): ContractPayoutToolCreation {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ContractModification,
|
||||
contractID: contractID,
|
||||
contractModificationType: ContractModificationType.ContractPayoutToolCreation,
|
||||
payoutToolID: payoutToolID,
|
||||
currency: currency,
|
||||
details: getDefaultWalletInfo(walletID)
|
||||
} as ContractPayoutToolCreation;
|
||||
}
|
||||
|
||||
export const defaultLegalAgreement = {
|
||||
id: '006815/07',
|
||||
signedAt: moment()
|
||||
.subtract(1, 'days')
|
||||
.utc()
|
||||
.format() as any
|
||||
} as LegalAgreement;
|
||||
|
||||
export function contractLegalAgreementBindingChange(
|
||||
contractID: string,
|
||||
legalAgreement?: LegalAgreement
|
||||
): ContractLegalAgreementBinding {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ContractModification,
|
||||
contractID: contractID,
|
||||
contractModificationType: ContractModificationType.ContractLegalAgreementBinding,
|
||||
legalAgreement: legalAgreement || defaultLegalAgreement
|
||||
} as ContractLegalAgreementBinding;
|
||||
}
|
||||
|
||||
/* Shop changes and defaults */
|
||||
|
||||
export function shopCreationChange(
|
||||
shopID: string,
|
||||
contractID: string,
|
||||
payoutToolID: string
|
||||
): ShopCreation {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ShopModification,
|
||||
shopID: shopID,
|
||||
shopModificationType: ShopModificationType.ShopCreation,
|
||||
location: {
|
||||
locationType: 'ShopLocationUrl',
|
||||
url: 'http://test.url'
|
||||
} as ShopLocationUrl,
|
||||
details: {
|
||||
name: 'Test shop',
|
||||
description: 'Shop for test integration'
|
||||
} as ShopDetails,
|
||||
contractID: contractID,
|
||||
payoutToolID: payoutToolID
|
||||
} as ShopCreation;
|
||||
}
|
||||
|
||||
export function shopCategoryChange(shopID: string, categoryID: number): ShopCategoryChange {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ShopModification,
|
||||
shopID: shopID,
|
||||
shopModificationType: ShopModificationType.ShopCategoryChange,
|
||||
categoryID: categoryID
|
||||
} as ShopCategoryChange;
|
||||
}
|
||||
|
||||
export function shopAccountCreationChange(shopID: string, currency: string): ShopAccountCreation {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ShopModification,
|
||||
shopID: shopID,
|
||||
shopModificationType: ShopModificationType.ShopAccountCreation,
|
||||
currency: currency
|
||||
} as ShopAccountCreation;
|
||||
}
|
||||
|
||||
export function shopPayoutScheduleChange(
|
||||
shopID: string,
|
||||
scheduleID: number | undefined
|
||||
): ShopPayoutScheduleChange {
|
||||
return {
|
||||
partyModificationType: PartyModificationType.ShopModification,
|
||||
shopModificationType: ShopModificationType.ShopPayoutScheduleChange,
|
||||
shopID,
|
||||
scheduleID
|
||||
};
|
||||
}
|
39
api/capi-v2/params/claim-params/live-shop-claim-params.ts
Normal file
39
api/capi-v2/params/claim-params/live-shop-claim-params.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import guid from '../../../../utils/guid';
|
||||
import {
|
||||
contractCreationChange,
|
||||
contractPayoutToolCreationChange,
|
||||
contractLegalAgreementBindingChange,
|
||||
shopCreationChange,
|
||||
shopCategoryChange,
|
||||
shopAccountCreationChange,
|
||||
contractPayoutToolWalletCreationChange
|
||||
} from './default-claim-params';
|
||||
import { ClaimChangeset } from '../../codegen';
|
||||
|
||||
export function liveShopClaimChangeset(id?: string): ClaimChangeset {
|
||||
const liveShopID = id || guid();
|
||||
const liveContractID = id || guid();
|
||||
const livePayoutToolID = id || guid();
|
||||
|
||||
return [
|
||||
contractCreationChange(liveContractID, 2),
|
||||
contractPayoutToolCreationChange(liveContractID, livePayoutToolID, 'RUB'),
|
||||
contractLegalAgreementBindingChange(liveContractID),
|
||||
shopCreationChange(liveShopID, liveContractID, livePayoutToolID),
|
||||
shopCategoryChange(liveShopID, 2),
|
||||
shopAccountCreationChange(liveShopID, 'RUB')
|
||||
] as ClaimChangeset;
|
||||
}
|
||||
|
||||
export function createPayoutToolClaimChangeset(liveContractID: string): ClaimChangeset {
|
||||
return [contractPayoutToolCreationChange(liveContractID, guid(), 'RUB')] as ClaimChangeset;
|
||||
}
|
||||
|
||||
export function createWalletPayoutToolClaimChangeset(
|
||||
liveContractID: string,
|
||||
walletID: string
|
||||
): ClaimChangeset {
|
||||
return [
|
||||
contractPayoutToolWalletCreationChange(liveContractID, guid(), 'RUB', walletID)
|
||||
] as ClaimChangeset;
|
||||
}
|
25
api/capi-v2/params/claim-params/test-shop-claim-params.ts
Normal file
25
api/capi-v2/params/claim-params/test-shop-claim-params.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import guid from '../../../../utils/guid';
|
||||
import {
|
||||
contractCreationChange,
|
||||
contractPayoutToolCreationChange,
|
||||
contractLegalAgreementBindingChange,
|
||||
shopCreationChange,
|
||||
shopCategoryChange,
|
||||
shopAccountCreationChange
|
||||
} from './default-claim-params';
|
||||
import { ClaimChangeset } from '../../codegen';
|
||||
|
||||
export function testShopClaimChangeset(id?: string): ClaimChangeset {
|
||||
const testShopID = id || guid();
|
||||
const testContractID = id || guid();
|
||||
const testPayoutToolID = id || guid();
|
||||
|
||||
return [
|
||||
contractCreationChange(testContractID, 1),
|
||||
contractPayoutToolCreationChange(testContractID, testPayoutToolID, 'RUB'),
|
||||
contractLegalAgreementBindingChange(testContractID),
|
||||
shopCreationChange(testShopID, testContractID, testPayoutToolID),
|
||||
shopCategoryChange(testShopID, 1),
|
||||
shopAccountCreationChange(testShopID, 'RUB')
|
||||
] as ClaimChangeset;
|
||||
}
|
13
api/capi-v2/params/index.ts
Normal file
13
api/capi-v2/params/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export * from './invoice-params/simple-invoice-params';
|
||||
export * from './payment-params/payment-params';
|
||||
export * from './payment-params/payer-params';
|
||||
export * from './payment-params/refund-params';
|
||||
export * from './payment-tools/qiwi-payment-tool';
|
||||
export * from './payment-tools/crypto-payment-tool';
|
||||
export * from './payment-tools/sane-visa-payment-tool';
|
||||
export * from './payment-tools/insufficient-funds-visa-tool';
|
||||
export * from './payment-tools/secure-visa-payment-tool';
|
||||
export * from './payment-tools/secure-visa-empty-cvv-payment-tool';
|
||||
export * from './claim-params/test-shop-claim-params';
|
||||
export * from './claim-params/live-shop-claim-params';
|
||||
export * from './webhook/params';
|
67
api/capi-v2/params/invoice-params/simple-invoice-params.ts
Normal file
67
api/capi-v2/params/invoice-params/simple-invoice-params.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import * as moment from 'moment';
|
||||
import { InvoiceLineTaxMode, InvoiceLineTaxVAT, InvoiceParams } from '../../codegen';
|
||||
import { Invoice, InvoiceParamsWithTemplate } from '../../index';
|
||||
|
||||
export function simpleInvoiceParams(shopID: string, params?: {}): InvoiceParams {
|
||||
return {
|
||||
shopID: shopID,
|
||||
dueDate: moment()
|
||||
.add(1, 'days')
|
||||
.utc()
|
||||
.format() as any,
|
||||
amount: 10000,
|
||||
currency: 'RUB',
|
||||
product: 'Test product',
|
||||
description: 'Test product description',
|
||||
cart: [
|
||||
{
|
||||
product: 'Product 1',
|
||||
quantity: 1,
|
||||
price: 10000,
|
||||
taxMode: {
|
||||
type: InvoiceLineTaxMode.TypeEnum.InvoiceLineTaxVAT,
|
||||
rate: InvoiceLineTaxVAT.RateEnum._10
|
||||
} as InvoiceLineTaxVAT
|
||||
}
|
||||
],
|
||||
metadata: {
|
||||
test: 1
|
||||
},
|
||||
...params
|
||||
} as InvoiceParams;
|
||||
}
|
||||
|
||||
export function invoiceParamsWithTemplate(params?: {}): InvoiceParamsWithTemplate {
|
||||
return {
|
||||
amount: 10000,
|
||||
currency: 'RUB',
|
||||
metadata: { test: 1 },
|
||||
...params
|
||||
};
|
||||
}
|
||||
|
||||
export function assertSimpleInvoice(invoice: Invoice, amount: number, shopID: string) {
|
||||
invoice.should.to.include({
|
||||
amount,
|
||||
currency: 'RUB',
|
||||
description: 'Test product description',
|
||||
product: 'Test product',
|
||||
shopID: shopID,
|
||||
status: 'unpaid'
|
||||
});
|
||||
invoice.cart.should.to.deep.equal([
|
||||
{
|
||||
cost: amount,
|
||||
price: amount,
|
||||
product: 'Product 1',
|
||||
quantity: 1,
|
||||
taxMode: {
|
||||
type: 'InvoiceLineTaxVAT',
|
||||
rate: '10%'
|
||||
}
|
||||
}
|
||||
]);
|
||||
invoice.metadata.should.to.deep.equal({ test: 1 });
|
||||
invoice.should.to.have.property('createdAt').to.be.a('string');
|
||||
invoice.should.to.have.property('id').to.be.a('string');
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
import { InvoiceLineTaxVAT } from '../../codegen';
|
||||
import { Invoice, InvoiceTemplate, InvoiceTemplateCreateParams } from '../../index';
|
||||
|
||||
export function simpleInvoiceTemplateParams(
|
||||
shopID: string,
|
||||
params?: {}
|
||||
): InvoiceTemplateCreateParams {
|
||||
return {
|
||||
shopID,
|
||||
product: 'Test product',
|
||||
description: 'Test product description',
|
||||
lifetime: {
|
||||
days: 3,
|
||||
months: 0,
|
||||
years: 0
|
||||
},
|
||||
details: {
|
||||
templateType: 'InvoiceTemplateMultiLine',
|
||||
cart: [
|
||||
{
|
||||
product: 'Product 1',
|
||||
quantity: 1,
|
||||
price: 10000,
|
||||
taxMode: {
|
||||
type: 'InvoiceLineTaxVAT',
|
||||
rate: '10%'
|
||||
}
|
||||
}
|
||||
],
|
||||
currency: 'RUB'
|
||||
},
|
||||
metadata: { test: 1 },
|
||||
...params
|
||||
} as InvoiceTemplateCreateParams;
|
||||
}
|
||||
|
||||
export function assertSimpleInvoiceTemplate(
|
||||
invoiceTemplate: InvoiceTemplate,
|
||||
shopID: string,
|
||||
assertParams?: {}
|
||||
) {
|
||||
invoiceTemplate.should.to.include({
|
||||
shopID: shopID,
|
||||
description: 'Test product description',
|
||||
...assertParams
|
||||
});
|
||||
invoiceTemplate.lifetime.should.to.deep.equal({
|
||||
days: 3,
|
||||
months: 0,
|
||||
years: 0
|
||||
});
|
||||
invoiceTemplate.details.should.to.include({
|
||||
templateType: 'InvoiceTemplateMultiLine'
|
||||
});
|
||||
invoiceTemplate.should.to.have.property('id').to.be.a('string');
|
||||
invoiceTemplate.metadata.should.to.deep.equal({ test: 1 });
|
||||
}
|
||||
|
||||
export function assertSimpleInvoiceWithTemplate(invoice: Invoice, amount: number, shopID: string) {
|
||||
invoice.should.to.include({
|
||||
amount,
|
||||
currency: 'RUB',
|
||||
description: 'Test product description',
|
||||
product: 'Product 1',
|
||||
shopID: shopID,
|
||||
status: 'unpaid'
|
||||
});
|
||||
invoice.cart.should.to.deep.equal([
|
||||
{
|
||||
cost: amount,
|
||||
price: amount,
|
||||
product: 'Product 1',
|
||||
quantity: 1,
|
||||
taxMode: {
|
||||
type: 'InvoiceLineTaxVAT',
|
||||
rate: '10%'
|
||||
}
|
||||
}
|
||||
]);
|
||||
invoice.metadata.should.to.deep.equal({ test: 1 });
|
||||
invoice.should.to.have.property('createdAt').to.be.a('string');
|
||||
invoice.should.to.have.property('id').to.be.a('string');
|
||||
}
|
69
api/capi-v2/params/payment-params/payer-params.ts
Normal file
69
api/capi-v2/params/payment-params/payer-params.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import {
|
||||
PaymentResource,
|
||||
PaymentResourcePayer,
|
||||
PaymentRecurrentParent,
|
||||
RecurrentPayer,
|
||||
CustomerPayer,
|
||||
Payer
|
||||
} from '../../codegen';
|
||||
|
||||
export function paymentResourcePayer(payload: PaymentResource): PaymentResourcePayer {
|
||||
return {
|
||||
payerType: 'PaymentResourcePayer',
|
||||
paymentToolToken: payload.paymentToolToken,
|
||||
paymentSession: payload.paymentSession,
|
||||
contactInfo: {
|
||||
email: 'user@example.com'
|
||||
}
|
||||
} as PaymentResourcePayer;
|
||||
}
|
||||
|
||||
export function recurrentPayer(payload: PaymentRecurrentParent): RecurrentPayer {
|
||||
return {
|
||||
payerType: 'RecurrentPayer',
|
||||
recurrentParentPayment: payload,
|
||||
contactInfo: {
|
||||
email: 'user@example.com'
|
||||
}
|
||||
} as RecurrentPayer;
|
||||
}
|
||||
|
||||
export function assertPayer(payer: Payer) {
|
||||
switch (payer.payerType) {
|
||||
case 'PaymentResourcePayer':
|
||||
payer.should.to.deep.include({
|
||||
contactInfo: {
|
||||
email: 'user@example.com'
|
||||
}
|
||||
});
|
||||
payer.should.to.have.property('paymentSession').to.be.a('string');
|
||||
payer.should.to.have.property('paymentToolToken').to.be.a('string');
|
||||
payer.should.to.have.property('paymentToolDetails').to.be.a('object');
|
||||
payer.should.to.have.property('contactInfo').to.be.a('object');
|
||||
payer.should.to.have.property('clientInfo').to.be.a('object');
|
||||
return;
|
||||
case 'RecurrentPayer':
|
||||
payer.should.to.deep.include({
|
||||
contactInfo: {
|
||||
email: 'user@example.com'
|
||||
}
|
||||
});
|
||||
payer.should.to.have.property('contactInfo').to.be.a('object');
|
||||
payer.should.to.have.property('paymentToolToken').to.be.a('string');
|
||||
payer.should.to.have.property('paymentToolDetails').to.be.a('object');
|
||||
const parent = (payer as RecurrentPayer).recurrentParentPayment;
|
||||
parent.should.to.have.property('invoiceID').to.be.a('string');
|
||||
parent.should.to.have.property('paymentID').to.be.a('string');
|
||||
return;
|
||||
case 'CustomerPayer':
|
||||
payer.should.to.deep.include({
|
||||
contactInfo: {
|
||||
email: 'user@example.com'
|
||||
}
|
||||
});
|
||||
payer.should.to.have.property('customerID').to.be.a('string');
|
||||
payer.should.to.have.property('paymentToolToken').to.be.a('string');
|
||||
payer.should.to.have.property('paymentToolDetails').to.be.a('object');
|
||||
return;
|
||||
}
|
||||
}
|
72
api/capi-v2/params/payment-params/payment-params.ts
Normal file
72
api/capi-v2/params/payment-params/payment-params.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { PaymentFlow, PaymentParams, CaptureParams, Payer } from '../../codegen';
|
||||
import TypeEnum = PaymentFlow.TypeEnum;
|
||||
import { Payment } from '../../';
|
||||
import { assertPayer } from './payer-params';
|
||||
|
||||
function getFlow(paymentType: TypeEnum, holdType?: string) {
|
||||
switch (paymentType) {
|
||||
case TypeEnum.PaymentFlowHold:
|
||||
return {
|
||||
type: paymentType,
|
||||
onHoldExpiration: holdType === undefined ? 'capture' : holdType
|
||||
};
|
||||
case TypeEnum.PaymentFlowInstant:
|
||||
default:
|
||||
return {
|
||||
type: paymentType
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function paymentParams(
|
||||
payer: Payer,
|
||||
paymentType: TypeEnum,
|
||||
makeRecurrent: boolean,
|
||||
holdType?: string,
|
||||
externalID?: string,
|
||||
metadata?: object
|
||||
): PaymentParams {
|
||||
return {
|
||||
externalID,
|
||||
flow: getFlow(paymentType, holdType),
|
||||
payer: payer,
|
||||
makeRecurrent: makeRecurrent,
|
||||
metadata: metadata
|
||||
};
|
||||
}
|
||||
|
||||
export function captureParams(amount?: number): CaptureParams {
|
||||
return amount === undefined
|
||||
? {
|
||||
reason: 'testCapture'
|
||||
}
|
||||
: {
|
||||
reason: 'testCapture',
|
||||
amount: amount,
|
||||
currency: 'RUB'
|
||||
};
|
||||
}
|
||||
|
||||
export function assertPayment(
|
||||
payment: Payment,
|
||||
amount: number,
|
||||
paymentType: TypeEnum,
|
||||
holdType?: string,
|
||||
metadata?: object
|
||||
) {
|
||||
payment.should.to.include({
|
||||
amount: amount,
|
||||
currency: 'RUB'
|
||||
});
|
||||
if (metadata != undefined) {
|
||||
payment.should.have.deep.property('metadata', metadata);
|
||||
}
|
||||
payment.flow.should.to.include(getFlow(paymentType, holdType));
|
||||
payment.should.to.have.property('status').to.be.a('string');
|
||||
payment.should.to.have.property('id').to.be.a('string');
|
||||
payment.should.to.have.property('createdAt').to.be.a('string');
|
||||
payment.should.to.have.property('invoiceID').to.be.a('string');
|
||||
payment.should.to.have.property('payer').to.be.a('object');
|
||||
payment.should.to.have.property('makeRecurrent').to.be.a('boolean');
|
||||
assertPayer(payment.payer);
|
||||
}
|
14
api/capi-v2/params/payment-params/refund-params.ts
Normal file
14
api/capi-v2/params/payment-params/refund-params.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { RefundParams } from '../../codegen';
|
||||
|
||||
export function refundParams(
|
||||
amount?: number,
|
||||
currency?: string,
|
||||
externalID?: string
|
||||
): RefundParams {
|
||||
return {
|
||||
amount: amount,
|
||||
currency: currency,
|
||||
reason: 'Some reason',
|
||||
externalID: externalID
|
||||
};
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { CardData, PaymentTool, PaymentResourceParams } from '../../codegen';
|
||||
|
||||
export const badCardholderPaymentTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.CardData,
|
||||
cardNumber: '4242424242424242',
|
||||
expDate: '12/20',
|
||||
cvv: '123',
|
||||
cardHolder: 'ЛЕХА СВОТИН 123'
|
||||
} as CardData,
|
||||
clientInfo: {
|
||||
fingerprint: '316a2eee53ea181b3deecb70691021ce'
|
||||
}
|
||||
} as PaymentResourceParams;
|
11
api/capi-v2/params/payment-tools/crypto-payment-tool.ts
Normal file
11
api/capi-v2/params/payment-tools/crypto-payment-tool.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { CryptoWalletData, PaymentTool, PaymentResourceParams } from '../../codegen';
|
||||
|
||||
export const cryptoPaymentTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.CryptoWalletData,
|
||||
cryptoCurrency: 'bitcoinCash'
|
||||
} as CryptoWalletData,
|
||||
clientInfo: {
|
||||
fingerprint: 'dc8280558372bd072521cff0f178aa1c'
|
||||
}
|
||||
} as PaymentResourceParams;
|
@ -0,0 +1,14 @@
|
||||
import { CardData, PaymentTool, PaymentResourceParams } from '../../codegen';
|
||||
|
||||
export const insufficientFundsVisaTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.CardData,
|
||||
cardNumber: '4000000000000002',
|
||||
expDate: '12/20',
|
||||
cvv: '123',
|
||||
cardHolder: 'LEXA SVOTIN'
|
||||
} as CardData,
|
||||
clientInfo: {
|
||||
fingerprint: '316a2eee53ea181b3deecb70691021ce'
|
||||
}
|
||||
} as PaymentResourceParams;
|
17
api/capi-v2/params/payment-tools/qiwi-payment-tool.ts
Normal file
17
api/capi-v2/params/payment-tools/qiwi-payment-tool.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import {
|
||||
DigitalWalletData,
|
||||
DigitalWalletQIWI,
|
||||
PaymentTool,
|
||||
PaymentResourceParams
|
||||
} from '../../codegen';
|
||||
|
||||
export const qiwiPaymentTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.DigitalWalletData,
|
||||
digitalWalletType: DigitalWalletData.DigitalWalletTypeEnum.DigitalWalletQIWI,
|
||||
phoneNumber: '+7911111111'
|
||||
} as DigitalWalletQIWI,
|
||||
clientInfo: {
|
||||
fingerprint: '71aadcee86e140f794924855f5e48aa9'
|
||||
}
|
||||
} as PaymentResourceParams;
|
14
api/capi-v2/params/payment-tools/sane-visa-payment-tool.ts
Normal file
14
api/capi-v2/params/payment-tools/sane-visa-payment-tool.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { CardData, PaymentTool, PaymentResourceParams } from '../../codegen';
|
||||
|
||||
export const saneVisaPaymentTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.CardData,
|
||||
cardNumber: '4242424242424242',
|
||||
expDate: '12/20',
|
||||
cvv: '123',
|
||||
cardHolder: 'LEXA SVOTIN'
|
||||
} as CardData,
|
||||
clientInfo: {
|
||||
fingerprint: '316a2eee53ea181b3deecb70691021ce'
|
||||
}
|
||||
} as PaymentResourceParams;
|
@ -0,0 +1,13 @@
|
||||
import { CardData, PaymentTool, PaymentResourceParams } from '../../codegen';
|
||||
|
||||
export const secureEmptyCVVVisaPaymentTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.CardData,
|
||||
cardNumber: '4012888888881881',
|
||||
expDate: '12/20',
|
||||
cardHolder: 'LEXA SVOTIN'
|
||||
} as CardData,
|
||||
clientInfo: {
|
||||
fingerprint: '316a2eee53ea181b3deecb70691021ce'
|
||||
}
|
||||
} as PaymentResourceParams;
|
14
api/capi-v2/params/payment-tools/secure-visa-payment-tool.ts
Normal file
14
api/capi-v2/params/payment-tools/secure-visa-payment-tool.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { CardData, PaymentTool, PaymentResourceParams } from '../../codegen';
|
||||
|
||||
export const secureVisaPaymentTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.CardData,
|
||||
cardNumber: '4012888888881881',
|
||||
expDate: '12/20',
|
||||
cvv: '123',
|
||||
cardHolder: 'LEXA SVOTIN'
|
||||
} as CardData,
|
||||
clientInfo: {
|
||||
fingerprint: '316a2eee53ea181b3deecb70691021ce'
|
||||
}
|
||||
} as PaymentResourceParams;
|
13
api/capi-v2/params/payment-tools/terminal-payment-tool.ts
Normal file
13
api/capi-v2/params/payment-tools/terminal-payment-tool.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { PaymentTerminalData, PaymentTool, PaymentResourceParams } from '../../codegen';
|
||||
import { PaymentTerminalDetails } from '../../';
|
||||
import ProviderEnum = PaymentTerminalDetails.ProviderEnum;
|
||||
|
||||
export const terminalPaymentTool = {
|
||||
paymentTool: {
|
||||
paymentToolType: PaymentTool.PaymentToolTypeEnum.PaymentTerminalData,
|
||||
provider: ProviderEnum.Euroset
|
||||
} as PaymentTerminalData,
|
||||
clientInfo: {
|
||||
fingerprint: '316a2eee53ea181b3deecb70691021ce'
|
||||
}
|
||||
} as PaymentResourceParams;
|
46
api/capi-v2/params/webhook/params.ts
Normal file
46
api/capi-v2/params/webhook/params.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { Webhook, WebhookScope } from '../../codegen';
|
||||
import * as request from 'request';
|
||||
import { testWebhookReceiverEndpoint, testWebhookReceiverInternal } from '../../../../settings';
|
||||
|
||||
export function webhookParams(scope: WebhookScope, testId: string): Webhook {
|
||||
return {
|
||||
scope: scope,
|
||||
url: `${testWebhookReceiverInternal}/hooker/${testId}`
|
||||
} as Webhook;
|
||||
}
|
||||
|
||||
export function getEvents(testId: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.get(
|
||||
{
|
||||
url: `${testWebhookReceiverEndpoint}/search/get/${testId}`
|
||||
},
|
||||
(err, response) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
response.statusCode.should.eq(200);
|
||||
resolve(response.body);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function countEvents(testId: string): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.get(
|
||||
{
|
||||
url: `${testWebhookReceiverEndpoint}/search/count/${testId}`
|
||||
},
|
||||
(err, response) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
response.statusCode.should.eq(200);
|
||||
resolve(JSON.parse(response.body).count);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
5
api/index.ts
Normal file
5
api/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './auth/get-access-token';
|
||||
export * from './capi-v2';
|
||||
// @ts-ignore
|
||||
export * from './papi-v1';
|
||||
export * from './url-shortener-v1';
|
16
api/papi-v1/api-key-auth.ts
Normal file
16
api/papi-v1/api-key-auth.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import request = require('request');
|
||||
import { Authentication } from './authentication';
|
||||
|
||||
export class ApiKeyAuth implements Authentication {
|
||||
public apiKey: string;
|
||||
|
||||
constructor(private location: string, private paramName: string) {}
|
||||
|
||||
applyToRequest(requestOptions: request.Options): void {
|
||||
if (this.location == 'query') {
|
||||
(<any>requestOptions.qs)[this.paramName] = this.apiKey;
|
||||
} else if (this.location == 'header' && requestOptions && requestOptions.headers) {
|
||||
requestOptions.headers[this.paramName] = this.apiKey;
|
||||
}
|
||||
}
|
||||
}
|
8
api/papi-v1/authentication.ts
Normal file
8
api/papi-v1/authentication.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import request = require('request');
|
||||
|
||||
export interface Authentication {
|
||||
/**
|
||||
* Apply authentication settings to header and query params.
|
||||
*/
|
||||
applyToRequest(requestOptions: request.Options): void;
|
||||
}
|
3
api/papi-v1/claims-api-api-keys.ts
Normal file
3
api/papi-v1/claims-api-api-keys.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export enum ClaimsApiApiKeys {
|
||||
bearer
|
||||
}
|
132
api/papi-v1/claims-api.ts
Normal file
132
api/papi-v1/claims-api.ts
Normal file
@ -0,0 +1,132 @@
|
||||
import request = require('request');
|
||||
import http = require('http');
|
||||
import * as chai from 'chai';
|
||||
import guid from '../../utils/guid';
|
||||
import { PapiForTests } from './papi-for-tests';
|
||||
import { Authentication } from './authentication';
|
||||
import { VoidAuth } from './void-auth';
|
||||
import { ApiKeyAuth } from './api-key-auth';
|
||||
import { ClaimsApiApiKeys } from './claims-api-api-keys';
|
||||
import { handleResponseError } from '../../utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class ClaimsApiForTests implements PapiForTests {
|
||||
public defaultHeaders: any = {};
|
||||
public basePath: string = '';
|
||||
public useQuerystring: boolean = false;
|
||||
|
||||
protected authentications = {
|
||||
default: <Authentication>new VoidAuth(),
|
||||
bearer: new ApiKeyAuth('header', 'Authorization')
|
||||
};
|
||||
|
||||
constructor(basePath: string) {
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
public setDefaultAuthentication(auth: Authentication) {
|
||||
this.authentications.default = auth;
|
||||
}
|
||||
|
||||
public setApiKey(key: ClaimsApiApiKeys, value: string) {
|
||||
this.authentications[ClaimsApiApiKeys[key]].apiKey = value;
|
||||
}
|
||||
|
||||
acceptClaimByIDForTests(
|
||||
partyID: string,
|
||||
claimID: number,
|
||||
claimRevision: number
|
||||
): Promise<void> {
|
||||
return this.acceptClaimByID(guid(), partyID, claimID, claimRevision)
|
||||
.then(result => {
|
||||
const response = result.response;
|
||||
response.statusCode.should.eq(200);
|
||||
return;
|
||||
})
|
||||
.catch(ex => handleResponseError(ex));
|
||||
}
|
||||
|
||||
private acceptClaimByID(
|
||||
xRequestID: string,
|
||||
partyID: string,
|
||||
claimID: number,
|
||||
claimRevision: number
|
||||
): Promise<{ response: http.ClientResponse; body?: any }> {
|
||||
const localVarPath = this.basePath + '/walk/claim/accept';
|
||||
let queryParameters: any = {};
|
||||
let headerParams: any = (<any>Object).assign({}, this.defaultHeaders);
|
||||
let formParams: any = {};
|
||||
|
||||
// verify required parameter 'xRequestID' is not null or undefined
|
||||
if (xRequestID === null || xRequestID === undefined) {
|
||||
throw new Error(
|
||||
'Required parameter xRequestID was null or undefined when calling acceptClaimByID.'
|
||||
);
|
||||
}
|
||||
|
||||
// verify required parameter 'partyID' is not null or undefined
|
||||
if (partyID === null || partyID === undefined) {
|
||||
throw new Error(
|
||||
'Required parameter partyID was null or undefined when calling acceptClaimByID.'
|
||||
);
|
||||
}
|
||||
|
||||
// verify required parameter 'claimID' is not null or undefined
|
||||
if (claimID === null || claimID === undefined) {
|
||||
throw new Error(
|
||||
'Required parameter claimID was null or undefined when calling acceptClaimByID.'
|
||||
);
|
||||
}
|
||||
|
||||
// verify required parameter 'claimRevision' is not null or undefined
|
||||
if (claimRevision === null || claimRevision === undefined) {
|
||||
throw new Error(
|
||||
'Required parameter claimRevision was null or undefined when calling acceptClaimByID.'
|
||||
);
|
||||
}
|
||||
|
||||
headerParams['X-Request-ID'] = xRequestID;
|
||||
|
||||
let useFormData = false;
|
||||
|
||||
let requestOptions: request.Options = {
|
||||
method: 'POST',
|
||||
qs: queryParameters,
|
||||
headers: headerParams,
|
||||
uri: localVarPath,
|
||||
useQuerystring: this.useQuerystring,
|
||||
json: true,
|
||||
body: {
|
||||
claimId: claimID,
|
||||
partyId: partyID,
|
||||
revision: claimRevision
|
||||
}
|
||||
};
|
||||
|
||||
this.authentications.bearer.applyToRequest(requestOptions);
|
||||
|
||||
this.authentications.default.applyToRequest(requestOptions);
|
||||
|
||||
if (Object.keys(formParams).length) {
|
||||
if (useFormData) {
|
||||
(<any>requestOptions).formData = formParams;
|
||||
} else {
|
||||
requestOptions.form = formParams;
|
||||
}
|
||||
}
|
||||
return new Promise<{ response: http.ClientResponse; body?: any }>((resolve, reject) => {
|
||||
request(requestOptions, (error, response, body) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
if (response.statusCode >= 200 && response.statusCode <= 299) {
|
||||
resolve({ response: response, body: body });
|
||||
} else {
|
||||
reject({ response: response, body: body });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
5
api/papi-v1/index.ts
Normal file
5
api/papi-v1/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './claims-api';
|
||||
export * from './payouts-api';
|
||||
export * from './payout';
|
||||
export * from './papi-factory';
|
||||
export * from './papi-for-tests';
|
21
api/papi-v1/papi-factory.ts
Normal file
21
api/papi-v1/papi-factory.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { ClaimsApiForTests, PapiForTests, PayoutsApiForTests } from '.';
|
||||
import { adminEndpoint } from '../../settings';
|
||||
|
||||
const classes = {
|
||||
ClaimsApiForTests,
|
||||
PayoutsApiForTests
|
||||
};
|
||||
|
||||
export class PapiFactory {
|
||||
public static getInstance<T extends PapiForTests>(className: string, accessToken: string): T {
|
||||
let instance = classes[className] && new classes[className]();
|
||||
if (instance) {
|
||||
instance.setApiKey(0, `Bearer ${accessToken}`);
|
||||
instance.defaultHeaders = {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
};
|
||||
instance.basePath = `${adminEndpoint}/papi/v1`;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
3
api/papi-v1/papi-for-tests.ts
Normal file
3
api/papi-v1/papi-for-tests.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export interface PapiForTests {
|
||||
defaultHeaders: any;
|
||||
}
|
9
api/papi-v1/payout.ts
Normal file
9
api/papi-v1/payout.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export class Payout {
|
||||
id: string;
|
||||
partyId: string;
|
||||
shopId: string;
|
||||
payoutType: string;
|
||||
createdAt: Date;
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
140
api/papi-v1/payouts-api.ts
Normal file
140
api/papi-v1/payouts-api.ts
Normal file
@ -0,0 +1,140 @@
|
||||
import request = require('request');
|
||||
import http = require('http');
|
||||
import { PapiForTests } from './papi-for-tests';
|
||||
import { Payout } from './payout';
|
||||
import * as chai from 'chai';
|
||||
import { Authentication } from './authentication';
|
||||
import { VoidAuth } from './void-auth';
|
||||
import { ApiKeyAuth } from './api-key-auth';
|
||||
import { ClaimsApiApiKeys } from './claims-api-api-keys';
|
||||
import { handleResponseError } from '../../utils';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class PayoutsApiForTests implements PapiForTests {
|
||||
public defaultHeaders: any = {};
|
||||
public basePath: string = '';
|
||||
public useQuerystring: boolean = false;
|
||||
|
||||
protected authentications = {
|
||||
default: <Authentication>new VoidAuth(),
|
||||
bearer: new ApiKeyAuth('header', 'Authorization')
|
||||
};
|
||||
|
||||
constructor(basePath: string) {
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
private getDefaultHeaders() {
|
||||
const headers = new Headers();
|
||||
headers.append('Content-type', 'application/json; charset=UTF-8');
|
||||
headers.append('Authorization', this.authentications.bearer.apiKey);
|
||||
return headers;
|
||||
}
|
||||
|
||||
public setDefaultAuthentication(auth: Authentication) {
|
||||
this.authentications.default = auth;
|
||||
}
|
||||
|
||||
public setApiKey(key: ClaimsApiApiKeys, value: string) {
|
||||
this.authentications[ClaimsApiApiKeys[key]].apiKey = value;
|
||||
}
|
||||
|
||||
public pay(payoutIds: string[]) {
|
||||
const params = {
|
||||
method: 'POST',
|
||||
headers: this.getDefaultHeaders(),
|
||||
body: JSON.stringify({ payoutIds })
|
||||
};
|
||||
return fetch(`${this.basePath}/payouts/pay`, params)
|
||||
.then(response => {
|
||||
if (response.status === 200) {
|
||||
return response;
|
||||
} else {
|
||||
return handleResponseError(response);
|
||||
}
|
||||
})
|
||||
.catch(ex => handleResponseError(ex));
|
||||
}
|
||||
|
||||
public confirmPayouts(payoutIds: string[]) {
|
||||
const params = {
|
||||
method: 'POST',
|
||||
headers: this.getDefaultHeaders(),
|
||||
body: JSON.stringify({ payoutIds })
|
||||
};
|
||||
return fetch(`${this.basePath}/payouts/confirm`, params)
|
||||
.then(response => {
|
||||
if (response.status === 200) {
|
||||
return response;
|
||||
} else {
|
||||
return handleResponseError(response);
|
||||
}
|
||||
})
|
||||
.catch(ex => handleResponseError(ex));
|
||||
}
|
||||
|
||||
public searchPayoutsForTests(fromTime?: Date, toTime?: Date): Promise<Payout[]> {
|
||||
return this.searchPayouts(fromTime, toTime)
|
||||
.then(http => {
|
||||
const response = http.response;
|
||||
response.statusCode.should.eq(200);
|
||||
return http.body.payouts;
|
||||
})
|
||||
.catch(ex => handleResponseError(ex));
|
||||
}
|
||||
|
||||
public searchPayouts(
|
||||
fromTime?: Date,
|
||||
toTime?: Date
|
||||
): Promise<{ response: http.ClientResponse; body: any }> {
|
||||
const localVarPath = this.basePath + '/payouts';
|
||||
let queryParameters: any = {};
|
||||
let headerParams: any = (<any>Object).assign({}, this.defaultHeaders);
|
||||
let formParams: any = {};
|
||||
|
||||
if (fromTime !== undefined) {
|
||||
queryParameters['fromTime'] = fromTime;
|
||||
}
|
||||
|
||||
if (toTime !== undefined) {
|
||||
queryParameters['toTime'] = toTime;
|
||||
}
|
||||
|
||||
let useFormData = false;
|
||||
|
||||
let requestOptions: request.Options = {
|
||||
method: 'GET',
|
||||
qs: queryParameters,
|
||||
headers: headerParams,
|
||||
uri: localVarPath,
|
||||
useQuerystring: this.useQuerystring,
|
||||
json: true
|
||||
};
|
||||
|
||||
this.authentications.bearer.applyToRequest(requestOptions);
|
||||
|
||||
this.authentications.default.applyToRequest(requestOptions);
|
||||
|
||||
if (Object.keys(formParams).length) {
|
||||
if (useFormData) {
|
||||
(<any>requestOptions).formData = formParams;
|
||||
} else {
|
||||
requestOptions.form = formParams;
|
||||
}
|
||||
}
|
||||
return new Promise<{ response: http.ClientResponse; body: any }>((resolve, reject) => {
|
||||
request(requestOptions, (error, response, body) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
if (response.statusCode >= 200 && response.statusCode <= 299) {
|
||||
resolve({ response: response, body: body });
|
||||
} else {
|
||||
reject({ response: response, body: body });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
11
api/papi-v1/void-auth.ts
Normal file
11
api/papi-v1/void-auth.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import request = require('request');
|
||||
import { Authentication } from './authentication';
|
||||
|
||||
export class VoidAuth implements Authentication {
|
||||
public username: string;
|
||||
public password: string;
|
||||
|
||||
applyToRequest(_: request.Options): void {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
29
api/proxy-api.ts
Normal file
29
api/proxy-api.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import guid from '../utils/guid';
|
||||
import * as request from 'request';
|
||||
import { proxyEndpoint } from '../settings';
|
||||
|
||||
export class ProxyApiForTests {
|
||||
constructor(private accessToken: string) {}
|
||||
|
||||
public payTerminalPayment(spid: string, amount: number): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const params = this.defaultParams(spid, amount);
|
||||
request.get(params, (err, response) =>
|
||||
response.body.indexOf('ERR_CD=0') !== -1 ? resolve() : reject('ERR_CD !== 0')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private defaultParams(spid: string, amount: number) {
|
||||
return {
|
||||
url: `${proxyEndpoint}/agent/api/payment?VERSION=2.01&DSTACNT_NR=${spid}&ACT_CD=1&TR_AMT=${amount /
|
||||
100}.00&CUR_CD=643&TR_NR=123`,
|
||||
json: true,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8',
|
||||
Authorization: `Bearer ${this.accessToken}`,
|
||||
'X-Request-ID': guid()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
1
api/url-shortener-v1/index.ts
Normal file
1
api/url-shortener-v1/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './short-urls';
|
38
api/url-shortener-v1/short-urls.ts
Normal file
38
api/url-shortener-v1/short-urls.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import * as chai from 'chai';
|
||||
import guid from '../../utils/guid';
|
||||
import { urlShortenerEndpoint } from '../../settings';
|
||||
import { ShortenerApiFp, ShortenedUrl } from './codegen';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class ShortUrls {
|
||||
private defaultOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
}
|
||||
};
|
||||
|
||||
private basePath = `${urlShortenerEndpoint}/v1`;
|
||||
|
||||
private api;
|
||||
|
||||
constructor(accessToken: string) {
|
||||
this.api = ShortenerApiFp({
|
||||
apiKey: `Bearer ${accessToken}`
|
||||
});
|
||||
}
|
||||
|
||||
shortenUrl(sourceUrl: string, expiresAt: any): Promise<ShortenedUrl> {
|
||||
return this.api.shortenUrl(guid(), { sourceUrl, expiresAt }, this.defaultOptions)(
|
||||
undefined,
|
||||
this.basePath
|
||||
);
|
||||
}
|
||||
|
||||
deleteShortenedUrl(id: string): Promise<void> {
|
||||
return this.api.deleteShortenedUrl(guid(), id, this.defaultOptions)(
|
||||
undefined,
|
||||
this.basePath
|
||||
);
|
||||
}
|
||||
}
|
35
api/wapi-v0/payres/params/payres-params.ts
Normal file
35
api/wapi-v0/payres/params/payres-params.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { BankCard } from '../codegen';
|
||||
import {
|
||||
BankCardDestinationResource,
|
||||
Destination,
|
||||
DestinationResource
|
||||
} from '../../wallet/codegen';
|
||||
import BankCardType = BankCard.TypeEnum;
|
||||
|
||||
import DestinationResourceType = DestinationResource.TypeEnum;
|
||||
|
||||
export function getBankCardParams(): BankCard {
|
||||
return {
|
||||
type: BankCardType.BankCard,
|
||||
cardNumber: '4242424242424242',
|
||||
expDate: '12/21',
|
||||
cardHolder: 'LEXA SVOTIN',
|
||||
cvv: '123'
|
||||
};
|
||||
}
|
||||
|
||||
export function getDestinationParams(
|
||||
identity: string,
|
||||
destinationResource: BankCardDestinationResource
|
||||
): Destination {
|
||||
const resource = {
|
||||
type: DestinationResourceType.BankCardDestinationResource,
|
||||
token: destinationResource.token
|
||||
};
|
||||
return {
|
||||
name: 'Test destination',
|
||||
identity,
|
||||
currency: 'RUB',
|
||||
resource
|
||||
};
|
||||
}
|
39
api/wapi-v0/privdoc/params/privdoc-params.ts
Normal file
39
api/wapi-v0/privdoc/params/privdoc-params.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import {
|
||||
PrivateDocument,
|
||||
RUSDomesticPassportData,
|
||||
RUSRetireeInsuranceCertificateData,
|
||||
SecuredPrivateDocument
|
||||
} from '../codegen';
|
||||
import PrivateDocumentType = PrivateDocument.TypeEnum;
|
||||
import { IdentityChallenge } from '../../wallet/codegen';
|
||||
import ric from '../../../../utils/ric-generator';
|
||||
|
||||
export function getPassportParams(): RUSDomesticPassportData {
|
||||
return {
|
||||
type: PrivateDocumentType.RUSDomesticPassportData,
|
||||
series: '4567',
|
||||
number: '123456',
|
||||
issuer: 'Отделение УФМС России по Кемеровской области в Юргинском районе',
|
||||
issuerCode: '666-777',
|
||||
issuedAt: '2018-11-28',
|
||||
familyName: 'Иванов',
|
||||
firstName: 'Иван',
|
||||
patronymic: 'Иванович',
|
||||
birthDate: '2018-11-28',
|
||||
birthPlace: 'дер. Белянино'
|
||||
};
|
||||
}
|
||||
|
||||
export function getRICParams(): RUSRetireeInsuranceCertificateData {
|
||||
return {
|
||||
type: PrivateDocumentType.RUSRetireeInsuranceCertificateData,
|
||||
number: ric()
|
||||
};
|
||||
}
|
||||
|
||||
export function getIdentityChallengeParams(proofs: SecuredPrivateDocument[]): IdentityChallenge {
|
||||
return {
|
||||
type: 'esia',
|
||||
proofs
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { Identity } from '../../codegen';
|
||||
|
||||
export function getSimpleIdentityParams(
|
||||
name: string = 'Test Name',
|
||||
provider: string = 'test',
|
||||
_class: string = 'person'
|
||||
): Identity {
|
||||
return {
|
||||
name,
|
||||
provider,
|
||||
class: _class
|
||||
} as any;
|
||||
}
|
18
api/wapi-v0/wallet/params/wallets-params/grant-params.ts
Normal file
18
api/wapi-v0/wallet/params/wallets-params/grant-params.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { DestinationGrantRequest, WalletGrantRequest } from '../../codegen';
|
||||
import moment = require('moment');
|
||||
|
||||
export function getWalletGrantParams(): WalletGrantRequest {
|
||||
return {
|
||||
asset: {
|
||||
amount: 1000,
|
||||
currency: 'RUB'
|
||||
},
|
||||
validUntil: new Date(moment.now() + 24 * 60 * 60 * 1000)
|
||||
};
|
||||
}
|
||||
|
||||
export function getWithdrawalGrantParams(): DestinationGrantRequest {
|
||||
return {
|
||||
validUntil: new Date(moment.now() + 24 * 60 * 60 * 1000)
|
||||
};
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import { Wallet } from '../../codegen';
|
||||
|
||||
export function getSimpleWalletParams(identity: string, name: string, currency: string): Wallet {
|
||||
return {
|
||||
name,
|
||||
identity,
|
||||
currency
|
||||
};
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import { WithdrawalBody, WithdrawalParameters } from '../../codegen';
|
||||
|
||||
export function getWithdrawalParams(
|
||||
wallet: string,
|
||||
destination: string,
|
||||
body: WithdrawalBody,
|
||||
externalID?: string
|
||||
): WithdrawalParameters {
|
||||
return {
|
||||
wallet,
|
||||
destination,
|
||||
body,
|
||||
externalID
|
||||
};
|
||||
}
|
3
conditions/index.ts
Normal file
3
conditions/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './payment-conditions';
|
||||
export * from './shop-conditions';
|
||||
export * from './refund-conditions';
|
71
conditions/payment-conditions.ts
Normal file
71
conditions/payment-conditions.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { TokensActions, PaymentsActions, InvoicesActions } from '../actions/capi-v2';
|
||||
import {
|
||||
InvoicesEventActions,
|
||||
isInvoicePaid,
|
||||
isPaymentCaptured
|
||||
} from '../actions/capi-v2/invoice-event-actions';
|
||||
import { AuthActions } from '../actions';
|
||||
import { InvoiceAndToken, PaymentResource } from '../api/capi-v2/codegen/api';
|
||||
|
||||
export interface InstantPaymentProceedResult {
|
||||
invoiceID: string;
|
||||
paymentID: string;
|
||||
}
|
||||
|
||||
export class PaymentConditions {
|
||||
private invoiceActions: InvoicesActions;
|
||||
private paymentsActions: PaymentsActions;
|
||||
private invoiceEventActions: InvoicesEventActions;
|
||||
private static instance: PaymentConditions;
|
||||
|
||||
static async getInstance(): Promise<PaymentConditions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new PaymentConditions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
private constructor(token: string) {
|
||||
this.invoiceActions = new InvoicesActions(token);
|
||||
this.paymentsActions = new PaymentsActions(token);
|
||||
this.invoiceEventActions = new InvoicesEventActions(token);
|
||||
}
|
||||
|
||||
async proceedInstantPayment(
|
||||
shopID: string,
|
||||
amount: number = 10000
|
||||
): Promise<InstantPaymentProceedResult> {
|
||||
const invoiceAndToken = await this.invoiceActions.createSimpleInvoice(shopID, amount);
|
||||
const invoiceAccessToken = invoiceAndToken.invoiceAccessToken.payload;
|
||||
const tokensActions = new TokensActions(invoiceAccessToken);
|
||||
const paymentResource = await tokensActions.createSaneVisaPaymentResource();
|
||||
return this.proceedInstantPaymentExtend(amount, paymentResource, invoiceAndToken);
|
||||
}
|
||||
|
||||
async proceedInstantPaymentExtend(
|
||||
amount: number,
|
||||
paymentResource: PaymentResource,
|
||||
invoiceAndToken: InvoiceAndToken,
|
||||
externalID?: string,
|
||||
metadata?: object
|
||||
): Promise<InstantPaymentProceedResult> {
|
||||
const invoiceID = invoiceAndToken.invoice.id;
|
||||
const { id } = await this.paymentsActions.createInstantPayment(
|
||||
invoiceID,
|
||||
paymentResource,
|
||||
amount,
|
||||
externalID,
|
||||
metadata
|
||||
);
|
||||
await this.invoiceEventActions.waitConditions(
|
||||
[isInvoicePaid(), isPaymentCaptured(id)],
|
||||
invoiceID
|
||||
);
|
||||
return {
|
||||
invoiceID,
|
||||
paymentID: id
|
||||
};
|
||||
}
|
||||
}
|
35
conditions/refund-conditions.ts
Normal file
35
conditions/refund-conditions.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import * as chai from 'chai';
|
||||
import { LogicError, Refund, RefundParams } from '../api/capi-v2/codegen';
|
||||
import { InvoicesEventActions, isRefundSucceeded, PaymentsActions } from '../actions/capi-v2';
|
||||
import { AuthActions } from '../actions';
|
||||
|
||||
chai.should();
|
||||
|
||||
export class RefundConditions {
|
||||
private paymentsActions: PaymentsActions;
|
||||
private invoiceEventActions: InvoicesEventActions;
|
||||
|
||||
private static instance: RefundConditions;
|
||||
|
||||
static async getInstance(): Promise<RefundConditions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const token = await AuthActions.getInstance().getExternalAccessToken();
|
||||
this.instance = new RefundConditions(token);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
private constructor(token: string) {
|
||||
this.paymentsActions = new PaymentsActions(token);
|
||||
this.invoiceEventActions = new InvoicesEventActions(token);
|
||||
}
|
||||
async provideRefund(invoiceID: string, paymentID: string, params: RefundParams) {
|
||||
const refund = await this.paymentsActions.createRefund(invoiceID, paymentID, params);
|
||||
refund.should.have.property('amount').to.equal(params.amount);
|
||||
await this.invoiceEventActions.waitConditions(
|
||||
[isRefundSucceeded(paymentID, refund.id)],
|
||||
invoiceID
|
||||
);
|
||||
}
|
||||
}
|
64
conditions/shop-conditions.ts
Normal file
64
conditions/shop-conditions.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { ClaimsActions, PartiesActions, ShopsActions } from '../actions/capi-v2';
|
||||
import { Shop } from '../api/capi-v2/codegen';
|
||||
import guid from '../utils/guid';
|
||||
import { PapiClaimsActions } from '../actions/papi-v1';
|
||||
import { AuthActions } from '../actions';
|
||||
|
||||
export class ShopConditions {
|
||||
private static instance: ShopConditions;
|
||||
private claimsActions: ClaimsActions;
|
||||
private partiesActions: PartiesActions;
|
||||
private shopsActions: ShopsActions;
|
||||
private papiClaimsActions: PapiClaimsActions;
|
||||
|
||||
static async getInstance(): Promise<ShopConditions> {
|
||||
if (this.instance) {
|
||||
return this.instance;
|
||||
}
|
||||
const authActions = AuthActions.getInstance();
|
||||
const exToken = await authActions.getExternalAccessToken();
|
||||
const inToken = await authActions.getInternalAccessToken();
|
||||
this.instance = new ShopConditions(exToken, inToken);
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor(externalToken: string, internalToken: string) {
|
||||
this.claimsActions = new ClaimsActions(externalToken);
|
||||
this.partiesActions = new PartiesActions(externalToken);
|
||||
this.shopsActions = new ShopsActions(externalToken);
|
||||
this.papiClaimsActions = new PapiClaimsActions(internalToken);
|
||||
}
|
||||
|
||||
async createShops(count: number): Promise<Shop[]> {
|
||||
const container = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
container.push(this.createShop());
|
||||
}
|
||||
return await Promise.all(container);
|
||||
}
|
||||
|
||||
async createShop(): Promise<Shop> {
|
||||
const party = await this.partiesActions.getActiveParty();
|
||||
const shopID = guid();
|
||||
const claim = await this.claimsActions.createClaimForLiveShop(shopID);
|
||||
await this.papiClaimsActions.acceptClaimByID(party.id, claim.id, 1);
|
||||
return await this.shopsActions.getShopByID(shopID);
|
||||
}
|
||||
|
||||
async createShopWithPayoutSchedule(scheduleID = 1): Promise<Shop> {
|
||||
const shop = await this.createShop();
|
||||
const claim = await this.claimsActions.createClaimForLiveShopWithSchedule(
|
||||
shop.id,
|
||||
scheduleID
|
||||
);
|
||||
const party = await this.partiesActions.getActiveParty();
|
||||
await this.papiClaimsActions.acceptClaimByID(party.id, claim.id, 1);
|
||||
return shop;
|
||||
}
|
||||
|
||||
async turnOffPayoutSchedule(shopID: string) {
|
||||
const claim = await this.claimsActions.createClaimForLiveShopWithSchedule(shopID);
|
||||
const party = await this.partiesActions.getActiveParty();
|
||||
await this.papiClaimsActions.acceptClaimByID(party.id, claim.id, 1);
|
||||
}
|
||||
}
|
2
lib/chai-moment-js/.gitignore
vendored
Normal file
2
lib/chai-moment-js/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
.idea/
|
1
lib/chai-moment-js/.npmignore
Normal file
1
lib/chai-moment-js/.npmignore
Normal file
@ -0,0 +1 @@
|
||||
.idea/
|
11
lib/chai-moment-js/LICENSE.md
Normal file
11
lib/chai-moment-js/LICENSE.md
Normal file
@ -0,0 +1,11 @@
|
||||
Copyright (c) 2017 Phil Gates-Shannon
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
169
lib/chai-moment-js/README.md
Normal file
169
lib/chai-moment-js/README.md
Normal file
@ -0,0 +1,169 @@
|
||||
# Chai MomentJS
|
||||
|
||||
**Chai MomentJS** is a plugin for the [Chai][1] assertion library that provides date/time comparisons. It is a wrapper for some of the query functions in the [MomentJS][2] date library. Use **Chai MomentJS** to write fluent BDD/TDD tests and get useful error messages.
|
||||
|
||||
In other words, _don't_ do this:
|
||||
|
||||
```javascript
|
||||
expect( moment( '2016-12-31' ).isSame( '2017-01-01' ) ).to.be.true;
|
||||
// => "expected false to be true"
|
||||
```
|
||||
|
||||
Do this instead:
|
||||
|
||||
```javascript
|
||||
expect( moment('2016-12-31') ).is.same.moment( '2017-01-01' );
|
||||
// => "expected 2016-12-31 00:00:00 to be 2017-01-01 00:00:00"
|
||||
```
|
||||
|
||||
[1]: http://chaijs.com/
|
||||
[2]: https://momentjs.com/
|
||||
|
||||
## Usage
|
||||
|
||||
Include the plugin as normal:
|
||||
|
||||
```javascript
|
||||
let chai = require( 'chai' );
|
||||
let chaiMoment = require( 'chai-moment-js' );
|
||||
|
||||
chai.use( chaiMoment );
|
||||
let expect = chai.expect;
|
||||
```
|
||||
|
||||
### Test Methods
|
||||
|
||||
**Chai MomentJS** provides two methods that can used to compare dates: `moment` and `betweenMoments`.
|
||||
|
||||
#### moment( date, [accuracy] )
|
||||
|
||||
In the default usage, `moment` is a wrapper for the MomentJS's [`isSame`][3] query function. (See "Flags" below for how to change behavior from the default.) It has one required argument, `date`, which can be either a a native JavaScript Date object or a Moment object from MomentJS. The optional argument, `accuracy`, specifies the accuracy of the comparison. You can use any of the vales recognized by MomentJS's [`startOf`][4] function, but the most common ones are:
|
||||
|
||||
- second
|
||||
- minute
|
||||
- hour
|
||||
- day
|
||||
- month
|
||||
- year
|
||||
|
||||
You can use them like this:
|
||||
|
||||
```javascript
|
||||
let m0 = moment( 1487070166000 );
|
||||
let m1 = moment( 1487070166773 );
|
||||
expect( m1 ).is.same.moment( m0 ); // => false
|
||||
expect( m1 ).is.same.moment( m0, 'second' ); // => true
|
||||
```
|
||||
|
||||
[3]: https://momentjs.com/docs/#/query/is-same/
|
||||
[4]: https://momentjs.com/docs/#/manipulating/start-of/
|
||||
|
||||
#### betweenMoments( start, end, [accuracy], [inclusivity] )
|
||||
|
||||
This is a wrapper for MomentJS's [`isBetween`][5] query function. It requires `start` and `end` arguments, which may be either a Date or a Moment. The `accuracy` parameters functions as in the `moment` function; it will accept `null` for millisecond accuracy.
|
||||
|
||||
Finally, the `inclusivity` parameter determines whether to return true or false if the object-under-test matches the `start` or `end` argument. Basically, a parenthesis excludes an exact match (returns false) while a square bracket includes an exact match (returns true). The default is to exclude on exact matches.
|
||||
|
||||
The following table explains inclusivity in more concrete terms:
|
||||
|
||||
| argument | result of exact match on `start` | result of exact match on `end` |
|
||||
| --- | --- | --- |
|
||||
| '()' | `false` | `false` |
|
||||
| '[]' | `true` | `true` |
|
||||
| '(]' | `false` | `true` |
|
||||
| '[)' | `true` | `false` |
|
||||
|
||||
The meaning of "exact match" is determined by the `accuracy` parameter.
|
||||
|
||||
Some examples:
|
||||
|
||||
```javascript
|
||||
let m0 = moment( 1487070166000 );
|
||||
let m1 = moment( 1487070166500 );
|
||||
let m2 = moment( 1487070166773 );
|
||||
expect( m1 ).is.betweenMoments( m0, m2 ); // => true
|
||||
expect( m1 ).is.betweenMoments( m0, m2, 'second' ); // => false
|
||||
expect( m1 ).is.betweenMoments( m0, m2, 'second', '[]' ); // => true
|
||||
expect( m0 ).is.betweenMoments( m0, m2 ); // => false
|
||||
expect( m0 ).is.betweenMoments( m0, m2, null, '[)' ); // => true
|
||||
expect( m0 ).is.betweenMoments( m0, m2, null, '(]' ); // => false
|
||||
expect( m2 ).is.betweenMoments( m0, m2, null, '[)' ); // => false
|
||||
expect( m2 ).is.betweenMoments( m0, m2, null, '(]' ); // => true
|
||||
```
|
||||
|
||||
[5]: https://momentjs.com/docs/#/query/is-between/
|
||||
|
||||
### Flags
|
||||
|
||||
These flags change the behavior of the `moment` comparison function. This allows you to write fluent TDD/BDD statements like `expect( fileDate ).is.before.moment( myDate )`.
|
||||
|
||||
Don't combine flags. That's bad, like crossing-the-streams bad.
|
||||
|
||||
#### before
|
||||
|
||||
The **before** flag tells **Chai MomentJS** to use MomentJS's [`isBefore`][6] query function.
|
||||
|
||||
```javascript
|
||||
let m0 = moment( 1487070166000 );
|
||||
let m1 = moment( 1487070166773 );
|
||||
expect( m0 ).is.before.moment( m1 ); // => true
|
||||
expect( m0 ).is.before.moment( m1, 'second' ); // => false
|
||||
```
|
||||
|
||||
[6]: https://momentjs.com/docs/#/query/is-before/
|
||||
|
||||
#### after
|
||||
|
||||
The **after** flag tells **Chai MomentJS** to use MomentJS's [`isAfter`][7] query function.
|
||||
|
||||
```javascript
|
||||
let m0 = moment( 1487070166000 );
|
||||
let m1 = moment( 1487070166773 );
|
||||
expect( m1 ).is.after.moment( m0 ); // => true
|
||||
expect( m1 ).is.after.moment( m0, 'second' ); // => false
|
||||
```
|
||||
|
||||
[7]: https://momentjs.com/docs/#/query/is-after/
|
||||
|
||||
#### sameOrBefore
|
||||
|
||||
The **sameOrBefore** flag tells **Chai MomentJS** to use MomentJS's [`isSameOrBefore`][8] query function.
|
||||
|
||||
```javascript
|
||||
let m0 = moment( 1487070166000 );
|
||||
let m1 = moment( 1487070166773 );
|
||||
expect( m0 ).is.sameOrBefore.moment( m1 ); // => true
|
||||
expect( m0 ).is.sameOrBefore.moment( m1, 'second' ); // => true
|
||||
```
|
||||
|
||||
[8]: https://momentjs.com/docs/#/query/is-same-or-before/
|
||||
|
||||
#### sameOrAfter
|
||||
|
||||
The **sameOrAfter** flag tells **Chai MomentJS** to use MomentJS's [`isSameOrAfter`][9] query function.
|
||||
|
||||
```javascript
|
||||
let m0 = moment( 1487070166000 );
|
||||
let m1 = moment( 1487070166773 );
|
||||
expect( m1 ).is.sameOrAfter.moment( m0 ); // => true
|
||||
expect( m1 ).is.sameOrAfter.moment( m0, 'second' ); // => true
|
||||
```
|
||||
|
||||
[9]: https://momentjs.com/docs/#/query/is-same-or-after/
|
||||
|
||||
## Thanks
|
||||
|
||||
Thanks to:
|
||||
|
||||
- @mguterl for [chai-datetime][3], which inspired this plugin.
|
||||
- @fastfrwrd for [chai-moment][10], which I didn't know about until I got a name collision upon running `npm publish`!
|
||||
|
||||
[3]: https://github.com/mguterl/chai-datetime
|
||||
[10]: https://www.npmjs.com/package/chai-moment
|
||||
|
||||
## License
|
||||
|
||||
The content of this repository is licensed under the [3-Clause BSD license][4]. Please see the enclosed [license file][5] for specific terms.
|
||||
|
||||
[4]: https://opensource.org/licenses/BSD-3-Clause
|
||||
[5]: https://github.com/philgs/chai-moment/blob/release/LICENSE.md
|
20
lib/chai-moment-js/index.d.ts
vendored
Normal file
20
lib/chai-moment-js/index.d.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/// <reference types="chai" />
|
||||
|
||||
declare global {
|
||||
|
||||
export namespace Chai {
|
||||
|
||||
interface Assertion extends LanguageChains, NumericComparison, TypeComparison {
|
||||
after:Assertion;
|
||||
before:Assertion;
|
||||
sameOrAfter:Assertion;
|
||||
sameOrBefore:Assertion;
|
||||
betweenMoments( start:any, end:any, specificity?:string, inclusivity?:string ):Assertion;
|
||||
moment( timestamp:any, specificity?:string ):Assertion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare function chaiMoment( chai: any, utils: any ): void;
|
||||
declare namespace chaiMoment { }
|
||||
export = chaiMoment;
|
173
lib/chai-moment-js/index.js
Normal file
173
lib/chai-moment-js/index.js
Normal file
@ -0,0 +1,173 @@
|
||||
let moment = require( 'moment' );
|
||||
let _ = require( 'lodash' ); // TODO Only require necessary modules
|
||||
|
||||
const AFTER = 'after';
|
||||
const BEFORE = 'before';
|
||||
const BETWEEN = 'betweenMoments';
|
||||
const MOMENT = 'moment';
|
||||
const SAME_OR_AFTER = 'sameOrAfter';
|
||||
const SAME_OR_BEFORE = 'sameOrBefore';
|
||||
|
||||
let ensureMoment = function( date ) {
|
||||
return moment.isMoment( date ) ? date : moment( date )
|
||||
};
|
||||
|
||||
let errorMessages = {
|
||||
getBadDate: function( value ) {
|
||||
return `AssertionError: expected ${value} to be a Date or Moment, but `
|
||||
+ `it is a ${typeof value}: expected false to be true`
|
||||
},
|
||||
|
||||
getBetweenError: function( actual, start, end ) {
|
||||
let format = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
|
||||
actual = ensureMoment( actual ).format( format );
|
||||
start = ensureMoment( start ).format( format );
|
||||
end = ensureMoment( end ).format( format );
|
||||
|
||||
return [
|
||||
`expected ${actual} to be between ${start} and ${end}`,
|
||||
`expected ${actual} to not be between ${start} and ${end}`,
|
||||
actual,
|
||||
start + ' <---> ' + end
|
||||
];
|
||||
},
|
||||
|
||||
getChainableError: function( name ) {
|
||||
return 'Chainable property "' + name + '" can only be used in a chain, '
|
||||
+ 'NOT to check a value';
|
||||
},
|
||||
|
||||
getComparisonError: function( actual, expected, comparisonPhrase ) {
|
||||
let format = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
|
||||
let act = ensureMoment( actual ).format( format );
|
||||
let exp = ensureMoment( expected ).format( format );
|
||||
|
||||
return [
|
||||
`expected ${act} to be ${comparisonPhrase} ${exp}`,
|
||||
`expected ${act} to not be ${comparisonPhrase} ${exp}`,
|
||||
act,
|
||||
exp
|
||||
];
|
||||
},
|
||||
|
||||
noFlagsForBetween: 'No flags can be used with the `betweenMoments` comparison.'
|
||||
};
|
||||
|
||||
let namespace = function( name ) {
|
||||
const ns = 'moment';
|
||||
return ns + '.' + name;
|
||||
};
|
||||
|
||||
let chainableError = function( name ) {
|
||||
return function() {
|
||||
throw new Error( errorMessages.getChainableError( name ) );
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function( chai, utils ) {
|
||||
let Assertion = chai.Assertion;
|
||||
|
||||
Assertion.addChainableMethod( AFTER, chainableError( AFTER ), function() {
|
||||
utils.flag( this, namespace( AFTER ), true );
|
||||
} );
|
||||
|
||||
Assertion.addChainableMethod( BEFORE, chainableError( BEFORE ), function() {
|
||||
utils.flag( this, namespace( BEFORE ), true );
|
||||
} );
|
||||
|
||||
Assertion.addChainableMethod( SAME_OR_AFTER, chainableError( SAME_OR_AFTER ), function() {
|
||||
utils.flag( this, namespace( SAME_OR_AFTER ), true );
|
||||
} );
|
||||
|
||||
Assertion.addChainableMethod( SAME_OR_BEFORE, chainableError( SAME_OR_BEFORE ), function() {
|
||||
utils.flag( this, namespace( SAME_OR_BEFORE ), true );
|
||||
} );
|
||||
|
||||
Assertion.addMethod( BETWEEN, function( start, end, accuracy, inclusivity ) {
|
||||
// I said, NO FLAGS ALLOWED!
|
||||
if ( utils.flag( this, namespace( AFTER ) )
|
||||
|| utils.flag( this, namespace( BEFORE ) )
|
||||
|| utils.flag( this, namespace( SAME_OR_AFTER ) )
|
||||
|| utils.flag( this, namespace( SAME_OR_BEFORE ) ) ) {
|
||||
throw new Error( errorMessages.noFlagsForBetween );
|
||||
}
|
||||
|
||||
// Do this check independent of `this` so it is not affect by flags
|
||||
new Assertion(
|
||||
moment.isDate( start ) || moment.isMoment( start ),
|
||||
errorMessages.getBadDate( start )
|
||||
).is.true;
|
||||
new Assertion(
|
||||
moment.isDate( end ) || moment.isMoment( end ),
|
||||
errorMessages.getBadDate( end )
|
||||
).is.true;
|
||||
|
||||
// Make sure that we have Moment objects
|
||||
let obj = ensureMoment( this._obj );
|
||||
start = ensureMoment( start );
|
||||
end = ensureMoment( end );
|
||||
|
||||
// Use a curried function, so we don't type the args to `this.assert` every time
|
||||
let compareThisTo = null;
|
||||
if ( inclusivity ) {
|
||||
compareThisTo = _.curry( obj.isBetween.bind( obj ), 4 )( _, _, accuracy, inclusivity );
|
||||
} else if ( accuracy ) {
|
||||
compareThisTo = _.curry( obj.isBetween.bind( obj ), 3 )( _, _, accuracy );
|
||||
} else {
|
||||
compareThisTo = _.curry( obj.isBetween.bind( obj ), 2 )( _, _ );
|
||||
}
|
||||
|
||||
// Do the comparison
|
||||
let [ positive, negative, actual, expected ] = errorMessages
|
||||
.getBetweenError( obj, start, end );
|
||||
this.assert( compareThisTo( start, end )
|
||||
, positive, negative, expected, actual, true );
|
||||
} );
|
||||
|
||||
Assertion.addMethod( MOMENT, function( timestamp, accuracy ) {
|
||||
// Do this check independent of `this` so it is not affect by flags
|
||||
new Assertion(
|
||||
moment.isDate( timestamp ) || moment.isMoment( timestamp ),
|
||||
errorMessages.getBadDate( timestamp )
|
||||
).is.true;
|
||||
|
||||
// Make sure that we have Moment objects
|
||||
let obj = ensureMoment( this._obj );
|
||||
timestamp = ensureMoment( timestamp );
|
||||
|
||||
// Determine the comparator function and message based on flags
|
||||
let comparatorFn = obj.isSame.bind( obj ); // default comparator
|
||||
let comparatorMsg = 'the same as';
|
||||
if ( utils.flag( this, namespace( AFTER ) ) ) {
|
||||
comparatorFn = obj.isAfter.bind( obj );
|
||||
comparatorMsg = 'after';
|
||||
}
|
||||
if ( utils.flag( this, namespace( BEFORE ) ) ) {
|
||||
comparatorFn = obj.isBefore.bind( obj );
|
||||
comparatorMsg = 'before';
|
||||
}
|
||||
if ( utils.flag( this, namespace( SAME_OR_AFTER ) ) ) {
|
||||
comparatorFn = obj.isSameOrAfter.bind( obj );
|
||||
comparatorMsg = 'same or after';
|
||||
}
|
||||
if ( utils.flag( this, namespace( SAME_OR_BEFORE ) ) ) {
|
||||
comparatorFn = obj.isSameOrBefore.bind( obj );
|
||||
comparatorMsg = 'same or before';
|
||||
}
|
||||
|
||||
// Create a curried comparison function, to reduce redundancy
|
||||
let compareThisTo = null;
|
||||
if ( accuracy ) {
|
||||
compareThisTo = _.curry( comparatorFn, 2 )( _, accuracy );
|
||||
} else {
|
||||
compareThisTo = _.curry( comparatorFn, 1 );
|
||||
}
|
||||
|
||||
// Do the comparison
|
||||
let [ positive, negative, actual, expected ] = errorMessages
|
||||
.getComparisonError( obj, timestamp, comparatorMsg );
|
||||
this.assert( compareThisTo( timestamp ), positive, negative, expected, actual, true );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports.messages = errorMessages;
|
32
lib/chai-moment-js/package.json
Normal file
32
lib/chai-moment-js/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "chai-moment-js",
|
||||
"version": "1.0.0",
|
||||
"description": "Date/time comparisons in Chai with MomentJS",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"scripts": {
|
||||
"test": "mocha --reporter spec"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/philgs/chai-moment-js.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "Phil Gates-Shannon",
|
||||
"email": "phil.gs@gmail.com",
|
||||
"url": "http://philgs.me"
|
||||
},
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.4",
|
||||
"moment": "^2.17.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chai": ">1.10.0 <4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^3.5.0",
|
||||
"dirty-chai": "^1.2.2",
|
||||
"mocha": "^4.0.1"
|
||||
}
|
||||
}
|
30
lib/chai-url/index.d.ts
vendored
Normal file
30
lib/chai-url/index.d.ts
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// Type definitions for chai-url
|
||||
|
||||
/// <reference types="chai" />
|
||||
|
||||
declare function chaiUrl(chai: any, utils: any): void;
|
||||
export = chaiUrl;
|
||||
|
||||
declare global {
|
||||
namespace Chai {
|
||||
interface Assertion {
|
||||
path(path: string): Assertion;
|
||||
pathname(pathname: string): Assertion;
|
||||
port(port: string): Assertion;
|
||||
hostname(hostname: string): Assertion;
|
||||
protocol(protocol: string): Assertion;
|
||||
auth(auth: string): Assertion;
|
||||
hash(hash: string): Assertion;
|
||||
}
|
||||
|
||||
interface Assert {
|
||||
path(val: string, exp: string, msg?: string): void;
|
||||
pathname(val: string, exp: string, msg?: string): void;
|
||||
port(val: string, exp: string, msg?: string): void;
|
||||
hostname(val: string, exp: string, msg?: string): void;
|
||||
protocol(val: string, exp: string, msg?: string): void;
|
||||
auth(val: string, exp: string, msg?: string): void;
|
||||
hash(val: string, exp: string, msg?: string): void;
|
||||
}
|
||||
}
|
||||
}
|
74
mocha-tests.js
Normal file
74
mocha-tests.js
Normal file
@ -0,0 +1,74 @@
|
||||
const Mocha = require('mocha');
|
||||
const path = require('path');
|
||||
const glob = require('glob');
|
||||
|
||||
const argv = require('yargs')
|
||||
.usage('Usage: $0 [options]')
|
||||
.describe('auth-endpoint', 'Auth endpoint')
|
||||
.describe('external-login', 'Auth external realm login')
|
||||
.describe('external-password', 'Auth external realm password')
|
||||
.describe('internal-login', 'Auth internal realm login')
|
||||
.describe('internal-password', 'Auth internal realm password')
|
||||
.describe('capi-endpoint', 'Common API endpoint')
|
||||
.describe('admin-endpoint', 'IDDQD endpoint')
|
||||
.describe('proxy-endpoint', 'Proxy endpoint')
|
||||
.describe('url-shortener-endpoint', 'URL Shortener API endpoint')
|
||||
.describe('test-webhook-receiver-endpoint', 'Test webhook receiver endpoint')
|
||||
.describe('file', 'include a file to be ran during the suite [filepath]')
|
||||
.describe('slow', '"slow" test threshold in ms')
|
||||
.describe('timeout', 'Set test-case timeout in ms')
|
||||
.describe('tt', 'Test transaction flag')
|
||||
.describe('test-dir', 'Path to directory containng tests')
|
||||
.describe('auth-warn', 'Auth flow warn threshold in ms')
|
||||
.describe('create-invoice-warn', 'Create invoice warn threshold in ms')
|
||||
.describe('create-payment-resource-warn', 'Create payment resource warn threshold in ms')
|
||||
.describe('create-payment-warn', 'Create payment warn threshold in ms')
|
||||
.describe('polling-warn', 'Polling payment and invoice events warn threshold in ms')
|
||||
.describe('fulfill-invoice-warn', 'Fulfill invoice warn threshold in ms')
|
||||
.describe('test-shop-id', 'Test shopID for test transaction')
|
||||
.describe('create-test-shop', 'Create test shop if not found')
|
||||
.default({
|
||||
timeout: 30000,
|
||||
slow: 150,
|
||||
'auth-warn': 200,
|
||||
'create-invoice-warn': 200,
|
||||
'create-payment-resource-warn': 200,
|
||||
'create-payment-warn': 200,
|
||||
'polling-warn': 5000,
|
||||
'fulfill-invoice-warn': 100,
|
||||
'test-shop-id': 'TEST',
|
||||
'create-test-shop': true,
|
||||
'test-dir': './build/test'
|
||||
})
|
||||
.demandOption([
|
||||
'auth-endpoint',
|
||||
'external-login',
|
||||
'external-password',
|
||||
'internal-login',
|
||||
'internal-password',
|
||||
'capi-endpoint',
|
||||
'admin-endpoint',
|
||||
'proxy-endpoint',
|
||||
'url-shortener-endpoint',
|
||||
'test-webhook-receiver-endpoint'
|
||||
]).argv;
|
||||
|
||||
const mocha = new Mocha({
|
||||
timeout: argv.timeout,
|
||||
slow: argv.slow
|
||||
});
|
||||
|
||||
const testDir = argv['test-dir'];
|
||||
const integrationTestFile = 'transaction.spec.js';
|
||||
|
||||
if (argv.file) {
|
||||
mocha.addFile(path.resolve(argv.file));
|
||||
} else {
|
||||
glob.sync('**/*.js', { cwd: testDir })
|
||||
.filter(file => (argv.tt ? file === integrationTestFile : file !== integrationTestFile))
|
||||
.forEach(file => mocha.addFile(path.resolve(testDir, file)));
|
||||
}
|
||||
|
||||
mocha
|
||||
.reporter(argv.tt ? 'min' : 'spec')
|
||||
.run(code => (argv.tt ? process.exit(code === 1 ? 3 : code) : process.exit(code)));
|
4227
package-lock.json
generated
Normal file
4227
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
43
package.json
Normal file
43
package.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "wetkitty-integration-tests",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/rbkmoney/wetkitty.git"
|
||||
},
|
||||
"scripts": {
|
||||
"prettier": "prettier \"**/*.{js,ts,md,json,prettierrc}\" --write",
|
||||
"check": "prettier \"**/*.{js,ts,md,json,prettierrc}\" --list-different"
|
||||
},
|
||||
"author": "",
|
||||
"dependencies": {
|
||||
"chai": "4.1.2",
|
||||
"chai-moment-js": "file:lib/chai-moment-js",
|
||||
"chai-url": "1.0.4",
|
||||
"glob": "7.1.2",
|
||||
"http": "0.0.0",
|
||||
"lodash": "^4.17.15",
|
||||
"memory-cache": "0.2.0",
|
||||
"mocha": "4.0.1",
|
||||
"moment": "^2.24.0",
|
||||
"pkg": "4.3.0-beta.5",
|
||||
"portable-fetch": "3.0.0",
|
||||
"request": "2.83.0",
|
||||
"url": "0.11.0",
|
||||
"yargs": "10.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.0.5",
|
||||
"@types/memory-cache": "0.2.0",
|
||||
"@types/mocha": "2.2.44",
|
||||
"@types/node": "8.0.53",
|
||||
"@types/request": "^2.48.3",
|
||||
"dotenv": "5.0.1",
|
||||
"prettier": "1.16.4",
|
||||
"rimraf": "2.6.2",
|
||||
"ts-node": "5.0.1",
|
||||
"typescript": "2.6.1"
|
||||
}
|
||||
}
|
21
settings.ts
Normal file
21
settings.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import * as yargs from 'yargs';
|
||||
require('dotenv').config();
|
||||
|
||||
export const authEndpoint = yargs.argv['auth-endpoint'] || process.env.AUTH_ENDPOINT;
|
||||
export const capiEndpoint = yargs.argv['capi-endpoint'] || process.env.CAPI_ENDPOINT;
|
||||
export const adminEndpoint = yargs.argv['admin-endpoint'] || process.env.ADMIN_ENDPOINT;
|
||||
export const proxyEndpoint = yargs.argv['proxy-endpoint'] || process.env.PROXY_ENDPOINT;
|
||||
export const urlShortenerEndpoint =
|
||||
yargs.argv['url-shortener-endpoint'] || process.env.URL_SHORTENER_ENDPOINT;
|
||||
export const externalLogin = yargs.argv['external-login'] || process.env.EXTERNAL_LOGIN;
|
||||
export const externalPassword = yargs.argv['external-password'] || process.env.EXTERNAL_PASSWORD;
|
||||
export const internalLogin = yargs.argv['internal-login'] || process.env.INTERNAL_LOGIN;
|
||||
export const internalPassword = yargs.argv['internal-password'] || process.env.INTERNAL_PASSWORD;
|
||||
export const wapiEndpoint = capiEndpoint + '/wallet';
|
||||
export const privdocEndpoint = capiEndpoint + '/privdoc';
|
||||
export const payresEndpoint = capiEndpoint + '/payres';
|
||||
export const anapiEndpoint = capiEndpoint + '/lk';
|
||||
export const binapiEndpoint = capiEndpoint + '/binbase';
|
||||
export const testWebhookReceiverInternal = 'http://test-webhook-receiver:8080';
|
||||
export const testWebhookReceiverEndpoint =
|
||||
yargs.argv['test-webhook-receiver-endpoint'] || process.env.TEST_WEBHOOK_RECEIVER_ENDPOINT;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user