payments fully integrated

This commit is contained in:
2023-08-06 20:35:50 +02:00
parent 32ed36b93f
commit 5cbf624284
6 changed files with 129 additions and 61 deletions

View File

@@ -57,7 +57,7 @@ class SQLDB {
} ); } );
this.sqlConnection.query( 'CREATE TABLE libreevent_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, pass TEXT, name TEXT, first_name TEXT, two_fa TINYTEXT, user_data VARCHAR( 60000 ), mail_confirmed TINYTEXT, marketing_ok TINYTEXT, PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', ( error ) => { this.sqlConnection.query( 'CREATE TABLE libreevent_users ( account_id INT ( 10 ) NOT NULL AUTO_INCREMENT, email TINYTEXT NOT NULL, pass TEXT, name TEXT, first_name TEXT, two_fa TINYTEXT, user_data VARCHAR( 60000 ), mail_confirmed TINYTEXT, marketing_ok TINYTEXT, PRIMARY KEY ( account_id ) ) ENGINE=INNODB;', ( error ) => {
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error; if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
this.sqlConnection.query( 'CREATE TABLE libreevent_orders ( order_id INT ( 10 ) NOT NULL AUTO_INCREMENT, order_name TINYTEXT, account_id INT ( 10 ) NOT NULL, tickets VARCHAR( 60000 ), PRIMARY KEY ( order_id ), FOREIGN KEY ( account_id ) REFERENCES libreevent_users( account_id ) ) ENGINE=INNODB;', ( error ) => { this.sqlConnection.query( 'CREATE TABLE libreevent_orders ( order_id INT ( 10 ) NOT NULL AUTO_INCREMENT, order_name TINYTEXT, account_id INT ( 10 ) NOT NULL, tickets VARCHAR( 60000 ), processed TINYTEXT, PRIMARY KEY ( order_id ), FOREIGN KEY ( account_id ) REFERENCES libreevent_users( account_id ) ) ENGINE=INNODB;', ( error ) => {
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error; if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;
this.sqlConnection.query( 'CREATE TABLE libreevent_admin ( account_id INT NOT NULL AUTO_INCREMENT, email TINYTEXT, pass TEXT, permissions VARCHAR( 1000 ), username TINYTEXT, two_fa TINYTEXT, PRIMARY KEY ( account_id ) );', ( error ) => { this.sqlConnection.query( 'CREATE TABLE libreevent_admin ( account_id INT NOT NULL AUTO_INCREMENT, email TINYTEXT, pass TEXT, permissions VARCHAR( 1000 ), username TINYTEXT, two_fa TINYTEXT, PRIMARY KEY ( account_id ) );', ( error ) => {
if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error; if ( error ) if ( error.code !== 'ER_TABLE_EXISTS_ERROR' ) throw error;

View File

@@ -8,6 +8,7 @@
*/ */
const path = require( 'path' ); const path = require( 'path' );
const fs = require( 'fs' );
// const ph = require( './paymentHandler.js' ); // const ph = require( './paymentHandler.js' );
// const paymentHandler = new ph(); // const paymentHandler = new ph();
@@ -15,4 +16,13 @@ module.exports = ( app, settings ) => {
app.get( '/payments/canceled', ( req, res ) => { app.get( '/payments/canceled', ( req, res ) => {
res.sendFile( path.join( __dirname + '/../../ui/en/payments/canceled.html' ) ); res.sendFile( path.join( __dirname + '/../../ui/en/payments/canceled.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 ) => {
if ( error ) res.sendFile( path.join( __dirname + '/../../ui/en/errors/404.html' ) );
else res.send( data );
} );
}
} );
}; };

View File

@@ -82,14 +82,37 @@ module.exports = ( app, settings ) => {
response.flushHeaders(); response.flushHeaders();
response.write( 'data: connected\n\n' ); response.write( 'data: connected\n\n' );
waitingClients[ request.session.id ] = response; waitingClients[ request.session.id ] = response;
const ping = setInterval( () => {
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 ) => { app.get( '/user/2fa/ping', ( request, response ) => {
if ( paymentOk[ request.session.token ] === 'ok' ) { if ( paymentOk[ request.session.id ] === 'ok' ) {
delete paymentOk[ request.session.token ]; delete paymentOk[ request.session.id ];
response.send( { 'status': 'ok' } ); response.send( { 'status': 'paymentOk' } );
} else { } else {
response.send( '' ); 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( '' );
}
} }
} ); } );
@@ -108,8 +131,10 @@ module.exports = ( app, settings ) => {
if ( event.type === 'checkout.session.completed' ) { if ( event.type === 'checkout.session.completed' ) {
setTimeout( () => { setTimeout( () => {
waitingClients[ sessionReference[ event.data.object.id ][ 'tok' ] ].write( 'data: paymentOk\n\n' ); if ( waitingClients[ sessionReference[ event.data.object.id ][ 'tok' ] ] ) {
}, 2000 ); waitingClients[ sessionReference[ event.data.object.id ][ 'tok' ] ].write( 'data: paymentOk\n\n' );
}
}, 1000 );
db.getDataSimple( 'temp', 'user_id', sessionReference[ event.data.object.id ][ 'tok' ] ).then( dat => { db.getDataSimple( 'temp', 'user_id', sessionReference[ event.data.object.id ][ 'tok' ] ).then( dat => {
db.getDataSimple( 'users', 'email', sessionReference[ event.data.object.id ][ 'email' ] ).then( user => { db.getDataSimple( 'users', 'email', sessionReference[ event.data.object.id ][ 'email' ] ).then( user => {
if ( user[ 0 ] ) { if ( user[ 0 ] ) {

View File

@@ -32,16 +32,31 @@ class TicketGenerator {
db.getJSONData( 'events' ).then( events => { db.getJSONData( 'events' ).then( events => {
this.events = events; this.events = events;
} ); } );
this.runningTickets = {};
} }
// TODO: Save to disk in case of crash of server / reboot / whatever // TODO: Save to disk in case of crash of server / reboot / whatever
// and continue processing once back online // and continue processing once back online
generateTickets ( order ) { generateTickets ( order ) {
this.ticketQueue [ this.jobId ] = { 'order': order }; this.ticketQueue[ this.jobId ] = { 'order': order };
this.runningTickets[ order ] = 'processing';
this.jobId += 1; this.jobId += 1;
this.queueHandler(); this.queueHandler();
} }
getGenerationStatus ( order ) {
if ( this.runningTickets[ order ] ) {
if ( this.runningTickets[ order ] === 'done' ) {
delete this.runningTickets[ order ];
return 'done';
} else {
return 'processing';
}
} else {
return 'noTicket';
}
}
// TODO: Maybe move to subprocesses // TODO: Maybe move to subprocesses
queueHandler () { queueHandler () {
if ( !this.isRunning ) { if ( !this.isRunning ) {
@@ -63,7 +78,8 @@ class TicketGenerator {
template: '' + fs.readFileSync( path.join( __dirname + '/../../ui/en/payments/ticketMail.html' ) ) template: '' + fs.readFileSync( path.join( __dirname + '/../../ui/en/payments/ticketMail.html' ) )
} ); } );
console.log( dat[ 0 ].email ); this.runningTickets[ res.order ] = 'done';
mailManager.sendMailWithAttachment( dat[ 0 ].email, await renderToString( app ), 'Thank you for your order', [ mailManager.sendMailWithAttachment( dat[ 0 ].email, await renderToString( app ), 'Thank you for your order', [
{ {
'filename': 'tickets.pdf', 'filename': 'tickets.pdf',
@@ -71,7 +87,7 @@ class TicketGenerator {
} }
], settings.mailSender ], settings.mailSender
); );
// db.writeDataSimple( 'orders', 'order_name', res.order, { 'processed': 'true' } ); db.writeDataSimple( 'orders', 'order_name', res.order, { 'processed': 'true' } );
} )(); } )();
} }
} ); } );

View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404</title>
</head>
<body>
<h1>404</h1>
</body>
</html>

View File

@@ -37,61 +37,67 @@
}, },
created() { created() {
if ( !!window.EventSource ) { if ( !!window.EventSource ) {
setTimeout( () => { setTimeout( () => {
let startNotification = this.$refs.notification.createNotification( 'Connecting to status service...', 20, 'progress', 'normal' ); let startNotification = this.$refs.notification.createNotification( 'Connecting to status service...', 20, 'progress', 'normal' );
let source = new EventSource( localStorage.getItem( 'url' ) + '/payments/status', { withCredentials: true } ); let source = new EventSource( localStorage.getItem( 'url' ) + '/payments/status', { withCredentials: true } );
let self = this; let self = this;
source.onmessage = ( e ) => { source.onmessage = ( e ) => {
if ( e.data === 'ready' ) { console.log( e );
open( '/tickets/get' ); if ( e.data === 'ready' ) {
} else if ( e.data === 'paymentOk' ) {
self.$refs.notification.createNotification( 'Your payment has been marked as completed!', 5, 'ok', 'normal' );
}
}
source.onopen = e => {
self.$refs.notification.createNotification( 'Connected to status service', 5, 'ok', 'normal' );
self.$refs.notification.cancelNotification( startNotification ); self.$refs.notification.cancelNotification( startNotification );
}; self.$refs.notification.createNotification( 'Your tickets are ready! Starting download...', 10, 'progress', 'normal' );
setTimeout( () => {
open( '/tickets/tickets.pdf' );
source.close();
}, 500 );
} else if ( e.data === 'paymentOk' ) {
self.$refs.notification.createNotification( 'Your payment has been marked as completed!', 5, 'ok', 'normal' );
}
}
source.addEventListener( 'error', function( e ) { source.onopen = e => {
if ( e.eventPhase == EventSource.CLOSED ) source.close(); self.$refs.notification.createNotification( 'Connected to status service', 5, 'ok', 'normal' );
self.$refs.notification.cancelNotification( startNotification );
};
if ( e.target.readyState == EventSource.CLOSED ) { source.addEventListener( 'error', function( e ) {
self.$refs.notification.cancelNotification( startNotification ); if ( e.eventPhase == EventSource.CLOSED ) source.close();
self.$refs.notification.createNotification( 'Could not connect to status service', 5, 'error', 'normal' );
} if ( e.target.readyState == EventSource.CLOSED ) {
}, false) self.$refs.notification.cancelNotification( startNotification );
}, 300 ); self.$refs.notification.createNotification( 'Could not connect to status service', 5, 'error', 'normal' );
} else { }
setTimeout( () => { }, false );
this.$refs.notification.createNotification( 'Unsupported browser detected. Ticket generation might take longer!', 20, 'warning', 'normal' ); }, 300 );
}, 300 ); } else {
// ping server every 5s to check if ticket ready setTimeout( () => {
this.serverPing = setInterval( () => { this.$refs.notification.createNotification( 'Unsupported browser detected. Ticket generation might take longer!', 20, 'warning', 'normal' );
fetch( '/payments/status/ping' ).then( res => { }, 300 );
if ( res.status === 200 ) { // ping server every 5s to check if ticket ready
res.json().then( data => { this.serverPing = setInterval( () => {
if ( data ) { fetch( '/payments/status/ping' ).then( res => {
if ( data.status === 'ready' ) { if ( res.status === 200 ) {
open( '/tickets/get' ); res.json().then( data => {
} else if ( data.status === 'paymentOk' ) { if ( data ) {
this.$refs.notification.createNotification( 'Your payment has been marked as completed!', 5, 'ok', 'normal' ); if ( data.status === 'ready' ) {
} open( '/tickets/get' );
} else if ( data.status === 'paymentOk' ) {
this.$refs.notification.createNotification( 'Your payment has been marked as completed!', 5, 'ok', 'normal' );
} }
} ); }
} else { } );
console.error( 'Request failed' ); } else {
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' ); console.error( 'Request failed' );
}
} ).catch( error => {
console.error( error );
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' ); this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
} ); }
}, 5000 ); } ).catch( error => {
} console.error( error );
this.$refs.notification.createNotification( 'We are sorry, but an error occurred. You will not be redirected automatically', 300, 'error', 'normal' );
} );
}, 5000 );
}
} }
} }
</script> </script>