-
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from Xpirix/stripe_scraping
Stripe scraping
- Loading branch information
Showing
3 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
|
||
""" stripe_donor_logger.cgi | ||
This scripts is to be run as a cgi on a public server. | ||
By creating a webhook at stripe for the payments to qgis/QGIS this | ||
script will be called, with the commit data as json (sent by striep). | ||
Given this data the script will do the following: | ||
- load the json and extract donationid, donorname and donordate | ||
- log success and errors to /tmp/stripehook.log | ||
- call the QGIS-Website/scripts/commit_donor.sh with the donorname as 1st arg | ||
- that script will: | ||
- git pull --rebase the QGIS-Website source | ||
- call the perl script which adds the donorname to the donors.json file | ||
- and commit this to github | ||
There is a special linux user created for this: stripe@qgis2. | ||
""" | ||
|
||
import sys | ||
import os | ||
import io | ||
import json | ||
import time | ||
from subprocess import Popen, PIPE | ||
|
||
|
||
def log(msg): | ||
with open('/tmp/stripehook.log', 'a', encoding="utf-8") as f: | ||
f.write('{}\n'.format(msg)) | ||
|
||
def test(): | ||
charge_success = '''{ | ||
"object": { | ||
"id": "ch_1CUyLrBBMqjyXePiy9wBoSW1", | ||
"object": "charge", | ||
"amount": 200, | ||
"amount_refunded": 0, | ||
"application": null, | ||
"application_fee": null, | ||
"balance_transaction": "txn_1CUx4ewrr3DBBMqjyXePig0uuohxp", | ||
"captured": true, | ||
"created": 1527082306, | ||
"currency": "eur", | ||
"customer": "cus_Cumd7sadfdegPGPUoVU", | ||
"description": "QGIS Donation", | ||
"destination": null, | ||
"dispute": null, | ||
"failure_code": null, | ||
"failure_message": null, | ||
"fraud_details": { | ||
}, | ||
"invoice": null, | ||
"livemode": true, | ||
"metadata": { | ||
"email": "[email protected]", | ||
"donorname": "אבלין李 克勤" | ||
}, | ||
"on_behalf_of": null, | ||
"order": null, | ||
"outcome": { | ||
"network_status": "approved_by_network", | ||
"reason": null, | ||
"risk_level": "normal", | ||
"seller_message": "Payment complete.", | ||
"type": "authorized" | ||
}, | ||
"paid": true, | ||
"receipt_email": null, | ||
"receipt_number": null, | ||
"refunded": false, | ||
"refunds": { | ||
"object": "list", | ||
"data": [ | ||
], | ||
"has_more": false, | ||
"total_count": 0, | ||
"url": "/v1/charges/ch_1CUx4dafaeeafABBMqjyXePi7Lu5EhcI/refunds" | ||
}, | ||
"review": null, | ||
"shipping": null, | ||
"source": { | ||
"id": "card_1CUx3tBBMqjydafdXePiM6yo4onz", | ||
"object": "card", | ||
"address_city": null, | ||
"address_country": null, | ||
"address_line1": null, | ||
"address_line1_check": null, | ||
"address_line2": null, | ||
"address_state": null, | ||
"address_zip": null, | ||
"address_zip_check": null, | ||
"brand": "Visa", | ||
"country": "NL", | ||
"customer": "cus_Cumddfa7sgPGPUoVU", | ||
"cvc_check": "pass", | ||
"dynamic_last4": null, | ||
"exp_month": 12, | ||
"exp_year": 1920, | ||
"fingerprint": "MzssdxRNkG8GPuXIaP2", | ||
"funding": "credit", | ||
"last4": "4242", | ||
"metadata": { | ||
}, | ||
"name": null, | ||
"tokenization_method": null | ||
}, | ||
"source_transfer": null, | ||
"statement_descriptor": null, | ||
"status": "succeeded", | ||
"transfer_group": null | ||
}, | ||
"previous_attributes": null | ||
}''' | ||
return charge_success | ||
|
||
def sent_content(status, msg): | ||
# http://www.restpatterns.org/HTTP_Status_Codes | ||
print('Status: {}'.format(status)) | ||
print('Content-Type: text/plain') | ||
print('') | ||
print('{}'.format(msg)) | ||
|
||
|
||
# THE ACTUAL CGI | ||
|
||
# TO TEST: make method GET and take one of the jsons from test() | ||
method = os.environ["REQUEST_METHOD"] | ||
|
||
# TODO: check the 'secret' == if the Stripe-Signature contains our SECRET | ||
SECRET='****' | ||
|
||
try: | ||
# TO TEST: make method GET and take one of the jsons from test() | ||
if method == "GET": | ||
rawdata = test() | ||
elif method == "POST": | ||
# duh, sys.stdin.read guesses the encoding... and in case of french guesses ascii: wrong! | ||
# https://stackoverflow.com/questions/16549332/python-3-how-to-specify-stdin-encoding | ||
# so instead of reading directly from sys.stdin we read via iowrapper: | ||
#rawdata = sys.stdin.read() | ||
content_length = int(os.environ.get('CONTENT_LENGTH', 0)) | ||
log(str(content_length) + ' content_length') | ||
if content_length > 0: | ||
|
||
# input_stream = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') | ||
# log(str(input_stream) + ' input_stream') | ||
# # Limit the size of the data read to the content_length | ||
# rawdata = input_stream.read(content_length) | ||
rawdata = sys.stdin.buffer.read(content_length) | ||
rawdata = rawdata.decode('utf-8') | ||
else: | ||
rawdata = '' | ||
else: | ||
sent_content(400, 'Illegal request') | ||
sys.exit(400) | ||
|
||
data = json.loads(rawdata) | ||
# sometimes not only the charge object is sent, but also the evt object surrounding it: | ||
if data['object']=='event': | ||
log('event received instead of charge...') | ||
data = data['data'] | ||
donationid = data['object']['id'] | ||
donationtime = time.asctime(time.gmtime(data['object']['created'])) | ||
donorname = data['object']['metadata'].get('donorname') | ||
if donorname is None or len(donorname)<1: | ||
# we promised to only publish the donorname if it was given! | ||
pass | ||
else: | ||
# casting to Title case | ||
donorname = donorname.title() | ||
# have to sent bytes utf-8 encoded to command?? | ||
#command = ['scripts/commit_donor.sh', donorname] | ||
command = ['scripts/commit_donor.sh', donorname] | ||
cwd = os.getcwd() | ||
result = Popen(command, cwd=cwd, stdout=PIPE, stderr=PIPE) | ||
(status, error) = result.communicate() | ||
if result.poll() == 0: | ||
log('Successfully add+commit of donation {} dd {} (UTC) by "{}" see https://dashboard.stripe.com/payments/{}'.format(donationid, donationtime, donorname, donationid)) | ||
else: | ||
log('ERROR add+commit of donation {} dd {} (UTC) by "{}" see https://dashboard.stripe.com/payments/{}'.format(donationid, donationtime, donorname, donationid)) | ||
log(error) | ||
sent_content(500, 'Some unexpected error occurred. Error text was: {}'.format(error)) | ||
sys.exit(500) | ||
# all fine: sent 200 back to Stripe | ||
sent_content(200, 'Ok') | ||
|
||
except Exception as error: | ||
log('ERROR in script: {}'.format(error)) | ||
sent_content(500, 'Some unexpected error occurred. Error text was: {}'.format(error)) | ||
sys.exit(500) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
This script should be run from the root repo directory (../) | ||
$ python scripts/add_donor.py "John Doe" | ||
It will update the json file (donors.json) | ||
ordered alphabetically by the first name. | ||
All names should start with a capital letter, | ||
names where all characters are capitalized | ||
should be converted to lower case letters | ||
(except for the first character of the name). | ||
Trailing dots or commas should be removed. | ||
If a name is already in the list, it should | ||
not be added again. | ||
""" | ||
|
||
import json | ||
import re | ||
import sys | ||
|
||
|
||
def log(msg): | ||
with open('/tmp/stripehook.log', 'a', encoding="utf-8") as f: | ||
f.write('{}\n'.format(msg)) | ||
|
||
# Function to clean and format names | ||
def format_name(name): | ||
# Remove trailing dots or commas | ||
name = re.sub(r'[.,]+$', '', name.strip()) | ||
|
||
# Ensure that the first letter of each word is capitalized | ||
# Convert to title case (first letter uppercase, others lowercase) | ||
name = name.title() | ||
return name | ||
|
||
|
||
# Function to update donors list with the new name | ||
def update_donors(new_donor_name, donors_json_file): | ||
# Read the existing donors from the JSON file | ||
try: | ||
with open(donors_json_file, 'r') as f: | ||
data = json.load(f) | ||
donors = data.get("donors", []) | ||
except FileNotFoundError: | ||
donors = [] | ||
data = {"donors": donors} | ||
|
||
# Clean and format the new donor's name | ||
new_donor = format_name(new_donor_name) | ||
|
||
# Add the new donor to the list if not already present | ||
if new_donor not in donors: | ||
donors.append(new_donor) | ||
|
||
# Sort donors alphabetically by first name | ||
donors.sort() | ||
|
||
# Write the updated donors list back to the JSON file | ||
with open(donors_json_file, 'w') as f: | ||
json.dump(data, f, ensure_ascii=False, indent=4) | ||
|
||
|
||
if __name__ == "__main__": | ||
if len(sys.argv) != 2: | ||
print("Usage: python add_donor.py \"John Doe\"") | ||
sys.exit(1) | ||
new_donor_name = sys.argv[1] # Name passed as argument | ||
log(f"Adding new donor: {new_donor_name}") | ||
donors_json_file = 'data/donors.json' # Path to the donors.json file | ||
|
||
# Update the donors list with the new name | ||
update_donors(new_donor_name, donors_json_file) | ||
print(f"Donor '{new_donor_name}' has been added and the list updated.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#!/usr/bin/env bash | ||
#!encoding: UTF-8 | ||
|
||
# Set the scripts directory as the current working directory | ||
# cd "${0%/*}" | ||
|
||
# Define log file | ||
LOG_FILE="/tmp/stripehook.log" | ||
|
||
# Log function to append messages to the log file | ||
log() { | ||
echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" >> "$LOG_FILE" | ||
} | ||
|
||
# Check if the script is already running | ||
if [ -f running ]; then | ||
log "$0 still running" | ||
exit 1 | ||
fi | ||
touch running | ||
|
||
# Log and execute git pull | ||
log "Executing git pull" | ||
git pull --rebase >> "$LOG_FILE" 2>&1 | ||
|
||
# Log and execute add_donor.py script | ||
log "Adding donor: $1" | ||
./scripts/add_donor.py "$1" >> "$LOG_FILE" 2>&1 | ||
|
||
# Log and execute git commit | ||
log "Committing donor $1" | ||
git commit -a -m "Donor $1 added" >> "$LOG_FILE" 2>&1 | ||
|
||
# Log and execute git push | ||
log "Pushing changes to origin main" | ||
git push origin main >> "$LOG_FILE" 2>&1 | ||
|
||
# Cleanup | ||
rm running | ||
log "Script completed successfully" | ||
|
||
# Deploy the changes | ||
# make deploy | ||
|
||
exit 0 |