import axios from 'axios'; import config from '../config'; import * as crypto from 'crypto'; import * as _ from 'lodash'; import * as qs from 'querystring'; import * as genPass from 'password-generator'; const clientID = config.SOLAR_STAFF_CLIENT_ID; const apiUrl = config.SOLAR_STAFF_API_URL; const apiSalt = config.SOLAR_STAFF_SALT; declare class Error { public name: string; public message: string; public stack: string; constructor(message?: string); } class NotFoundError extends Error { private status = 404; constructor(public message: string) { super(message); this.name = 'NotFoundError'; this.message = message; this.stack = (new Error()).stack; } toString() { return this.name + ': ' + this.message; } } export enum CardStatuses { INITIALIZED = 1, NEED_APPROVEMENT = 2, LINKED = 4, BLOCKED = 5, REJECTED = 6, } export enum Currencies { RUSSIAN_RUBLE = 'RUB', AMERICAN_DOLLAR = 'USD', EURO = 'EURO', } export enum Specializations { WEB_DESIGNER = 1, PROGRAMMER = 2, SEO_SPECIALIST = 3, ACCOUNTANT = 4, WEB_DEVELOPER = 5, ARTIST = 6, CLERK = 7, WEBMASTER = 8, VIDEO_OPERATOR = 9, EDITOR = 10, PHOTOGRAPHER = 11, // ... REPAIRMAN = 401, // ремонтник } export enum Countries { RUSSIA = 'RU', } enum Paths { WORKERS = 'workers/', INFO = 'info/', PAYMENT = 'payment/', TASK = 'task/', } enum WorkerActions { CARD_VERIFY = 'card_verify', CARD_STATUS = 'card_status', CARD_REMOVE = 'card_remove', CARDS_LIST = 'cards_list', WORKER_CREATE = 'worker_create', WORKER_FIND = 'worker_find', WORKER_REMOVE = 'worker_remove', WORKER_BALANCE = 'worker_balance', WORKER_TRANSACTIONS = 'worker_transactions', WORKERS_LIST = 'workers_list', } enum InfoActions { BALANCE = 'balance', GET_EXCHANGE_RATE = 'get_exchange_rate', TRANSACTIONS = 'transactions', TRANSACTION_STATUS = 'transaction_status', } enum PaymentActions { PAYOUT = 'payout', PAYOUT_QIWI = 'payout_qiwi', PAYOUT_WEBMONEY = 'payout_webmoney', } enum TaskActions { SEARCH = 'search', CHANGE_STATUS = 'change_status', } function getSignedData(data: any): any { data.client_id = clientID; const shasum = crypto.createHash('sha1'); let paramString = _.toPairs(data).sort().map((item: any) => { return item[0] + ':' + item[1]; }).join(';'); paramString += `;${apiSalt}`; shasum.update(paramString); data.signature = shasum.digest('hex'); console.log(paramString, data.signature); return data; } export enum SendMessage{ YES = 1, NO = 0, } export interface IWorkerCreateData { email: string; password?: string; first_name: string; last_name: string; phone: string; specialization: Specializations; country: Countries; send_message: SendMessage; } export function workerCreate(worker: Partial):Promise { worker.phone = worker.phone.replace(/\D/g,''); // replace all non numeric characters worker.password = genPass(12); const data : any = worker; data.action = WorkerActions.WORKER_CREATE; return sendRequest(Paths.WORKERS, data); } export interface IWorkerSelector { email?: string; worker_id?: string; } export function checkWorkerSelector(selector: IWorkerSelector): IWorkerSelector { if (selector.worker_id != null) { return { worker_id: selector.worker_id }; } if (selector.email) { return { email: selector.email }; } throw new Error('Can not determine worker'); } export function workerRemove(workerSelector: Partial):Promise { const data: any = checkWorkerSelector(workerSelector); data.action = WorkerActions.WORKER_REMOVE; return sendRequest(Paths.WORKERS, data); } export interface ICardVerifyData { currency: Currencies; redirect_url: string; } export function cardVerify(workerSelector: Partial, cardVerifyData: ICardVerifyData):Promise { let data: any = checkWorkerSelector(workerSelector); data.action = WorkerActions.CARD_VERIFY; data = _.merge(data, cardVerifyData); return sendRequest(Paths.WORKERS, data); } export function cardStatus(workerSelector: Partial, cardId: number):Promise { const data: any = checkWorkerSelector(workerSelector); data.action = WorkerActions.CARD_STATUS; data.card_id = cardId; return sendRequest(Paths.WORKERS, data); } export function cardRemove(workerSelector: Partial, cardId: number):Promise { const data: any = checkWorkerSelector(workerSelector); data.action = WorkerActions.CARD_REMOVE; data.card_id = cardId; return sendRequest(Paths.WORKERS, data); } export interface IQiwiPayoutData { wallet_number: string; currency: Currencies; amount: number; todo_type?: number; // todo_attributes: string; // Address task_id?: number; merchant_transaction?: string; task_title?: string; task_description?: string; } export function payoutQiwi(workerSelector: Partial, qiwiPayoutData: IQiwiPayoutData):Promise { let data: any = checkWorkerSelector(workerSelector); qiwiPayoutData.wallet_number = qiwiPayoutData.wallet_number .replace(/\D/g,''); // replace all non numeric characters qiwiPayoutData.amount = Math.round(qiwiPayoutData.amount); data.action = PaymentActions.PAYOUT_QIWI; data = _.merge(data, qiwiPayoutData); return sendRequest(Paths.PAYMENT, data); } export interface IPayoutData { currency: Currencies; amount: number; card_id: string; todo_type?: number; // todo_attributes: string; // Address task_id?: number; merchant_transaction?: string; task_title?: string; task_description?: string; } export function payout(workerSelector: Partial, payoutData: IPayoutData):Promise { let data: any = checkWorkerSelector(workerSelector); data.action = PaymentActions.PAYOUT; payoutData.amount = Math.round(payoutData.amount); data = _.merge(data, payoutData); return sendRequest(Paths.PAYMENT, data); } async function sendRequest(action: string, data: any):Promise { const signedData = getSignedData(data); console.log(apiUrl + action, signedData); const response = await axios.post(apiUrl + action, qs.stringify(signedData)); if (response.data.code && response.data.code === 110) { throw new NotFoundError('Payment system API error. Object not found'); } if ( response !== null && response.data && response.data.success === true && response.data.code === 200 ) { return response.data; } throw new Error(`Payment system API error. code = ${response.data.code}, ${response.data.response.error_text}`); }