mirror of
https://github.com/YunoHost/pepettes.git
synced 2024-09-03 20:06:20 +02:00
Compare commits
28 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7c318b3d6c | ||
|
bd7b91b9a7 | ||
|
7dd7202d81 | ||
|
4efabca559 | ||
|
afaf1019aa | ||
|
a40de29ebe | ||
|
ac970eb50e | ||
|
62ba1edb0f | ||
|
3c85de822e | ||
|
b1d3177384 | ||
|
f85a0cd408 | ||
|
477f3afa9e | ||
|
784172a8ea | ||
|
c66a7c85d3 | ||
|
89dee68807 | ||
|
31640b1523 | ||
|
da4808bd40 | ||
|
c2b4a31050 | ||
|
549a9f24e2 | ||
|
4a8291c871 | ||
|
f3b271ca3b | ||
|
aa8654ac9b | ||
|
f46a1d90f7 | ||
|
1c26b78b87 | ||
|
4d26967eaf | ||
|
6be78be447 | ||
|
424a3f61c4 | ||
|
dc2686408a |
14 changed files with 309 additions and 159 deletions
35
.github/workflows/autoblack.yml
vendored
Normal file
35
.github/workflows/autoblack.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
name: Check / auto apply Black
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
black:
|
||||
name: Check / auto apply black
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check files using the black formatter
|
||||
uses: psf/black@stable
|
||||
id: black
|
||||
with:
|
||||
options: "."
|
||||
continue-on-error: true
|
||||
- shell: pwsh
|
||||
id: check_files_changed
|
||||
run: |
|
||||
# Diff HEAD with the previous commit
|
||||
$diff = git diff
|
||||
$HasDiff = $diff.Length -gt 0
|
||||
Write-Host "::set-output name=files_changed::$HasDiff"
|
||||
- name: Create Pull Request
|
||||
if: steps.check_files_changed.outputs.files_changed == 'true'
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: "Format Python code with Black"
|
||||
commit-message: ":art: Format Python code with Black"
|
||||
body: |
|
||||
This pull request uses the [psf/black](https://github.com/psf/black) formatter.
|
||||
base: ${{ github.head_ref }} # Creates pull request onto pull request or commit branch
|
||||
branch: actions/black
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -127,3 +127,6 @@ dmypy.json
|
|||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# Config file
|
||||
settings.py
|
||||
|
|
23
README.md
23
README.md
|
@ -8,22 +8,23 @@ The demo is running in test mode -- use `4242424242424242` as a test card number
|
|||
|
||||
Use the `4000002500003155` test card number to trigger a 3D Secure challenge flow.
|
||||
|
||||
Read more about testing on Stripe at https://stripe.com/docs/testing.
|
||||
Read more about testing on Stripe at <https://stripe.com/docs/testing>.
|
||||
|
||||
## How to run locally
|
||||
|
||||
Follow the steps below to run locally.
|
||||
|
||||
```
|
||||
git clone https://github.com/yunohost/donate
|
||||
cd donate
|
||||
```bash
|
||||
git clone https://github.com/YunoHost/pepettes
|
||||
cd pepettes
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip3 install requirements.txt
|
||||
python3 -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Create a settings.py file with :
|
||||
```
|
||||
|
||||
```python
|
||||
ENV = 'development'
|
||||
PORT = 8000
|
||||
DOMAIN = 'http://localhost:8000'
|
||||
|
@ -55,7 +56,15 @@ DONATION['recuring']['EUR'] = 'price_1IKumjE7vOmTpJBikyqS2NqD'
|
|||
DONATION['recuring']['USD'] = 'price_1IKumAE7vOmTpJBiO4CEfa3Q'
|
||||
```
|
||||
|
||||
```
|
||||
```bash
|
||||
export FLASK_APP=server.py
|
||||
python3 -m flask run --port=8000
|
||||
```
|
||||
|
||||
```bash
|
||||
# extract new strings or update existing strings
|
||||
pybabel extract -F babel.cfg -o messages.pot *.py assets/*.html
|
||||
|
||||
# then update the locale files, please translate into french any new string
|
||||
pybabel update -i messages.pot -d locales
|
||||
```
|
||||
|
|
|
@ -1,25 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<html lang="{{ lang }}">
|
||||
|
||||
<title>{{ _('Donate to %(name)s', name=name) }}</title>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="icon" href="{{ favicon }}" type="image/x-icon" />
|
||||
<link href="./css/bootstrap-5.0.0-beta2.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
||||
<link href="./css/global.css" rel="stylesheet" />
|
||||
</head>
|
||||
<title>{{ _('Donate to %(name)s', name=name) }}</title>
|
||||
|
||||
<body class="text-center">
|
||||
<main class="form-donate">
|
||||
<div>
|
||||
<img src="{{ logo }}" class="mb-4" alt="" width="74" height="74"/>
|
||||
<h1 class="h3 mb-3 fw-normal">{{ _('Your payment was canceled') }}</h1>
|
||||
<link rel="icon" href="{{ favicon }}" type="image/x-icon" />
|
||||
<link href="./css/bootstrap-5.3.3.min.css" rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" />
|
||||
<link href="./css/global.css" rel="stylesheet" />
|
||||
<script src="./darkmode.js" defer></script>
|
||||
</head>
|
||||
|
||||
<button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary">{{ _('Go back to the donate form') }}</button>
|
||||
<body class="text-center">
|
||||
<main class="form-donate">
|
||||
<div>
|
||||
<img src="{{ logo }}" class="mb-4" alt="{{ _('%(name)s Logo', name=name) }}" />
|
||||
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
<h1 class="h3 mb-3 fw-normal">{{ _('Your payment was canceled') }}</h1>
|
||||
|
||||
<button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary">
|
||||
{{ _('Go back to the donate form') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
7
assets/css/bootstrap-5.0.0-beta2.min.css
vendored
7
assets/css/bootstrap-5.0.0-beta2.min.css
vendored
File diff suppressed because one or more lines are too long
6
assets/css/bootstrap-5.3.3.min.css
vendored
Normal file
6
assets/css/bootstrap-5.3.3.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -8,7 +8,16 @@ body {
|
|||
align-items: center;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
img {
|
||||
filter: invert(100%);
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 13em
|
||||
}
|
||||
|
||||
.form-donate {
|
||||
|
@ -17,9 +26,11 @@ body {
|
|||
padding: 15px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.form-donate .checkbox {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.form-donate .form-control {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
|
@ -27,17 +38,19 @@ body {
|
|||
padding: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.form-donate .form-control:focus {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.form-donate input[type="email"] {
|
||||
margin-bottom: -1px;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.form-donate input[type="password"] {
|
||||
margin-bottom: 10px;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
}
|
13
assets/darkmode.js
Normal file
13
assets/darkmode.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Set theme to the user's preferred color scheme
|
||||
function updateTheme() {
|
||||
const colorMode = window.matchMedia("(prefers-color-scheme: dark)").matches ?
|
||||
"dark" :
|
||||
"light";
|
||||
document.querySelector("html").setAttribute("data-bs-theme", colorMode);
|
||||
}
|
||||
|
||||
// Set theme on load
|
||||
updateTheme()
|
||||
|
||||
// Update theme when the preferred scheme changes
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateTheme)
|
|
@ -1,42 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<html lang="{{ lang }}">
|
||||
|
||||
<title>{{ _('Donate to %(name)s', name=name) }}</title>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="icon" href="{{ favicon }}" type="image/x-icon" />
|
||||
<link href="./css/bootstrap-5.0.0-beta2.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
||||
<link href="./css/global.css" rel="stylesheet" />
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script src="./index.js" defer></script>
|
||||
</head>
|
||||
<title>{{ _('Donate to %(name)s', name=name) }}</title>
|
||||
|
||||
<body class="text-center">
|
||||
<main class="form-donate">
|
||||
<div>
|
||||
<img src="{{ logo }}" class="mb-4" alt="" width="74" height="74"/>
|
||||
<h1 class="h3 mb-3 fw-normal">{{ _('I want to give to %(name)s', name=name) }}</h1>
|
||||
<div class="input-group mb-3">
|
||||
<input type="hidden" id="csrf" value="{{ csrf }}" />
|
||||
<input type="hidden" id="public_key" value="{{ stripe_publishable_key }}" />
|
||||
<input type="number" min="0" max="9999" class="form-control" id="quantity" value="10" aria-label="Amount">
|
||||
<select class="form-control" id="currency" style="width:40px">
|
||||
{% for iso, symbol in currencies %}
|
||||
<option value="{{ iso }}">{{ symbol }}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select class="form-control" id="frequency">
|
||||
<option value="recuring"> {{ _('/ month') }}
|
||||
<option value="one_time"> {{ _('one time') }}
|
||||
</select>
|
||||
</div>
|
||||
<link rel="icon" href="{{ favicon }}" type="image/x-icon" />
|
||||
<link href="./css/bootstrap-5.3.3.min.css" rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" />
|
||||
<link href="./css/global.css" rel="stylesheet" />
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script src="./index.js" defer></script>
|
||||
<script src="./darkmode.js" defer></script>
|
||||
</head>
|
||||
|
||||
<button id="submit" class="w-100 btn btn-lg btn-primary">{{ _('Donate') }}</button>
|
||||
<p><a href="{{ contact_url }}">{{ _('If you want to stop a monthly donation contact us') }}</a></p>
|
||||
<div id="error-message"></div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
<body class="text-center">
|
||||
<main class="form-donate">
|
||||
<div>
|
||||
<img src="{{ logo }}" class="mb-4" alt="{{ _('%(name)s Logo', name=name) }}" />
|
||||
<h1 class="h3 mb-3 fw-normal">{{ _('I want to give to %(name)s', name=name) }}</h1>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input type="hidden" id="csrf" value="{{ csrf }}" />
|
||||
<input type="hidden" id="public_key" value="{{ stripe_publishable_key }}" />
|
||||
|
||||
<input type="number" min="0" max="9999" class="form-control" id="quantity" value="10"
|
||||
aria-label="{{ _('Amount') }}">
|
||||
|
||||
<select class="form-select" id="currency" style="width:40px" aria-label="{{ _('Currency') }}">
|
||||
{% for iso, symbol in currencies %}
|
||||
<option value="{{ iso }}">{{ symbol }} </option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<select class="form-select" id="frequency" aria-label="{{ _('Frequency') }}">
|
||||
<option value="recuring"> {{ _('/ month') }} </option>
|
||||
<option value="one_time"> {{ _('one time') }} </option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button id="submit" class="w-100 btn btn-lg btn-primary">
|
||||
{{ _('Donate') }}
|
||||
</button>
|
||||
|
||||
<p><a href="{{ contact_url }}">{{ _('If you want to cancel a monthly donation, please contact us') }}</a></p>
|
||||
|
||||
<div id="error-message"></div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,25 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<html lang="{{ lang }}">
|
||||
|
||||
<title>{{ _('Donate to %(name)s', name=name) }}</title>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="icon" href="{{ favicon }}" type="image/x-icon" />
|
||||
<link href="./css/bootstrap-5.0.0-beta2.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
||||
<link href="./css/global.css" rel="stylesheet" />
|
||||
</head>
|
||||
<title>{{ _('Donate to %(name)s', name=name) }}</title>
|
||||
|
||||
<body class="text-center">
|
||||
<main class="form-donate">
|
||||
<div>
|
||||
<img src="{{ logo }}" class="mb-4" alt="" width="74" height="74"/>
|
||||
<h1 class="h3 mb-3 fw-normal">{{ _('Thanks for your donation 🙂') }}</h1>
|
||||
<link rel="icon" href="{{ favicon }}" type="image/x-icon" />
|
||||
<link href="./css/bootstrap-5.3.3.min.css" rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" />
|
||||
<link href="./css/global.css" rel="stylesheet" />
|
||||
<script src="./darkmode.js" defer></script>
|
||||
</head>
|
||||
|
||||
<button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary">{{ _('Go back to the donate form') }}</button>
|
||||
<body class="text-center">
|
||||
<main class="form-donate">
|
||||
<div>
|
||||
<img src="{{ logo }}" class="mb-4" alt="{{ _('%(name)s Logo', name=name) }}" />
|
||||
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
<h1 class="h3 mb-3 fw-normal">{{ _('Thanks for your donation 🙂') }}</h1>
|
||||
|
||||
<button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary">
|
||||
{{ _('Go back to the donate form') }}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -7,48 +7,69 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2021-02-18 23:32+0100\n"
|
||||
"POT-Creation-Date: 2024-05-22 04:43+0200\n"
|
||||
"PO-Revision-Date: 2021-02-18 23:33+0100\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: en\n"
|
||||
"Language-Team: en <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.0\n"
|
||||
"Generated-By: Babel 2.15.0\n"
|
||||
|
||||
#: assets/canceled.html:7 assets/index.html:7 assets/success.html:7
|
||||
#: assets/canceled.html:8 assets/index.html:8 assets/success.html:8
|
||||
#, python-format
|
||||
msgid "Donate to %(name)s"
|
||||
msgstr ""
|
||||
|
||||
#: assets/canceled.html:18
|
||||
#: assets/canceled.html:20 assets/index.html:22 assets/success.html:20
|
||||
#, python-format
|
||||
msgid "%(name)s Logo"
|
||||
msgstr ""
|
||||
|
||||
#: assets/canceled.html:22
|
||||
msgid "Your payment was canceled"
|
||||
msgstr ""
|
||||
|
||||
#: assets/canceled.html:20 assets/success.html:20
|
||||
#: assets/canceled.html:25 assets/success.html:25
|
||||
msgid "Go back to the donate form"
|
||||
msgstr ""
|
||||
|
||||
#: assets/index.html:20
|
||||
#: assets/index.html:23
|
||||
#, python-format
|
||||
msgid "I want to give to %(name)s"
|
||||
msgstr ""
|
||||
|
||||
#: assets/index.html:31
|
||||
msgid "/ month"
|
||||
#: assets/index.html:30
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#: assets/index.html:32
|
||||
msgid "Currency"
|
||||
msgstr ""
|
||||
|
||||
#: assets/index.html:38
|
||||
msgid "Frequency"
|
||||
msgstr ""
|
||||
|
||||
#: assets/index.html:39
|
||||
msgid "/ month"
|
||||
msgstr ""
|
||||
|
||||
#: assets/index.html:40
|
||||
msgid "one time"
|
||||
msgstr ""
|
||||
|
||||
#: assets/index.html:36
|
||||
#: assets/index.html:45
|
||||
msgid "Donate"
|
||||
msgstr ""
|
||||
|
||||
#: assets/success.html:18
|
||||
#: assets/index.html:48
|
||||
msgid "If you want to cancel a monthly donation, please contact us"
|
||||
msgstr ""
|
||||
|
||||
#: assets/success.html:22
|
||||
msgid "Thanks for your donation 🙂"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -7,48 +7,72 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2021-02-18 23:32+0100\n"
|
||||
"POT-Creation-Date: 2024-05-22 04:43+0200\n"
|
||||
"PO-Revision-Date: 2021-02-18 23:33+0100\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: fr\n"
|
||||
"Language-Team: fr <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.0\n"
|
||||
"Generated-By: Babel 2.15.0\n"
|
||||
|
||||
#: assets/canceled.html:7 assets/index.html:7 assets/success.html:7
|
||||
#: assets/canceled.html:8 assets/index.html:8 assets/success.html:8
|
||||
#, python-format
|
||||
msgid "Donate to %(name)s"
|
||||
msgstr "Donner à %(name)s"
|
||||
|
||||
#: assets/canceled.html:18
|
||||
#: assets/canceled.html:20 assets/index.html:22 assets/success.html:20
|
||||
#, python-format
|
||||
msgid "%(name)s Logo"
|
||||
msgstr "Logo de %(name)s"
|
||||
|
||||
#: assets/canceled.html:22
|
||||
msgid "Your payment was canceled"
|
||||
msgstr "Votre paiement a été annulé"
|
||||
|
||||
#: assets/canceled.html:20 assets/success.html:20
|
||||
#: assets/canceled.html:25 assets/success.html:25
|
||||
msgid "Go back to the donate form"
|
||||
msgstr "Retourner au formulaire de don"
|
||||
|
||||
#: assets/index.html:20
|
||||
#: assets/index.html:23
|
||||
#, python-format
|
||||
msgid "I want to give to %(name)s"
|
||||
msgstr "Je veux donner à %(name)s"
|
||||
|
||||
#: assets/index.html:31
|
||||
#: assets/index.html:30
|
||||
#, fuzzy
|
||||
msgid "Amount"
|
||||
msgstr "Montant"
|
||||
|
||||
#: assets/index.html:32
|
||||
msgid "Currency"
|
||||
msgstr "Devise"
|
||||
|
||||
#: assets/index.html:38
|
||||
msgid "Frequency"
|
||||
msgstr "Fréquence"
|
||||
|
||||
#: assets/index.html:39
|
||||
msgid "/ month"
|
||||
msgstr "/ mois"
|
||||
|
||||
#: assets/index.html:32
|
||||
#: assets/index.html:40
|
||||
msgid "one time"
|
||||
msgstr "une fois"
|
||||
|
||||
#: assets/index.html:36
|
||||
#: assets/index.html:45
|
||||
msgid "Donate"
|
||||
msgstr "Donner"
|
||||
|
||||
#: assets/success.html:18
|
||||
#: assets/index.html:48
|
||||
msgid "If you want to cancel a monthly donation, please contact us"
|
||||
msgstr ""
|
||||
"Si vous souhaitez mettre fin à votre don mensuel, contactez-nous s'il "
|
||||
"vous plaît"
|
||||
|
||||
#: assets/success.html:22
|
||||
msgid "Thanks for your donation 🙂"
|
||||
msgstr "Merci pour votre don 🙂"
|
||||
|
||||
|
|
|
@ -13,3 +13,4 @@ toml==0.9.6
|
|||
urllib3==1.25.3
|
||||
flask-simple-csrf
|
||||
flask-babel
|
||||
Werkzeug==0.16.0
|
||||
|
|
95
server.py
95
server.py
|
@ -12,84 +12,89 @@ import os
|
|||
import random
|
||||
import string
|
||||
|
||||
from flask import Flask, render_template, jsonify, request, send_from_directory, session
|
||||
from flask_babel import Babel, _
|
||||
from flask import Flask, render_template, jsonify, request, session
|
||||
from flask_babel import Babel
|
||||
from flask_simple_csrf import CSRF
|
||||
|
||||
|
||||
static_dir = str(os.path.abspath(os.path.join(
|
||||
__file__, "..", 'assets')))
|
||||
app = Flask(__name__, static_folder=static_dir,
|
||||
static_url_path="", template_folder=static_dir)
|
||||
app.config.from_pyfile('settings.py')
|
||||
stripe.api_key = app.config['STRIPE_SECRET_KEY']
|
||||
CSRF = CSRF(config={
|
||||
'SECRET_CSRF_KEY': app.config['SECRET_CSRF_KEY']
|
||||
})
|
||||
static_dir = str(os.path.abspath(os.path.join(__file__, "..", "assets")))
|
||||
app = Flask(
|
||||
__name__, static_folder=static_dir, static_url_path="", template_folder=static_dir
|
||||
)
|
||||
app.config.from_pyfile("settings.py")
|
||||
stripe.api_key = app.config["STRIPE_SECRET_KEY"]
|
||||
CSRF = CSRF(config={"SECRET_CSRF_KEY": app.config["SECRET_CSRF_KEY"]})
|
||||
app = CSRF.init_app(app)
|
||||
babel = Babel(app)
|
||||
|
||||
|
||||
@app.before_request
|
||||
def before_request():
|
||||
if 'CSRF_TOKEN' not in session or 'USER_CSRF' not in session:
|
||||
session['USER_CSRF'] = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(64))
|
||||
session['CSRF_TOKEN'] = CSRF.create(session['USER_CSRF'])
|
||||
if "CSRF_TOKEN" not in session or "USER_CSRF" not in session:
|
||||
session["USER_CSRF"] = "".join(
|
||||
random.SystemRandom().choice(string.ascii_uppercase + string.digits)
|
||||
for _ in range(64)
|
||||
)
|
||||
session["CSRF_TOKEN"] = CSRF.create(session["USER_CSRF"])
|
||||
|
||||
|
||||
@babel.localeselector
|
||||
def get_locale():
|
||||
return 'fr' #request.accept_languages.best_match(app.config['LANGUAGES'])
|
||||
return request.accept_languages.best_match(app.config["LANGUAGES"])
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
|
||||
@app.context_processor
|
||||
def utility_processor():
|
||||
return dict(lang=babel.locale_selector_func())
|
||||
|
||||
|
||||
@app.route("/", methods=["GET"])
|
||||
def get_index():
|
||||
return render_template('index.html', **app.config['CUSTOM'],
|
||||
csrf=session['USER_CSRF'])
|
||||
return render_template(
|
||||
"index.html", **app.config["CUSTOM"], csrf=session["USER_CSRF"]
|
||||
)
|
||||
|
||||
|
||||
@app.route('/success', methods=['GET'])
|
||||
@app.route("/success", methods=["GET"])
|
||||
def get_success():
|
||||
return render_template('success.html', **app.config['CUSTOM'])
|
||||
return render_template("success.html", **app.config["CUSTOM"])
|
||||
|
||||
|
||||
@app.route('/canceled', methods=['GET'])
|
||||
@app.route("/canceled", methods=["GET"])
|
||||
def get_canceled():
|
||||
return render_template('canceled.html', **app.config['CUSTOM'])
|
||||
return render_template("canceled.html", **app.config["CUSTOM"])
|
||||
|
||||
|
||||
@app.route('/create-checkout-session', methods=['POST'])
|
||||
@app.route("/create-checkout-session", methods=["POST"])
|
||||
def create_checkout_session():
|
||||
data = json.loads(request.data)
|
||||
domain_url = app.config['DOMAIN']
|
||||
domain_url = app.config["DOMAIN"]
|
||||
try:
|
||||
donation = app.config['DONATION']
|
||||
currencies = [iso for iso, symbol in app.config['CUSTOM']['currencies']]
|
||||
if CSRF.verify(data['user_csrf'], session['CSRF_TOKEN']) is False or \
|
||||
data['frequency'] not in ['recuring', 'one_time'] or \
|
||||
data['currency'] not in currencies or \
|
||||
int(data['quantity']) <= 0:
|
||||
donation = app.config["DONATION"]
|
||||
currencies = [iso for iso, symbol in app.config["CUSTOM"]["currencies"]]
|
||||
if (
|
||||
CSRF.verify(data["user_csrf"], session["CSRF_TOKEN"]) is False
|
||||
or data["frequency"] not in ["recuring", "one_time"]
|
||||
or data["currency"] not in currencies
|
||||
or int(data["quantity"]) <= 0
|
||||
):
|
||||
return jsonify(error="Bad value"), 400
|
||||
|
||||
# Create new Checkout Session for the order
|
||||
price = donation[data['frequency']][data['currency']]
|
||||
mode = "payment" if data['frequency'] == 'one_time' else "subscription"
|
||||
price = donation[data["frequency"]][data["currency"]]
|
||||
mode = "payment" if data["frequency"] == "one_time" else "subscription"
|
||||
|
||||
checkout_session = stripe.checkout.Session.create(
|
||||
success_url=domain_url +
|
||||
"/success?session_id={CHECKOUT_SESSION_ID}",
|
||||
success_url=domain_url + "/success?session_id={CHECKOUT_SESSION_ID}",
|
||||
cancel_url=domain_url + "/canceled",
|
||||
payment_method_types= ["card"],
|
||||
payment_method_types=["card"],
|
||||
mode=mode,
|
||||
line_items=[
|
||||
{
|
||||
"price": price,
|
||||
"quantity": data['quantity']
|
||||
}
|
||||
]
|
||||
line_items=[{"price": price, "quantity": data["quantity"]}],
|
||||
)
|
||||
return jsonify({'sessionId': checkout_session['id']})
|
||||
return jsonify({"sessionId": checkout_session["id"]})
|
||||
except Exception as e:
|
||||
return jsonify(error=str(e)), 403
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=app.config['PORT'], debug=app.debug)
|
||||
if __name__ == "__main__":
|
||||
app.run(port=app.config["PORT"], debug=app.debug)
|
||||
|
|
Loading…
Add table
Reference in a new issue