Commit 26421c86 authored by Mindiell's avatar Mindiell
Browse files

First commit

parents
__pycache__
config.py
db.sqlite3
*.mo
This diff is collapsed.
# FakeBank
This project is a small web app faking a bank in order to test online payment.
## Installation
git clone
, then
pip install -r requirements.txt
## Informations
Everything is not ok yet, and there is some more work to do, like computing the right key for each
payment...
#encoding: utf-8
from flask_admin import Admin, expose, AdminIndexView
from flask_sqlalchemy import SQLAlchemy
from app.form.user import UserForm
class IndexView(AdminIndexView):
@expose('/')
def index(self):
form = UserForm()
return self.render('admin/index.html', form=form)
admin = Admin(index_view=IndexView())
db = SQLAlchemy()
#encoding: utf-8
from flask import render_template
class Controller():
@classmethod
def as_view(cls, function_name, *class_args, **class_kwargs):
# Create the view function to return
def view(*args, **kwargs):
self = view.view_class(*class_args, **class_kwargs)
if hasattr(self, function_name):
return getattr(self, function_name)(*args, **kwargs)
else:
return "Class %s has no method called %s" % (cls.__name__, function_name)
view.view_class = cls
# name used for endpoint : Class name + function name
view.__name__ = '.'.join((cls.__name__.lower(), function_name))
view.__doc__ = cls.__doc__
view.__module__ = cls.__module__
return view
#encoding: utf-8
from flask import render_template, request, redirect
import requests
from random import randint
from app.controller.controller import Controller
class Core(Controller):
def home(self):
return render_template('core/home.html')
def payment(self):
"""
Processing fake payment request
Example of datas POSTed
('signature', '8736af0cd9d457f5e15ec7bf10005a12a9d2ff48'),
('vads_url_check', 'https://localhost/payment/pledge/check/'),
('vads_shop_url', 'https://localhost'),
('submit', 'Valider ce don'),
('vads_page_action', 'PAYMENT'),
('vads_redirect_error_timeout', '5'),
('vads_trans_date', '20180310080607'),
('vads_trans_id', '000004'),
('csrfmiddlewaretoken', 'xe6CYxhA4Esa4zBmPAT7Ee29hAlZtYKld0o4waId5hxi5IvRbvZU787mzbbySLnU'),
('vads_ctx_mode', 'TEST'),
('vads_redirect_success_timeout', '5'),
('vads_validation_mode', '0'),
('vads_return_mode', 'GET'),
('vads_language', 'fr'),
('vads_action_mode', 'INTERACTIVE'),
('vads_currency', '978'),
('vads_site_id', '1'),
('vads_capture_delay', '0'),
('vads_url_return', 'https://localhost/payment/pledge/4/return/'),
('vads_amount', '3000'),
('vads_version', 'V2'),
('vads_shop_name', 'localhost:8000'),
('vads_payment_config', 'SINGLE')
"""
url_check = request.form['vads_url_check'].replace('https', 'http')
url_return = request.form['vads_url_return'].replace('https', 'http')
# Preparing answer data
params = {}
try:
params = {
'vads_trans_status' : 'AUTHORISED',
'vads_trans_date' : request.form['vads_trans_date'],
'vads_trans_id' : int(request.form['vads_trans_id']),
'vads_action_mode': request.form['vads_action_mode'],
'vads_ctx_mode': request.form['vads_ctx_mode'],
'vads_language': request.form['vads_language'],
'vads_page_action': request.form['vads_page_action'],
'vads_shop_url': request.form['vads_shop_url'],
'vads_site_id': request.form['vads_site_id'],
'vads_presentation_date': request.form['vads_trans_date'],
'signature' : '78cb45e9a68f0f7d27211bb194d0019c2d69ed03',
'vads_expiry_month': '12',
'vads_expiry_year': '2024',
'vads_auth_mode': 'FULL',
'vads_auth_number': '3fec2d',
'vads_auth_result': '00',
'vads_bank_code': '17807',
'vads_bank_product': 'F',
'vads_capture_delay': '0',
'vads_card_brand': 'CB',
'vads_card_country': 'FR',
'vads_card_number': '497010XXXXXX0014',
'vads_contract_used': '5201306',
'vads_extra_result': '',
'vads_hash': '74026bd3287e4241f30b1eac74ae6951a525989b57c320750dedbbbbafac4582',
'vads_operation_type': 'DEBIT',
'vads_payment_certificate': '3a179852ac1bb4b7c64722d1b20c4052e20cc596',
'vads_payment_src': 'EC',
'vads_pays_ip': 'FR',
'vads_result': '00',
'vads_sequence_number': '1',
'vads_shop_name': 'Support La Quadrature du Net',
'vads_threeds_cavv': 'Q2F2dkNhdnZDYXZ2Q2F2dkNhdnY=',
'vads_threeds_cavvAlgorithm': '2',
'vads_threeds_eci': '05',
'vads_threeds_enrolled': 'Y',
'vads_threeds_error_code': '',
'vads_threeds_exit_status': '10',
'vads_threeds_sign_valid': '1',
'vads_threeds_status': 'Y',
'vads_threeds_xid': 'VkZHZVViWXpscWRDQkRjdWNuakE=',
'vads_trans_uuid': '6c673fec09d047bea48b8ac137c7d7e4',
'vads_url_check_src': 'PAY',
'vads_validation_mode': '0',
'vads_version': 'V2',
'vads_warranty_result': 'YES',
}
except:
print("error data basic")
try:
if request.form['vads_page_action']=='PAYMENT':
params['vads_currency'] = request.form['vads_currency']
params['vads_amount'] = request.form['vads_amount']
params['vads_effective_amount'] = request.form['vads_amount']
params['vads_effective_creation_date'] = request.form['vads_trans_date']
params['vads_effective_currency'] = request.form['vads_currency']
params['vads_payment_config'] = request.form['vads_payment_config']
except:
print("error data payment")
try:
if request.form['vads_page_action']=='REGISTER_SUBSCRIBE':
params['vads_cust_email'] = request.form['vads_cust_email'] or 'test@test.fr'
params['vads_identifier'] = request.form['vads_identifier']
params['vads_sub_amount'] = request.form['vads_sub_amount']
params['vads_sub_currency'] = request.form['vads_sub_currency']
params['vads_sub_desc'] = request.form['vads_sub_desc']
params['vads_sub_effect_date'] = request.form['vads_sub_effect_date']
params['vads_effective_amount'] = request.form['vads_sub_amount']
params['vads_effective_currency'] = request.form['vads_sub_currency']
params['vads_amount'] = request.form['vads_sub_amount']
params['vads_currency'] = request.form['vads_sub_currency']
params['vads_identifier_status'] = 'CREATED'
params['vads_recurrence_status'] = 'CREATED'
params['vads_subscription'] = 'SUBSCRIBED'
except:
print("error data subscribe")
print("="*42)
print(request.form)
print("="*42)
print(params)
print("="*42)
print(request.form['vads_url_check'], url_check)
print(request.form['vads_url_return'], url_return)
# Calling the check page
result = requests.post(url_check, data=params)
print(result)
with open('result.html', 'w') as f:
f.write(result.text)
# Then, we need to redirect to the return page
return redirect(url_return)
#encoding: utf-8
from flask_wtf import FlaskForm
from wtforms import StringField, FileField, SelectField, HiddenField, PasswordField
from wtforms.validators import DataRequired
class UserForm(FlaskForm):
user_id = HiddenField('Id')
login = StringField('Login', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
password_confirm = PasswordField('Password confirmation')
email = StringField('E-mail')
#encoding: utf-8
import importlib
import os
import pkgutil
# Import automatically every model apart the base model 'model'
for module in pkgutil.iter_modules(path=(os.path.abspath(os.path.dirname(__file__)),)):
name = module[1]
capitalized_name = name[0].upper() + name[1:]
if name!="model":
getattr(importlib.import_module('app.model.%s' % name), capitalized_name)
#encoding: utf-8
from flask import redirect, request, url_for
from flask_admin.contrib.sqla import ModelView
from flask_login import current_user
from app import db
class View(ModelView):
def is_accessible(self):
return current_user.is_authenticated and current_user.is_admin
def inaccessible_callback(self, name, **kwargs):
return redirect(url_for('admin.login', next=request.url))
class Model():
def save(self):
if self.id is None or self.id=='':
db.session.add(self)
db.session.commit()
def delete(self):
if self.id is not None:
db.session.delete(self)
db.session.commit()
#encoding: utf-8
from app import admin, db
from app.model.model import Model, View
def get_user(user_id):
return User.query.get(user_id)
class User(db.Model, Model):
id = db.Column(db.Integer, primary_key=True)
login = db.Column(db.String(1000))
password = db.Column(db.String(64))
email = db.Column(db.String(1000))
active = db.Column(db.Boolean())
admin = db.Column(db.Boolean())
def is_authenticated(self):
return self.id is not None
def is_active(self):
return self.active
def is_anonymous(self):
return False
def is_admin(self):
return self.admin
def get_id(self):
return str(self.id)
class UserAdmin(View):
column_exclude_list = ['password', ]
# User model will be automatically managed through flask-admin module
admin.add_view(UserAdmin(User, db.session))
#encoding: utf-8
from app.controller.core import Core
routes = [
('/', Core.as_view('home')),
('/payment', Core.as_view('payment'), ['GET', 'POST']),
]
apis = [
]
{% include "header.html" %}
{% block content %}
<section>{{ _("An error has been detected. Please come back later.") }}</section>
{% endblock %}
{% include "footer.html" %}
{% extends 'base.html' %}
{% block content %}
<!-- Content -->
<h1>FakeBank</h1>
<p>This website is just a small app faking a bank in order to test online payment.</p>
{% endblock %}
</section>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- General information -->
<meta name="author" content="">
<meta name="description" content="">
<link rel="icon" href="/static/img/favicon.ico">
<title>FakeBank</title>
</head>
<body>
<section class="container-fluid">
#encoding: utf-8
import os
APPLICATION = 'Flask MVC'
DEBUG = False
HOST = '0.0.0.0'
PORT = 5000
SECRET_KEY = 'Choose a secret key'
JINJA_ENV = {
'TRIM_BLOCKS' : True,
'LSTRIP_BLOCKS' : True,
}
# defining base directory
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
# defining database URI
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, 'db.sqlite3')
SQLALCHEMY_TRACK_MODIFICATIONS = False
# defining Babel settings
BABEL_DEFAULT_LOCALE = 'en'
# Languages available
AVAILABLE_LANGUAGES = {
'en': 'English',
'fr': 'French',
}
#encoding: utf-8
from flask import Flask, session, g
from flask_restful import Api
from flask_admin import Admin
from flask_babel import Babel
from flask_login import LoginManager
from app import admin, db
app = Flask(__name__, template_folder='app/view')
app.config.from_object('config')
if 'JINJA_ENV' in app.config:
app.jinja_env.trim_blocks = app.config['JINJA_ENV']['TRIM_BLOCKS']
app.jinja_env.lstrip_blocks = app.config['JINJA_ENV']['LSTRIP_BLOCKS']
admin.init_app(app)
api = Api(app)
babel = Babel(app)
login_manager = LoginManager(app)
db.init_app(app)
from app.routes import routes, apis
# Loading routes
for route in routes:
if len(route)<3:
app.add_url_rule(route[0], route[1].__name__, route[1], methods=["GET"])
else:
app.add_url_rule(route[0], route[1].__name__, route[1], methods=route[2])
# Loading routes for api
for route in apis:
api.add_resource(route[1], route[0])
# Manage locale
@babel.localeselector
def get_locale():
#TODO: set locale even when session is cleared...
if 'locale' not in session:
session['locale'] = app.config['BABEL_DEFAULT_LOCALE']
return session['locale']
# Manage user
from app.model.user import get_user
@login_manager.user_loader
def load_user(user_id):
return get_user(user_id)
if __name__=='__main__':
# Initialize Database
from app import model
with app.app_context():
db.create_all()
app.run(
debug = app.config['DEBUG'],
host = app.config['HOST'],
port = app.config['PORT'],
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment