Skip to content

Commit 5078fe1

Browse files
authored
Merge pull request #398 from PyBotDevs/isocard-phase-4
Release Isocard System Final Phase (Phase 4)
2 parents 221b3d3 + c6b17e2 commit 5078fe1

File tree

4 files changed

+339
-11
lines changed

4 files changed

+339
-11
lines changed

cogs/isocard.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
import discord
55
import random
66
import json
7+
import math
8+
from framework.isobot.isocardtxn import IsoCardTxn
79
from framework.isobot.db.isocard import IsoCard
810
from discord import option, ApplicationContext, SlashCommandGroup
911
from discord.ext import commands
1012

1113
# Variables and Functions
1214
isocard_db = IsoCard()
15+
isocardtxn = IsoCardTxn()
1316

1417
def generate_card_id() -> int:
1518
# Generate 16 random digits and append to a str variable
@@ -126,8 +129,86 @@ async def verify_transaction(self, ctx: ApplicationContext, verification_code: i
126129
description="Please wait patiently until the merchant has verified the transaction.",
127130
color=discord.Color.green()
128131
)
132+
localembed.set_footer(text=f"Transaction ID: {transactions_db[str(verification_code)]['txn_id']}")
129133
await ctx.respond(embed=localembed, ephemeral=True)
130134
except KeyError: return await ctx.respond("This transaction verification code is invalid.")
131135

136+
@isocard.command(
137+
name="transaction_history",
138+
description="View all your past transactions (paid and received)"
139+
)
140+
@option(name="transaction_type", description="Which type of transactions do you want to view?", type=str, choices=["paid", "received"])
141+
@option(name="page", description="Select the page number that you want to view (1 page = 5 logs)", type=int, default=1)
142+
async def transaction_history(self, ctx: ApplicationContext, transaction_type: str, page: int = 1):
143+
"""View all your past transactions (paid and received)"""
144+
transactions_db = isocardtxn.fetch_raw()
145+
146+
if transaction_type == "paid":
147+
user_transactions_paid = {}
148+
for transaction in transactions_db:
149+
if str(transactions_db[transaction]["payer_id"]) == str(ctx.author.id):
150+
user_transactions_paid[transaction] = transactions_db[transaction]
151+
152+
# Initial Calculation for Pages
153+
total_pages = math.ceil(len(user_transactions_paid)/5)
154+
if page > total_pages: page = total_pages
155+
156+
log_entries = 0
157+
log_entries_offset = -((page-1)*5)
158+
parsed_output = str()
159+
sr = 0
160+
for transaction in user_transactions_paid:
161+
sr += 1
162+
log_entries_offset += 1
163+
if log_entries_offset > 0:
164+
log_entries += 1
165+
if log_entries <= 5:
166+
txn_data = user_transactions_paid[transaction]
167+
status = ""
168+
if txn_data['status'] == "Successful": status = ":white_check_mark: Successful"
169+
elif txn_data['status'] == "In Progress": status = ":arrows_counterclockwise: In Progress"
170+
elif txn_data['status'] == "Terminated (insufficient balance)": status = ":x: Terminated (insufficient balance)"
171+
elif txn_data['status'] == "Failed (unable to process payment)": status = ":warning: Failed (unable to process payment)"
172+
parsed_output += f"{sr}. **TXN ID:** `{transaction}`\n> <@!{txn_data['payer_id']}> -> <@!{txn_data['merchant_id']}> | Amount: {txn_data['amount']} | Card Used: `{txn_data['card_number']}`\n> Status: **{status}** | <t:{txn_data['timestamp']}:f>\n\n"
173+
localembed = discord.Embed(
174+
title=f"IsoCard Transaction History for **{ctx.author.name}** (paid)",
175+
description=parsed_output
176+
)
177+
localembed.set_footer(text=f"Page {page} of {total_pages}")
178+
return await ctx.respond(embed=localembed, ephemeral=True)
179+
180+
elif transaction_type == "received":
181+
user_transactions_received = {}
182+
for transaction in transactions_db:
183+
if str(transactions_db[transaction]["merchant_id"]) == str(ctx.author.id):
184+
user_transactions_received[transaction] = transactions_db[transaction]
185+
186+
# Initial Calculation for Pages
187+
total_pages = math.ceil(len(user_transactions_received)/5)
188+
if page > total_pages: page = total_pages
189+
190+
log_entries = 0
191+
log_entries_offset = -((page-1)*5)
192+
parsed_output = str()
193+
sr = 0
194+
for transaction in user_transactions_received:
195+
sr += 1
196+
log_entries_offset += 1
197+
if log_entries_offset > 0:
198+
log_entries += 1
199+
if log_entries <= 5:
200+
txn_data = user_transactions_received[transaction]
201+
status = ""
202+
if txn_data['status'] == "Successful": status = ":white_check_mark: Successful"
203+
elif txn_data['status'] == "Terminated (insufficient balance)": status = ":x: Terminated (insufficient balance)"
204+
elif txn_data['status'] == "Failed (unable to process payment)": status = ":warning: Failed (unable to process payment)"
205+
parsed_output += f"{sr}. **TXN ID:** `{transaction}`\n> <@!{txn_data['payer_id']}> -> <@!{txn_data['merchant_id']}> | Amount: {txn_data['amount']} | Card Used: `{txn_data['card_number']}`\n> Status: **{status}** | <t:{txn_data['timestamp']}:f>\n\n"
206+
localembed = discord.Embed(
207+
title=f"IsoCard Transaction History for **{ctx.author.name}** (received)",
208+
description=parsed_output
209+
)
210+
localembed.set_footer(text=f"Page {page} of {total_pages}")
211+
return await ctx.respond(embed=localembed, ephemeral=True)
212+
132213
# Initialization
133214
def setup(bot): bot.add_cog(IsoCard(bot))

framework/isobot/isocard.py

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import random
55
import logging
6+
from framework.isobot import isocardtxn as isocardtxn_
67
from api import auth
78
from flask import Flask
89
from flask import request
@@ -13,6 +14,7 @@
1314
log = logging.getLogger('werkzeug')
1415
log.setLevel(logging.ERROR)
1516
app = Flask('')
17+
isocardtxn = isocardtxn_.IsoCardTxn()
1618
currency = currency.CurrencyAPI("database/currency.json", "logs/currency.log")
1719

1820
def call_isocards_database() -> dict:
@@ -36,6 +38,16 @@ def generate_verification_code() -> int:
3638
code: str = int_1 + int_2 + int_3 + int_4 + int_5 + int_6
3739
return int(code)
3840

41+
def generate_txn_id() -> str:
42+
"""Generates a randomized transaction id, which is three *CAPITAL* letters followed by 6 numbers."""
43+
txn_id = str()
44+
for _ in range(3):
45+
txn_id += str(random.choice(('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', )))
46+
txn_id += "-"
47+
for _ in range(6):
48+
txn_id += str(random.randint(0, 9))
49+
return txn_id
50+
3951
# API Commands
4052
@app.route('/', methods=["GET"])
4153
def main():
@@ -53,8 +65,10 @@ def requestpayment():
5365
merchant_id = args.get("merchantid")
5466
if str(isocards[str(card_number)]["ssc"]) == ssc:
5567
verification_code = generate_verification_code()
68+
txn_id = generate_txn_id()
5669
user_id = isocards[str(card_number)]["cardholder_user_id"]
5770
transactions_db[str(verification_code)] = {
71+
"txn_id": txn_id,
5872
"payer_id": user_id,
5973
"merchant_id": merchant_id,
6074
"card_number": card_number,
@@ -63,9 +77,17 @@ def requestpayment():
6377
"status": "in_progress"
6478
}
6579
save(transactions_db)
80+
isocardtxn.write_to_log(
81+
txn_id=txn_id,
82+
payer_id=user_id,
83+
reciever_id=merchant_id,
84+
data=f"New transaction request started (txn_amount: {amount}; verification code: {verification_code})"
85+
)
86+
isocardtxn.write_transaction(txn_id, user_id, merchant_id, card_number, user_id, int(amount), "In Progress")
6687
request_data = {
6788
"code": 200,
6889
"message": f"Payment requested to IsoCard number: {card_number}. Payment will be complete once user accepts this.",
90+
"txn_id": txn_id,
6991
"verification_code": verification_code
7092
}
7193
return request_data, 200
@@ -81,38 +103,65 @@ def requestpayment():
81103

82104
@app.route('/checkpayment', methods=["GET"])
83105
def checkpayment():
106+
with open("database/isocard_transactions.json", 'r') as f: transactions_db = json.load(f)
84107
try:
85-
with open("database/isocard_transactions.json", 'r') as f: transactions_db = json.load(f)
86108
args = request.args
87109
verification_code = args.get("verificationcode")
110+
txn_id: str = transactions_db[str(verification_code)]["txn_id"]
88111
if transactions_db[str(verification_code)]["status"] == "complete":
89112
if currency.get_bank(transactions_db[str(verification_code)]["payer_id"]) < transactions_db[str(verification_code)]["amount"]:
113+
isocardtxn.write_to_log(
114+
txn_id=txn_id,
115+
payer_id=transactions_db[str(verification_code)]["payer_id"],
116+
reciever_id=transactions_db[str(verification_code)]["merchant_id"],
117+
data="Transaction has been terminated (reason: insufficient balance of the payer)"
118+
)
90119
del transactions_db[str(verification_code)]
120+
save(transactions_db)
121+
isocardtxn.update_transaction_status(txn_id, "Terminated (insufficient balance)")
91122
return {
92123
"code": 403,
124+
"txn_id": txn_id,
93125
"message": "Transaction terminated: Insufficient payer balance.",
94126
"exception": "InsufficientFunds"
95127
}, 403
96128
currency.bank_remove(transactions_db[str(verification_code)]["payer_id"], transactions_db[str(verification_code)]["amount"])
97129
currency.bank_add(transactions_db[str(verification_code)]["merchant_id"], transactions_db[str(verification_code)]["amount"])
130+
isocardtxn.write_to_log(
131+
txn_id=txn_id,
132+
payer_id=transactions_db[str(verification_code)]["payer_id"],
133+
reciever_id=transactions_db[str(verification_code)]["merchant_id"],
134+
data=f"Payment of {transactions_db[str(verification_code)]['amount']} coins has been successful"
135+
)
98136
del transactions_db[str(verification_code)]
99137
save(transactions_db)
138+
isocardtxn.update_transaction_status(txn_id, "Successful")
100139
return {
101140
"code": 200,
141+
"txn_id": txn_id,
102142
"message": "Transaction complete."
103143
}, 200
104144
else: return {
105145
"code": 202,
146+
"txn_id": txn_id,
106147
"message": "Transaction still not approved."
107148
}, 202
108149
except KeyError: return {
109150
"code": 404,
110151
"message": "Verification code does not point to an active transaction.",
111152
"exception": "TransactionNotFound"
112153
}, 404
113-
except Exception as e: return {
154+
except Exception as e:
155+
isocardtxn.write_to_log(
156+
txn_id=txn_id,
157+
payer_id=transactions_db[str(verification_code)]["payer_id"],
158+
reciever_id=transactions_db[str(verification_code)]["merchant_id"],
159+
data=f"Failed to process payment due to a server error (error: {e})"
160+
)
161+
isocardtxn.update_transaction_status(txn_id, "Failed (unable to process payment)")
162+
return {
114163
"code": 500,
115-
"message": f"Failed to process payment: {e}",
164+
"message": f"Failed to process payment due to an unhandled server error: {e}",
116165
"exception": type(e).__name__
117166
}, 500
118167

@@ -151,11 +200,13 @@ def account():
151200
# Initialization
152201
def run(): app.run(host="0.0.0.0", port=4800)
153202

154-
if auth.get_runtime_options()["isocard_server_enabled"]: # Run server ONLY if its runtime option is enabled
155-
print("[isocard/server] Starting IsoCard payments server...")
156-
t = Thread(target=run)
157-
t.daemon = True
158-
t.start()
203+
def deploy_server():
204+
"""Deploys the IsoCard Payments Server. (if the option is enabled in the runtimeconfig file)\n\nRuntimeconfig Option: `isocard_server_enabled`"""
205+
if auth.get_runtime_options()["isocard_server_enabled"]: # Run server ONLY if its runtime option is enabled
206+
print("[isocard/server] Starting IsoCard payments server...")
207+
t = Thread(target=run)
208+
t.daemon = True
209+
t.start()
159210

160211

161212
#btw i use arch

0 commit comments

Comments
 (0)