mirror of
https://github.com/valitydev/tokenizer.js.git
synced 2024-11-06 01:25:23 +00:00
FE-219: support access token (#19)
* FE-219: Removed sample. Seperated provoder and tokenizer parts. * FE-219: Added webpack. Updated build image tag. Added init with cache. * FE-219: Added access token support.
This commit is contained in:
parent
7a08accac7
commit
3195d8a360
4
.babelrc
4
.babelrc
@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"presets": ["es2015"]
|
"presets": [
|
||||||
|
["es2015", { "modules": false }]
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
2
Makefile
2
Makefile
@ -15,7 +15,7 @@ SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG)
|
|||||||
BASE_IMAGE_NAME := service-fe
|
BASE_IMAGE_NAME := service-fe
|
||||||
BASE_IMAGE_TAG := a58a828755e9d342ecbd7071e7dc224ffe546378
|
BASE_IMAGE_TAG := a58a828755e9d342ecbd7071e7dc224ffe546378
|
||||||
|
|
||||||
BUILD_IMAGE_TAG := 6fb209e428feaa0ef6cec07d3909d8a3c4013537
|
BUILD_IMAGE_TAG := 629911df323f69e08de05aea7491b0a91cf4722e
|
||||||
|
|
||||||
CALL_W_CONTAINER := init build clean submodules
|
CALL_W_CONTAINER := init build clean submodules
|
||||||
|
|
||||||
|
36
README.md
36
README.md
@ -1,28 +1,38 @@
|
|||||||
# Tokenizer.js
|
# Tokenizer
|
||||||
[![Build Status](http://ci.rbkmoney.com/buildStatus/icon?job=rbkmoney_private/tokenizer.js/master)](http://ci.rbkmoney.com/job/rbkmoney_private/job/tokenizer.js/job/master)
|
[![Build Status](http://ci.rbkmoney.com/buildStatus/icon?job=rbkmoney_private/tokenizer.js/master)](http://ci.rbkmoney.com/job/rbkmoney_private/job/tokenizer.js/job/master)
|
||||||
|
|
||||||
JavaScript библиотека для токенизации карточных данных клиентов.
|
JavaScript библиотека для токенизации карточных данных клиентов.
|
||||||
|
|
||||||
## Настройка
|
## Настройка
|
||||||
Конфигурация происходит в файле [appConfig.json](/src/appConfig.json)
|
Конфигурация происходит в файле [tokenizerConfig.json](/src/tokenizerConfig.json)
|
||||||
Для изменения конфигурации в рантайме достаточно заменить `appConfig.json`
|
Для изменения конфигурации в рантайме достаточно заменить `tokenizerConfig.json`.
|
||||||
Например в случае с nginx `appConfig.json` нужно положить в `/usr/share/nginx/html`
|
Например в случае с nginx `tokenizerConfig.json` нужно положить в `/usr/share/nginx/html`
|
||||||
|
|
||||||
## Установка
|
## Установка
|
||||||
Для загрузки зависимостей выполнить:
|
Загрузка зивисимостей:
|
||||||
|
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
Сборка библиотеки:
|
Сборка библиотеки:
|
||||||
|
|
||||||
gulp
|
npm run build
|
||||||
|
|
||||||
Разработка / запуск примера:
|
Режим разработки:
|
||||||
|
|
||||||
gulp develop
|
|
||||||
|
|
||||||
Библиотека будет доступна по адресу: http://localhost:7000/
|
|
||||||
Пример будет доступен по адресу: http://localhost:7001/
|
|
||||||
|
|
||||||
|
npm start
|
||||||
|
|
||||||
## Использование
|
## Использование
|
||||||
Пример использования можно посмотреть [тут](/sample/index.html)
|
```javascript
|
||||||
|
Tokenizer.setAccessToken('<invoice access token>');
|
||||||
|
Tokenizer.card.createToken({
|
||||||
|
paymentToolType: 'CardData',
|
||||||
|
cardHolder: '<card holder>',
|
||||||
|
cardNumber: '<card number>',
|
||||||
|
expDate: '<exp date>',
|
||||||
|
cvv: '<cvv>'
|
||||||
|
}, (token) => {
|
||||||
|
console.log(token); // { token: 'string', session: 'string' }
|
||||||
|
}, (error) => {
|
||||||
|
console.error(error); // { code: 'string', message: 'string' }
|
||||||
|
});
|
||||||
|
```
|
||||||
|
10
config/helpers.js
Normal file
10
config/helpers.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const _root = path.resolve(__dirname, '..');
|
||||||
|
|
||||||
|
function root(args) {
|
||||||
|
args = Array.prototype.slice.call(arguments, 0);
|
||||||
|
return path.join.apply(path, [_root].concat(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.root = root;
|
36
config/webpack.common.js
Normal file
36
config/webpack.common.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const helpers = require('./helpers');
|
||||||
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: {
|
||||||
|
tokenizer: './src/tokenizer.js',
|
||||||
|
tokenizerProvider: './src/tokenizerProvider.js'
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
modules: [
|
||||||
|
path.join(__dirname, 'src'),
|
||||||
|
'node_modules'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: ['babel-loader', 'eslint-loader'],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new CopyWebpackPlugin([{
|
||||||
|
from: './src/rpc/provider.html'
|
||||||
|
}, {
|
||||||
|
from: './src/tokenizerConfig.json'
|
||||||
|
}])
|
||||||
|
],
|
||||||
|
output: {
|
||||||
|
path: helpers.root('dist'),
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
};
|
9
config/webpack.dev.js
Normal file
9
config/webpack.dev.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const webpackMerge = require('webpack-merge');
|
||||||
|
const commonConfig = require('./webpack.common.js');
|
||||||
|
|
||||||
|
module.exports = webpackMerge(commonConfig, {
|
||||||
|
devtool: 'eval-source-map',
|
||||||
|
devServer: {
|
||||||
|
stats: 'minimal'
|
||||||
|
}
|
||||||
|
});
|
26
config/webpack.prod.js
Normal file
26
config/webpack.prod.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
|
const webpackMerge = require('webpack-merge');
|
||||||
|
const commonConfig = require('./webpack.common.js');
|
||||||
|
|
||||||
|
module.exports = webpackMerge(commonConfig, {
|
||||||
|
plugins: [
|
||||||
|
new webpack.LoaderOptionsPlugin({
|
||||||
|
minimize: true,
|
||||||
|
debug: false
|
||||||
|
}),
|
||||||
|
new webpack.optimize.UglifyJsPlugin({
|
||||||
|
compress: {
|
||||||
|
warnings: false,
|
||||||
|
screw_ie8: true,
|
||||||
|
conditionals: true,
|
||||||
|
unused: true,
|
||||||
|
comparisons: true,
|
||||||
|
sequences: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
@ -1,76 +0,0 @@
|
|||||||
import gulp from 'gulp';
|
|
||||||
import browserify from 'browserify';
|
|
||||||
import babelify from 'babelify';
|
|
||||||
import source from 'vinyl-source-stream';
|
|
||||||
import uglify from 'gulp-uglify';
|
|
||||||
import rename from 'gulp-rename';
|
|
||||||
import connect from 'gulp-connect';
|
|
||||||
import eslint from 'gulp-eslint';
|
|
||||||
import karma from 'karma';
|
|
||||||
import cors from 'cors';
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
dist: 'dist'
|
|
||||||
};
|
|
||||||
|
|
||||||
gulp.task('lint', () => {
|
|
||||||
return gulp.src('src/**/*.js')
|
|
||||||
.pipe(eslint())
|
|
||||||
.pipe(eslint.format());
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('browserify', ['lint'], () => {
|
|
||||||
return browserify({
|
|
||||||
entries: 'src/bootstrap.js',
|
|
||||||
extensions: ['.js'],
|
|
||||||
debug: true
|
|
||||||
}).transform('babelify').bundle()
|
|
||||||
.pipe(source('tokenizer.js'))
|
|
||||||
.pipe(gulp.dest(config.dist));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('uglify', ['browserify'], () => {
|
|
||||||
return gulp.src(`${config.dist}/tokenizer.js`)
|
|
||||||
.pipe(rename('tokenizer.min.js'))
|
|
||||||
.pipe(uglify())
|
|
||||||
.pipe(gulp.dest(config.dist));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('copyStatic', () => {
|
|
||||||
return gulp.src(['src/rpc/provider.html', 'src/tokenizerConfig.json'])
|
|
||||||
.pipe(gulp.dest(config.dist));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('test', done => {
|
|
||||||
const KarmaServer = karma.Server;
|
|
||||||
new KarmaServer({
|
|
||||||
configFile: `${__dirname}/karma.conf.js`
|
|
||||||
}, done).start();
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('connectDist', () => {
|
|
||||||
connect.server({
|
|
||||||
root: 'dist',
|
|
||||||
middleware: function() {
|
|
||||||
return [cors()];
|
|
||||||
},
|
|
||||||
host: '127.0.0.1',
|
|
||||||
port: 7000
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('connectSample', () => {
|
|
||||||
connect.server({
|
|
||||||
root: 'sample',
|
|
||||||
host: '127.0.0.1',
|
|
||||||
port: 7001
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('watch', () => {
|
|
||||||
gulp.watch('src/**/*', ['build', 'copyStatic']);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build', ['uglify', 'copyStatic']);
|
|
||||||
gulp.task('develop', ['build', 'connectDist', 'watch', 'connectSample']);
|
|
||||||
gulp.task('default', ['build']);
|
|
@ -1,17 +0,0 @@
|
|||||||
module.exports = function (config) {
|
|
||||||
config.set({
|
|
||||||
frameworks: ['mocha', 'browserify'],
|
|
||||||
browsers: ['Chrome'],
|
|
||||||
files: [
|
|
||||||
'tests/**/*.test.js'
|
|
||||||
],
|
|
||||||
preprocessors: {
|
|
||||||
'tests/**/*.test.js': [ 'browserify' ]
|
|
||||||
},
|
|
||||||
reporters: ['mocha'],
|
|
||||||
browserify: {
|
|
||||||
debug: true,
|
|
||||||
transform: [ 'babelify' ]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
36
package.json
36
package.json
@ -1,36 +1,30 @@
|
|||||||
{
|
{
|
||||||
"name": "tokenizer.js",
|
"name": "Tokenizer",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
|
"private": true,
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/rbkmoney/tokenizer.js.git"
|
"url": "git+https://github.com/rbkmoney/tokenizer.js.git"
|
||||||
},
|
},
|
||||||
"author": "rbkmoney",
|
"author": "rbkmoney",
|
||||||
|
"licenses": [],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "gulp build"
|
"start": "webpack-dev-server --config config/webpack.dev.js --inline --progress --port 7000",
|
||||||
|
"build": "rimraf dist && webpack --config config/webpack.prod.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.23.1",
|
||||||
|
"babel-loader": "^6.3.2",
|
||||||
"babel-preset-es2015": "^6.9.0",
|
"babel-preset-es2015": "^6.9.0",
|
||||||
"babel-register": "^6.11.6",
|
"copy-webpack-plugin": "^4.0.1",
|
||||||
"babelify": "^7.3.0",
|
"eslint": "^3.16.1",
|
||||||
"browserify": "^13.0.1",
|
"eslint-loader": "^1.6.3",
|
||||||
"chai": "^3.5.0",
|
"path": "^0.12.7",
|
||||||
"cors": "^2.8.1",
|
"rimraf": "^2.6.1",
|
||||||
"gulp": "^3.9.1",
|
"webpack": "^2.2.1",
|
||||||
"gulp-connect": "^5.0.0",
|
"webpack-dev-server": "^2.4.1",
|
||||||
"gulp-eslint": "^3.0.1",
|
"webpack-merge": "^3.0.0"
|
||||||
"gulp-rename": "^1.2.2",
|
|
||||||
"gulp-uglify": "^1.5.4",
|
|
||||||
"karma": "^1.2.0",
|
|
||||||
"karma-browserify": "^5.1.0",
|
|
||||||
"karma-chrome-launcher": "^1.0.1",
|
|
||||||
"karma-mocha": "^1.1.1",
|
|
||||||
"karma-mocha-reporter": "^2.1.0",
|
|
||||||
"karma-phantomjs-launcher": "^1.0.1",
|
|
||||||
"mocha": "^3.0.2",
|
|
||||||
"vinyl-source-stream": "^1.1.0",
|
|
||||||
"watchify": "^3.7.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fingerprintjs2": "^1.4.1",
|
"fingerprintjs2": "^1.4.1",
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Tokenization sample</title>
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
|
|
||||||
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
|
||||||
<script src="https://code.jquery.com/jquery-3.1.0.slim.min.js"
|
|
||||||
integrity="sha256-cRpWjoSOw5KcyIOaZNo4i6fZ9tKPhYYb6i5T9RSVJG8=" crossorigin="anonymous"></script>
|
|
||||||
|
|
||||||
<script type="application/javascript" src="http://localhost:7000/tokenizer/tokenizer.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function () {
|
|
||||||
$('#request-result').hide();
|
|
||||||
$('#pay-button').click(function () {
|
|
||||||
Tokenizer.setPublicKey('eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJUdEZzelc3NDB2NTQ1MThVUVg1MGNnczN1U2pCSXkxbDdGcDVyMHdmYzFrIn0.eyJqdGkiOiJjODBhZjlmYi0yNzY5LTQ2YWItOTg4NC0wZWQ0YTVmMjRiOTYiLCJleHAiOjAsIm5iZiI6MCwiaWF0IjoxNDc1MTMxNjAwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjMxMjQ1L2F1dGgvcmVhbG1zL2V4dGVybmFsIiwiYXVkIjoidG9rZW5pemVyIiwic3ViIjoiNGQxMmQyMTMtZWU1ZS00ZWEzLTg2YTYtMDc5ZjZkNDM3NWExIiwidHlwIjoiT2ZmbGluZSIsImF6cCI6InRva2VuaXplciIsIm5vbmNlIjoiMGUzYTU2ZmQtZGUxNy00NTI1LTgxNmYtNjM1YTEzNWJlYTYwIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNDU3MWE0NjQtYmRjYi00YTkyLTg2ZjQtYWI5YjExYzgyNjE5IiwiY2xpZW50X3Nlc3Npb24iOiI0OTU1MWE3ZC04NGNiLTQxZTUtOTQ2OC0wZmQ3ZDg5ZGYxZmUiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiXX0sInJlc291cmNlX2FjY2VzcyI6eyJjb21tb24tYXBpIjp7InJvbGVzIjpbInBheW1lbnRfdG9vbF90b2tlbnM6Y3JlYXRlIl19fX0.ZayOtPaUNxDfBZh_t8IfTUNOJ8653v2lkNX3pDBEyQV28EGf8qbIFJRtA7LbGwdd8brhRIWLk2XBco7RZUX_GYVHIlRo0IvGAzyLYozjXWdfZHaTkChCpk6QnTCTgYeFxTMbgtYYBXOS7oT0tmQZY-N3O0cuIeBItGU8lzaNqfwH9i61WETZKkHYQ_wL28Kbip9IDSgxqDUWnohDA3ee5QROiw-J0DU8MmEkKBSC4owPkYQTFCJr4A69_3hsXArSh3xYu6gkbHoS3CWXMPMtbpFrSrZG191aRwV9ZQIouzd5jKsk6IRiPVhAWSWayd44qRYTgugMX3Tz06O1hOXkDg');
|
|
||||||
Tokenizer.card.createToken({
|
|
||||||
"paymentToolType": "cardData",
|
|
||||||
"cardHolder": $('#card-holder').val(),
|
|
||||||
"cardNumber": $('#card-number').val(),
|
|
||||||
"expDate": $('#exp-date').val(),
|
|
||||||
"cvv": $('#cvv').val()
|
|
||||||
}, function (result) {
|
|
||||||
$('#request-result').removeClass('alert-danger').addClass('alert-success').show().text(JSON.stringify(result));
|
|
||||||
}, function (error) {
|
|
||||||
$('#request-result').removeClass('alert-success').addClass('alert-danger').show().text(JSON.stringify(error.message));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container" style="padding-top: 150px">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3"></div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<form>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Card holder</label>
|
|
||||||
<input id="card-holder" class="form-control" placeholder="card holder" value="Test Holder">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Card number</label>
|
|
||||||
<input id="card-number" class="form-control" placeholder="card number" value="4242424242424242">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label>Exp date</label>
|
|
||||||
<input id="exp-date" class="form-control" placeholder="exp date" value="03/17">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label>CVV</label>
|
|
||||||
<input id="cvv" class="form-control" placeholder="cvv" value="638">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button id="pay-button" type="button" class="btn btn-success">Pay</button>
|
|
||||||
</form>
|
|
||||||
<div class="alert" style="margin-top: 30px" id="request-result"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
36
src/bootstrap.js
vendored
36
src/bootstrap.js
vendored
@ -1,36 +0,0 @@
|
|||||||
import 'whatwg-fetch';
|
|
||||||
import RpcProvider from './rpc/RpcProvider';
|
|
||||||
import RpcConsumer from './rpc/RpcConsumer';
|
|
||||||
import ClientInfo from './clientInfo/ClientInfo';
|
|
||||||
import Utils from './utils/Utils';
|
|
||||||
import includes from './polyfills/includes';
|
|
||||||
|
|
||||||
(function init() {
|
|
||||||
includes();
|
|
||||||
const host = Utils.getScriptUrl();
|
|
||||||
if (host.includes(this.location.host)) {
|
|
||||||
new RpcProvider();
|
|
||||||
} else {
|
|
||||||
const clientInfo = new ClientInfo();
|
|
||||||
const rpc = new RpcConsumer(host);
|
|
||||||
let publicKey;
|
|
||||||
this.Tokenizer = {
|
|
||||||
setPublicKey: key => (publicKey = key),
|
|
||||||
card: {
|
|
||||||
createToken: (cardData, success, error) => {
|
|
||||||
if (publicKey) {
|
|
||||||
const request = {
|
|
||||||
paymentTool: cardData,
|
|
||||||
clientInfo: clientInfo.getInfo()
|
|
||||||
};
|
|
||||||
rpc.createToken(publicKey, request, success, error);
|
|
||||||
} else {
|
|
||||||
error({
|
|
||||||
message: 'Public key required'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}).call(window || {});
|
|
@ -1,12 +1,9 @@
|
|||||||
import 'whatwg-fetch';
|
import 'whatwg-fetch';
|
||||||
import Utils from '../utils/Utils';
|
|
||||||
|
|
||||||
export default class ConfigLoader {
|
export default class ConfigLoader {
|
||||||
static load() {
|
static load() {
|
||||||
const scriptUrl = Utils.getScriptUrl();
|
|
||||||
const appConfigUrl = Utils.getOrigin(scriptUrl);
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fetch(`${appConfigUrl}/tokenizerConfig.json`, {
|
fetch('tokenizerConfig.json', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
export default function () {
|
|
||||||
if (!String.prototype.includes) {
|
|
||||||
String.prototype.includes = function () {
|
|
||||||
return String.prototype.indexOf.apply(this, arguments) !== -1;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,10 @@
|
|||||||
/* global easyXDM:true */
|
/* global easyXDM:true */
|
||||||
import 'madlib-shim-easyxdm';
|
import 'madlib-shim-easyxdm';
|
||||||
import Utils from '../utils/Utils';
|
|
||||||
|
|
||||||
export default class {
|
export default class {
|
||||||
constructor(host) {
|
constructor(providerEndpoint) {
|
||||||
const url = Utils.getOrigin(host);
|
|
||||||
return new easyXDM.Rpc({
|
return new easyXDM.Rpc({
|
||||||
remote: `${url}/provider.html`
|
remote: `${providerEndpoint}/provider.html`
|
||||||
}, {
|
}, {
|
||||||
remote: {
|
remote: {
|
||||||
createToken: {}
|
createToken: {}
|
||||||
|
@ -5,6 +5,6 @@
|
|||||||
<title>Provider</title>
|
<title>Provider</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="application/javascript" src="tokenizer.min.js"></script>
|
<script type="application/javascript" src="tokenizerProvider.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
25
src/tokenizer.js
Normal file
25
src/tokenizer.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import RpcConsumer from './rpc/RpcConsumer';
|
||||||
|
import ClientInfo from './clientInfo/ClientInfo';
|
||||||
|
import getOrigin from './utils/getOrigin';
|
||||||
|
|
||||||
|
(function init() {
|
||||||
|
const clientInfo = new ClientInfo();
|
||||||
|
const consumer = new RpcConsumer(getOrigin());
|
||||||
|
let accessToken;
|
||||||
|
this.Tokenizer = {
|
||||||
|
setAccessToken: token => (accessToken = token),
|
||||||
|
card: {
|
||||||
|
createToken: (cardData, success, error) => {
|
||||||
|
if (accessToken) {
|
||||||
|
const request = {
|
||||||
|
paymentTool: cardData,
|
||||||
|
clientInfo: clientInfo.getInfo()
|
||||||
|
};
|
||||||
|
consumer.createToken(accessToken, request, success, error);
|
||||||
|
} else {
|
||||||
|
error({ message: 'Access token required' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}).call(window || {});
|
@ -1,4 +1,3 @@
|
|||||||
{
|
{
|
||||||
"capiUrl": "http://localhost:7051",
|
"capiEndpoint": "https://api.rbk.test:8080"
|
||||||
"keycloakUrl": "http://localhost:8080/auth"
|
|
||||||
}
|
}
|
5
src/tokenizerProvider.js
Normal file
5
src/tokenizerProvider.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import RpcProvider from './rpc/RpcProvider';
|
||||||
|
|
||||||
|
(function init() {
|
||||||
|
new RpcProvider();
|
||||||
|
}).call(window || {});
|
@ -1,44 +1,25 @@
|
|||||||
import 'whatwg-fetch';
|
import 'whatwg-fetch';
|
||||||
import ConfigLoader from '../loaders/ConfigLoader';
|
import ConfigLoader from '../loaders/ConfigLoader';
|
||||||
|
import generateGuid from '../utils/generateGuid';
|
||||||
|
|
||||||
export default class CardTokenizer {
|
export default class CardTokenizer {
|
||||||
static createToken(key, cardData, success, error) {
|
static createToken(accessToken, cardData, success, error) {
|
||||||
ConfigLoader.load().then(config => {
|
ConfigLoader.load().then(config => {
|
||||||
CardTokenizer.refreshToken(key, config.keycloakUrl)
|
CardTokenizer.tokenize(accessToken, cardData, config.capiEndpoint)
|
||||||
.then(keycloakRes => CardTokenizer.tokenize(keycloakRes.access_token, cardData, config.capiUrl)
|
.then(capiRes => success(capiRes))
|
||||||
.then(capiRes => success(capiRes))
|
.catch(cause => error(cause));
|
||||||
.catch(cause => error(cause)))
|
|
||||||
.catch(cause => error(cause))
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static refreshToken(key, keycloakUrl) {
|
static tokenize(accessToken, cardData, capiEndpoint) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fetch(`${keycloakUrl}/realms/external/protocol/openid-connect/token`, {
|
fetch(`${capiEndpoint}/v1/processing/payment_tools`, {
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
body: `grant_type=refresh_token&client_id=tokenizer&refresh_token=${key}`
|
|
||||||
}).then(response => {
|
|
||||||
if (response.status >= 200 && response.status < 300) {
|
|
||||||
resolve(response.json());
|
|
||||||
} else {
|
|
||||||
reject(response);
|
|
||||||
}
|
|
||||||
}).catch(() => reject('Error request to keycloak'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static tokenize(token, cardData, capiUrl) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fetch(`${capiUrl}/processing/payment_tools`, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json; charset=utf-8',
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
'X-Request-ID': this.guid(),
|
'X-Request-ID': generateGuid(),
|
||||||
'Authorization': `Bearer ${token}`,
|
'Authorization': `Bearer ${accessToken}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(cardData)
|
body: JSON.stringify(cardData)
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
@ -47,14 +28,7 @@ export default class CardTokenizer {
|
|||||||
} else {
|
} else {
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
}).catch(() => reject('Error request to CAPI'));
|
}).catch(() => reject('Error request to api'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static guid() {
|
|
||||||
function s4() {
|
|
||||||
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
|
|
||||||
}
|
|
||||||
return `${s4()}${s4()}-${s4()}-${s4()}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
export default class Utils {
|
|
||||||
static getScriptUrl() {
|
|
||||||
const scripts = document.getElementsByTagName('script');
|
|
||||||
const element = scripts[scripts.length - 1];
|
|
||||||
return element.src;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getOrigin(url) {
|
|
||||||
const parser = document.createElement('a');
|
|
||||||
parser.href = url;
|
|
||||||
return parser.origin;
|
|
||||||
}
|
|
||||||
}
|
|
9
src/utils/generateGuid.js
Normal file
9
src/utils/generateGuid.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
function s4() {
|
||||||
|
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function guid() {
|
||||||
|
return `${s4()}${s4()}-${s4()}-${s4()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default guid;
|
13
src/utils/getOrigin.js
Normal file
13
src/utils/getOrigin.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
function getScriptUrl() {
|
||||||
|
const scripts = document.getElementsByTagName('script');
|
||||||
|
const element = scripts[scripts.length - 1];
|
||||||
|
return element.src;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOrigin() {
|
||||||
|
const parser = document.createElement('a');
|
||||||
|
parser.href = getScriptUrl();
|
||||||
|
return parser.origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getOrigin;
|
@ -1,14 +0,0 @@
|
|||||||
import chai from 'chai';
|
|
||||||
import ClientInfo from '../src/clientInfo/ClientInfo'
|
|
||||||
chai.should();
|
|
||||||
|
|
||||||
describe('Client info', () => {
|
|
||||||
const clientInfo = new ClientInfo();
|
|
||||||
|
|
||||||
describe('getInfo', () => {
|
|
||||||
it('fingerprint should match regexp', () => {
|
|
||||||
const info = clientInfo.getInfo();
|
|
||||||
info.fingerprint.should.match(/^[0-9a-f]{32}$/i);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in New Issue
Block a user