mirror of
https://github.com/janishutz/libreevent.git
synced 2025-11-25 13:24:24 +00:00
add payrexx as payment provider
This commit is contained in:
@@ -74,6 +74,10 @@ class GETHandler {
|
||||
} );
|
||||
} else if ( call === 'getCurrency' ) {
|
||||
resolve( this.settings.currency );
|
||||
} else if ( call === 'getAdminAccounts' ) {
|
||||
// TODO: Finish
|
||||
} else if ( call === 'getSettings' ) {
|
||||
resolve( this.settings );
|
||||
} else {
|
||||
reject( { 'code': 404, 'error': 'Route not found' } );
|
||||
}
|
||||
|
||||
@@ -106,6 +106,15 @@ class POSTHandler {
|
||||
} ).catch( error => {
|
||||
reject( { 'code': 500, 'error': error } );
|
||||
} );
|
||||
} else if ( call === 'createAdminAccount' ) {
|
||||
// TODO: Finish
|
||||
} else if ( call === 'updateAdminAccount' ) {
|
||||
// TODO: Finish
|
||||
} else if ( call === 'deleteAdminAccount' ) {
|
||||
// TODO: Finish
|
||||
} else if ( call === 'updateSettings' ) {
|
||||
// TODO: Finish
|
||||
// TODO: Parse all events and update currency
|
||||
} else {
|
||||
reject( { 'code': 404, 'error': 'Route not found' } );
|
||||
}
|
||||
|
||||
@@ -91,7 +91,8 @@ if ( settings.init ) {
|
||||
|
||||
console.log( '[ Server ] loading plugins' );
|
||||
// TODO: load dynamically
|
||||
require( './backend/plugins/payments/stripe/stripeRoutes.js' )( app, settings ); // stripe routes
|
||||
// require( './backend/plugins/payments/stripe/stripeRoutes.js' )( app, settings ); // stripe routes
|
||||
require( './backend/plugins/payments/payrexx/payrexxRoutes.js' )( app, settings ); // payrexx routes
|
||||
require( './backend/payments/paymentRoutes.js' )( app, settings ); // payment routes
|
||||
|
||||
app.use( ( request, response ) => {
|
||||
|
||||
@@ -17,6 +17,10 @@ module.exports = ( app, settings ) => {
|
||||
res.sendFile( path.join( __dirname + '/../../ui/en/payments/canceled.html' ) );
|
||||
} );
|
||||
|
||||
app.get( '/payments/failed', ( req, res ) => {
|
||||
res.sendFile( path.join( __dirname + '/../../ui/en/payments/failed.html' ) );
|
||||
} );
|
||||
|
||||
app.get( '/tickets/tickets.pdf', ( req, res ) => {
|
||||
if ( req.session.id ) {
|
||||
fs.readFile( path.join( __dirname + '/../tickets/store/' + req.session.id + '.pdf' ), ( error, data ) => {
|
||||
|
||||
@@ -4,28 +4,7 @@ All payment gateway integration plugins have to be in their own folders. This fo
|
||||
You will also need to add documentation for the user to set up the payment gateway. Read on below to find out how.
|
||||
|
||||
## Setting up the routes.js file
|
||||
In the routes.js file you should have at least the following code:
|
||||
|
||||
```
|
||||
module.exports = ( app, settings ) => {
|
||||
app.post( '/payments/prepare', ( req, res ) => {
|
||||
|
||||
} );
|
||||
|
||||
app.get( '/payments/status', ( request, response ) => {
|
||||
response.writeHead( 200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive',
|
||||
} );
|
||||
response.status( 200 );
|
||||
response.flushHeaders();
|
||||
response.write( 'data: connected\n\n' );
|
||||
} );
|
||||
}
|
||||
```
|
||||
|
||||
Take some inspiration of the stripe or adyen setup as these are officially supported by the system and have been developed by the original creator.
|
||||
Take some inspiration of the stripe or payrexx setup as these are officially supported by the system and have been developed by the original creator.
|
||||
|
||||
The express.js routes it has to expose are the following:
|
||||
|
||||
@@ -36,4 +15,8 @@ It can contain any number of (not interfering) routes. Please always use the /pa
|
||||
|
||||
|
||||
## The plugin.json file
|
||||
The plugin.json file should look as follows:
|
||||
The plugin.json file should look as follows:
|
||||
|
||||
## configOption.json
|
||||
This file contains the settings that should be available in the settings page of libreevent. It should contain the following fields, as required by the settings.vue module.
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* libreevent - module.payrexx.js
|
||||
*
|
||||
* Created by Janis Hutz 08/12/2023, Licensed under the GPL V3 License
|
||||
* https://janishutz.com, development@janishutz.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
const fs = require( 'fs' );
|
||||
const path = require( 'path' );
|
||||
const qs = require( 'qs' );
|
||||
const axios = require( 'axios' );
|
||||
const Base64 = require( 'crypto-js/enc-base64' );
|
||||
const hmacSHA256 = require( 'crypto-js/hmac-sha256' );
|
||||
const payrexxConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'payrexx' ];
|
||||
|
||||
const baseUrl = 'https://api.payrexx.com/v1.0/';
|
||||
const instance = payrexxConfig.instance;
|
||||
const secret = payrexxConfig.APISecret;
|
||||
|
||||
exports.init = function () {
|
||||
function buildSignature ( query = '' ) {
|
||||
return Base64.stringify( hmacSHA256( query, secret ) );
|
||||
}
|
||||
|
||||
function buildBaseUrl ( path ) {
|
||||
return baseUrl + path + '?instance=' + instance;
|
||||
}
|
||||
|
||||
return {
|
||||
getGateway: function ( id ) {
|
||||
const baseUrl = buildBaseUrl( 'Gateway/' + id + '/' );
|
||||
const url = baseUrl + '&ApiSignature=' + buildSignature();
|
||||
return axios.get( url );
|
||||
},
|
||||
createGateway: function ( params ) {
|
||||
if ( !params.amount ) {
|
||||
throw new Error( 'Amount required!' );
|
||||
}
|
||||
|
||||
const defaultParams = {
|
||||
currency: 'CHF'
|
||||
};
|
||||
|
||||
let queryParams = Object.assign( {}, defaultParams, params );
|
||||
|
||||
const queryStr = qs.stringify( queryParams, { format: 'RFC1738' } );
|
||||
const signature = buildSignature( queryStr );
|
||||
|
||||
queryParams.ApiSignature = signature;
|
||||
const queryStrSigned = qs.stringify( queryParams );
|
||||
|
||||
const baseUrl = buildBaseUrl( 'Gateway/' );
|
||||
return axios.post( baseUrl, queryStrSigned );
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* libreevent - payrexxRoutes.js
|
||||
*
|
||||
* Created by Janis Hutz 08/12/2023, Licensed under the GPL V3 License
|
||||
* https://janishutz.com, development@janishutz.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
const fs = require( 'fs' );
|
||||
const path = require( 'path' );
|
||||
const db = require( '../../../db/db.js' );
|
||||
const payrexxConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'payrexx' ];
|
||||
const bodyParser = require( 'body-parser' );
|
||||
const ticket = require( '../../../tickets/ticketGenerator.js' );
|
||||
const payrexxModule = require( './module.payrexx.js' );
|
||||
const payrexx = payrexxModule.init();
|
||||
const TicketGenerator = new ticket();
|
||||
|
||||
|
||||
let sessionReference = {};
|
||||
let waitingClients = {};
|
||||
let pendingPayments = {};
|
||||
let paymentOk = {};
|
||||
|
||||
module.exports = ( app, settings ) => {
|
||||
app.post( '/payments/prepare', bodyParser.json(), ( req, res ) => {
|
||||
if ( req.session.loggedInUser ) {
|
||||
let purchase = {
|
||||
'successRedirectUrl': settings.yourDomain + '/payments/success',
|
||||
'cancelRedirectUrl': settings.yourDomain + '/payments/canceled',
|
||||
'failedRedirectUrl': settings.yourDomain + '/payments/failed',
|
||||
'currency': settings.currency,
|
||||
'basket': [],
|
||||
'pm': payrexxConfig.paymentMethods,
|
||||
'amount': 0,
|
||||
};
|
||||
|
||||
db.getDataSimple( 'temp', 'user_id', req.session.id ).then( dat => {
|
||||
if ( dat[ 0 ] ) {
|
||||
db.getJSONData( 'events' ).then( events => {
|
||||
let data = JSON.parse( dat[ 0 ].data );
|
||||
( async () => {
|
||||
for ( let event in data ) {
|
||||
for ( let item in data[ event ] ) {
|
||||
purchase[ 'basket' ].push( {
|
||||
'name': data[ event ][ item ].name,
|
||||
'quantity': data[ event ][ item ].count ?? 1,
|
||||
'amount': Math.round( parseFloat( events[ event ][ 'categories' ][ data[ event ][ item ].category ].price[ data[ event ][ item ][ 'ticketOption' ] ] ) * 100 ),
|
||||
} );
|
||||
purchase[ 'amount' ] += Math.round( parseFloat( events[ event ][ 'categories' ][ data[ event ][ item ].category ].price[ data[ event ][ item ][ 'ticketOption' ] ] ) * 100 ) * ( data[ event ][ item ].count ?? 1 );
|
||||
}
|
||||
}
|
||||
const response = await payrexx.createGateway( purchase );
|
||||
if ( response.status === 200 ) {
|
||||
const session = response.data.data[ 0 ];
|
||||
sessionReference[ session.id ] = { 'tok': req.session.id, 'email': req.session.username };
|
||||
pendingPayments[ req.session.id ] = true;
|
||||
res.send( session.link );
|
||||
} else {
|
||||
res.status( 500 ).send( 'ERR_PAYMENT' );
|
||||
}
|
||||
} )();
|
||||
} );
|
||||
} else {
|
||||
res.status( 400 ).send( 'ERR_UID_NOT_FOUND' );
|
||||
}
|
||||
} ).catch( error => {
|
||||
console.error( '[ STRIPE ] DB ERROR: ' + error );
|
||||
res.status( 500 ).send( 'ERR_DB' );
|
||||
} );
|
||||
} else {
|
||||
res.status( 403 ).send( 'ERR_UNAUTHORIZED' );
|
||||
}
|
||||
} );
|
||||
|
||||
app.get( '/payments/status', ( request, response ) => {
|
||||
response.writeHead( 200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive',
|
||||
} );
|
||||
response.status( 200 );
|
||||
response.flushHeaders();
|
||||
response.write( 'data: connected\n\n' );
|
||||
waitingClients[ request.session.id ] = response;
|
||||
const ping = setInterval( () => {
|
||||
if ( !pendingPayments[ request.session.id ] ) {
|
||||
const stat = TicketGenerator.getGenerationStatus( request.session.id );
|
||||
if ( stat === 'done' ) {
|
||||
clearInterval( ping );
|
||||
setTimeout( () => {
|
||||
response.write( 'data: ready\n\n' );
|
||||
response.end();
|
||||
delete waitingClients[ request.session.id ];
|
||||
}, 2000 );
|
||||
} else if ( stat === 'noTicket' ) {
|
||||
clearInterval( ping );
|
||||
response.write( 'data: noData\n\n' );
|
||||
response.end();
|
||||
delete waitingClients[ request.session.id ];
|
||||
}
|
||||
}
|
||||
}, 2000 );
|
||||
} );
|
||||
|
||||
app.get( '/user/2fa/ping', ( request, response ) => {
|
||||
if ( paymentOk[ request.session.id ] === 'ok' ) {
|
||||
delete paymentOk[ request.session.id ];
|
||||
response.send( { 'status': 'paymentOk' } );
|
||||
} else {
|
||||
if ( !pendingPayments[ request.session.id ] ) {
|
||||
const stat = TicketGenerator.getGenerationStatus( request.session.id );
|
||||
if ( stat === 'done' ) {
|
||||
response.send( { 'status': 'ticketOk' } );
|
||||
} else if ( stat === 'noTicket' ) {
|
||||
response.send( { 'status': 'noTicket' } );
|
||||
} else {
|
||||
response.send( '' );
|
||||
}
|
||||
} else {
|
||||
response.send( '' );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
app.post( '/payments/webhook', bodyParser.raw( { type: 'application/json' } ), async ( req, res ) => {
|
||||
console.error( req.body );
|
||||
const response = await payrexx.getGateway( req.body.id );
|
||||
|
||||
if ( response.status === 200 ) {
|
||||
const gateway = response.data.data[ 0 ];
|
||||
|
||||
res.status( 200 ).end();
|
||||
if ( gateway.status === 'confirmed' ) {
|
||||
setTimeout( () => {
|
||||
if ( waitingClients[ sessionReference[ response.data.data[ 0 ].id ][ 'tok' ] ] ) {
|
||||
waitingClients[ sessionReference[ response.data.data[ 0 ].id ][ 'tok' ] ].write( 'data: paymentOk\n\n' );
|
||||
}
|
||||
}, 1000 );
|
||||
db.getDataSimple( 'temp', 'user_id', sessionReference[ response.data.data[ 0 ].id ][ 'tok' ] ).then( dat => {
|
||||
db.getDataSimple( 'users', 'email', sessionReference[ response.data.data[ 0 ].id ][ 'email' ] ).then( user => {
|
||||
if ( user[ 0 ] ) {
|
||||
const tickets = JSON.parse( dat[ 0 ].data );
|
||||
db.writeDataSimple( 'orders', 'account_id', user[ 0 ].account_id, { 'account_id': user[ 0 ].account_id, 'tickets': dat[ 0 ].data, 'order_name': sessionReference[ response.data.data[ 0 ].id ][ 'tok' ] } ).then( () => {
|
||||
console.log( sessionReference[ response.data.data[ 0 ].id ][ 'tok' ] );
|
||||
TicketGenerator.generateTickets( sessionReference[ response.data.data[ 0 ].id ] );
|
||||
db.getJSONData( 'booked' ).then( ret => {
|
||||
let booked = ret ?? {};
|
||||
for ( let event in tickets ) {
|
||||
if ( !booked[ String( event ) ] ) {
|
||||
booked[ String( event ) ] = {};
|
||||
}
|
||||
for ( let tik in tickets[ event ] ) {
|
||||
booked[ event ][ tik ] = tickets[ event ][ tik ];
|
||||
}
|
||||
}
|
||||
db.writeJSONData( 'booked', booked ).then( () => {
|
||||
delete pendingPayments[ sessionReference[ response.data.data[ 0 ].id ][ 'tok' ] ];
|
||||
} );
|
||||
db.deleteDataSimple( 'temp', 'user_id', sessionReference[ response.data.data[ 0 ].id ][ 'tok' ] ).catch( error => {
|
||||
console.error( '[ STRIPE ] ERROR whilst deleting data from DB: ' + error );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
} else {
|
||||
console.log( sessionReference[ response.data.data[ 0 ].id ][ 'email' ] );
|
||||
console.error( 'user not found' );
|
||||
}
|
||||
} );
|
||||
} ).catch( err => {
|
||||
console.error( err );
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
@@ -10,21 +10,19 @@
|
||||
const fs = require( 'fs' );
|
||||
const path = require( 'path' );
|
||||
const db = require( '../../../db/db.js' );
|
||||
const stripConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'stripe' ];
|
||||
const stripe = require( 'stripe' )( stripConfig[ 'APIKey' ] );
|
||||
const stripeConfig = JSON.parse( fs.readFileSync( path.join( __dirname + '/../../../../config/payments.config.secret.json' ) ) )[ 'stripe' ];
|
||||
const stripe = require( 'stripe' )( stripeConfig[ 'APIKey' ] );
|
||||
const bodyParser = require( 'body-parser' );
|
||||
const ticket = require( '../../../tickets/ticketGenerator.js' );
|
||||
const TicketGenerator = new ticket();
|
||||
|
||||
const endpointSecret = stripConfig[ 'endpointSecret' ];
|
||||
const endpointSecret = stripeConfig[ 'endpointSecret' ];
|
||||
|
||||
let sessionReference = {};
|
||||
let waitingClients = {};
|
||||
let pendingPayments = {};
|
||||
let paymentOk = {};
|
||||
|
||||
// TODO: Remove all selected tickets if timestamp more than user defined amount ago
|
||||
|
||||
module.exports = ( app, settings ) => {
|
||||
app.post( '/payments/prepare', bodyParser.json(), ( req, res ) => {
|
||||
if ( req.session.loggedInUser ) {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
{
|
||||
"stripe": {
|
||||
"APIKey": ""
|
||||
"APIKey": "",
|
||||
"endpointSecret": ""
|
||||
},
|
||||
"payrexx": {
|
||||
"APISecret": "",
|
||||
"instance": "",
|
||||
"pm": []
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"setupKey": "hello world",
|
||||
"twoFAMode": "enhanced",
|
||||
"db": "mysql",
|
||||
"payments": "stripe",
|
||||
"payments": "payrexx",
|
||||
"name": "libreevent",
|
||||
"yourDomain": "http://localhost:8080",
|
||||
"mailSender": "libreevent <info@libreevent.janishutz.com>",
|
||||
|
||||
123
src/server/package-lock.json
generated
123
src/server/package-lock.json
generated
@@ -11,9 +11,11 @@
|
||||
"dependencies": {
|
||||
"@pdfme/generator": "^1.2.6",
|
||||
"@seald-io/nedb": "^4.0.2",
|
||||
"axios": "^1.4.0",
|
||||
"bcrypt": "^5.0.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"crypto-js": "^4.1.1",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"html-to-text": "^9.0.5",
|
||||
@@ -21,6 +23,7 @@
|
||||
"mysql": "^2.18.1",
|
||||
"nodemailer": "^6.9.3",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"qs": "^6.11.2",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"serve-static": "^1.15.0",
|
||||
"stripe": "^12.14.0",
|
||||
@@ -432,6 +435,11 @@
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -454,6 +462,16 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -535,6 +553,20 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/body-parser/node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
@@ -665,6 +697,17 @@
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
@@ -774,6 +817,11 @@
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||
},
|
||||
"node_modules/crypto-js": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
|
||||
"integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
|
||||
},
|
||||
"node_modules/css-b64-images": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz",
|
||||
@@ -820,6 +868,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
@@ -934,6 +990,16 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/encoding": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
|
||||
"integrity": "sha512-bl1LAgiQc4ZWr++pNYUdRe/alecaHFeHxIJ/pNciqGdKXghaTCOwKkbKp6ye7pKZGu/GcaSXFk8PBVhgs+dJdA==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"iconv-lite": "~0.4.13"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
@@ -1087,6 +1153,20 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/express/node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/raw-body": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
||||
@@ -1152,6 +1232,25 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fontkit": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.2.tgz",
|
||||
@@ -1176,6 +1275,19 @@
|
||||
"is-callable": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
@@ -2158,10 +2270,15 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"version": "6.11.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
|
||||
"integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
|
||||
@@ -44,9 +44,11 @@
|
||||
"dependencies": {
|
||||
"@pdfme/generator": "^1.2.6",
|
||||
"@seald-io/nedb": "^4.0.2",
|
||||
"axios": "^1.4.0",
|
||||
"bcrypt": "^5.0.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"crypto-js": "^4.1.1",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"html-to-text": "^9.0.5",
|
||||
@@ -54,6 +56,7 @@
|
||||
"mysql": "^2.18.1",
|
||||
"nodemailer": "^6.9.3",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"qs": "^6.11.2",
|
||||
"serve-favicon": "^2.5.0",
|
||||
"serve-static": "^1.15.0",
|
||||
"stripe": "^12.14.0",
|
||||
|
||||
57
src/server/ui/en/payments/failed.html
Normal file
57
src/server/ui/en/payments/failed.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Payment Canceled</title>
|
||||
<style>
|
||||
body, html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
text-align: center;
|
||||
background-color: rgb(41, 40, 40);
|
||||
color: white;
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.submit {
|
||||
margin-top: 2%;
|
||||
background: linear-gradient(90deg, rgb(30, 36, 131), rgb(87, 66, 184), rgb(105, 115, 214), rgb(30, 36, 131), rgb(41, 128, 109), rgb(146, 50, 47));
|
||||
background-size: 300px;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
transition: all 3s;
|
||||
font-size: 75%;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.submit:hover {
|
||||
background-size: 200%;
|
||||
background-position: -100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>Payment Failed</h1>
|
||||
<p>Your payment has failed! Please try again or use a different payment method</p>
|
||||
<button onclick="location.href = '/cart'" class="submit">Back to the cart</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- <h2>Setup check</h2> -->
|
||||
<!-- TODO: Maybe add -->
|
||||
<!-- TODO: call config check of payment + check if events are deployed -->
|
||||
<h2>Settings</h2>
|
||||
<p>Changing any of these settings requires a restart of libreevent.</p>
|
||||
<p>Currency codes used must be valid ISO 4217 codes. Read more on <a href="https://libreevent.janishutz.com/docs/admin-panel/settings#currency" target="_blank">this page</a> of the documentation <!-- https://en.wikipedia.org/wiki/ISO_4217#List_of_ISO_4217_currency_codes"--></p>
|
||||
@@ -171,9 +174,9 @@
|
||||
},
|
||||
showPaymentSettings () {
|
||||
this.$refs.popup.openPopup( 'Payment gateway settings', {
|
||||
'link': '/payments/settings',
|
||||
}
|
||||
, 'iframe' );
|
||||
'link': '/payments/settings',
|
||||
}
|
||||
, 'iframe' );
|
||||
},
|
||||
createAccount() {
|
||||
this.$refs.popup.openPopup( 'Create new admin user', {
|
||||
@@ -224,6 +227,7 @@
|
||||
},
|
||||
handlePopupReturns( data ) {
|
||||
console.log( data );
|
||||
// TODO: Delete user
|
||||
if ( data.status === 'cancel' ) {
|
||||
console.log( 'user canceled' );
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user