khairul91's picture
Update app.py from anycoder
863b390 verified
Raw
History Blame Contribute Delete
19.8 kB
"""
Malaysia Telco Topup & SIM Card Purchase Application
Supports cryptocurrency payments (Bitcoin, Ethereum, USDT, etc.)
Built with Gradio 6 - Modern UI with themes
"""
import gradio as gr
import random
from datetime import datetime
from typing import Optional, Dict, Any
# Malaysian Telco Providers
TELCO_PROVIDERS = {
"Maxis": {
"plans": ["Hotlink Prepaid", "Maxis Postpaid", "Maxis Fibre"],
"min_amount": 5,
"max_amount": 500
},
"Celcom": {
"plans": ["Celcom Prepaid", "Celcom Postpaid", "Celcom Home Fibre"],
"min_amount": 5,
"max_amount": 500
},
"Digi": {
"plans": ["Digi Prepaid", "Digi Postpaid", "Digi Fibre"],
"min_amount": 5,
"max_amount": 500
},
"Telekom Malaysia": {
"plans": ["Unifi Mobile", "Streamyx", "Unifi Fibre"],
"min_amount": 10,
"max_amount": 1000
},
"U Mobile": {
"plans": ["U Prepaid", "U Postpaid", "U Fibre"],
"min_amount": 5,
"max_amount": 500
}
}
# Cryptocurrency Options
CRYPTO_OPTIONS = {
"Bitcoin (BTC)": {"symbol": "BTC", "network": "Bitcoin"},
"Ethereum (ETH)": {"symbol": "ETH", "network": "Ethereum"},
"USDT (BEP20)": {"symbol": "USDT", "network": "Binance Smart Chain"},
"USDT (ERC20)": {"symbol": "USDT", "network": "Ethereum"},
"BNB": {"symbol": "BNB", "network": "Binance Smart Chain"},
"USDC": {"symbol": "USDC", "network": "Ethereum"}
}
def validate_phone_number(phone: str) -> bool:
"""Validate Malaysian phone number format"""
if not phone:
return False
phone = phone.replace(" ", "").replace("-", "")
if len(phone) < 10 or len(phone) > 11:
return False
if phone[0] != '0':
return False
return True
def calculate_crypto_amount(myr_amount: float, crypto_type: str) -> Dict[str, Any]:
"""Calculate cryptocurrency equivalent amount (simulated rates)"""
rates = {
"Bitcoin (BTC)": 0.000015,
"Ethereum (ETH)": 0.00035,
"USDT (BEP20)": 0.22,
"USDT (ERC20)": 0.22,
"BNB": 0.0035,
"USDC": 0.22
}
rate = rates.get(crypto_type, 0.22)
crypto_amount = myr_amount * rate
return {
"crypto_amount": crypto_amount,
"rate": rate,
"symbol": CRYPTO_OPTIONS[crypto_type]["symbol"]
}
def process_topup(
telco: str,
plan: str,
phone_number: str,
amount: float,
crypto_type: str,
request: Optional[gr.Request] = None
) -> Dict[str, Any]:
"""Process the topup transaction with cryptocurrency payment"""
if not validate_phone_number(phone_number):
raise gr.Error("Nombor telefon tidak sah. Sila gunakan format Malaysia (contoh: 0123456789)")
if amount < TELCO_PROVIDERS[telco]["min_amount"]:
raise gr.Error(f"Amount terlalu rendah. Minimum untuk {telco} ialah RM{TELCO_PROVIDERS[telco]['min_amount']}")
if amount > TELCO_PROVIDERS[telco]["max_amount"]:
raise gr.Error(f"Amount terlalu tinggi. Maximum untuk {telco} ialah RM{TELCO_PROVIDERS[telco]['max_amount']}")
crypto_calc = calculate_crypto_amount(amount, crypto_type)
transaction_id = f"TXN{random.randint(100000, 999999)}{datetime.now().strftime('%Y%m%d%H%M%S')}"
result = {
"status": "success",
"transaction_id": transaction_id,
"telco": telco,
"plan": plan,
"phone_number": phone_number,
"amount_myr": amount,
"crypto_type": crypto_type,
"crypto_amount": crypto_calc["crypto_amount"],
"crypto_symbol": crypto_calc["symbol"],
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"wallet_address": f"0x{random.randint(1000000000, 9999999999)}...{random.randint(1000, 9999)}"
}
return result
def generate_transaction_summary(result: Dict[str, Any]) -> str:
"""Generate a formatted transaction summary"""
summary = f"""
## βœ… Transaksi Berjaya!
**ID Transaksi:** `{result['transaction_id']}`
### πŸ“± Butiran Topup
- **Telco:** {result['telco']}
- **Plan:** {result['plan']}
- **Nombor Telefon:** {result['phone_number']}
- **Amount (MYR):** RM {result['amount_myr']:.2f}
### πŸ’° Pembayaran Kripto
- **Jenis Kripto:** {result['crypto_type']}
- **Amount Kripto:** {result['crypto_amount']:.6f} {result['crypto_symbol']}
- **Wallet Address:** `{result['wallet_address']}`
### πŸ• Masa Transaksi
- **Tarikh:** {result['timestamp']}
---
**Status:** βœ… Completed
**Reference:** Simpan ID transaksi untuk rujukan masa hadapan.
"""
return summary
def get_available_plans(telco: str) -> list:
"""Get available plans for selected telco"""
if telco in TELCO_PROVIDERS:
return TELCO_PROVIDERS[telco]["plans"]
return []
def get_amount_range(telco: str) -> tuple:
"""Get min and max amount for selected telco"""
if telco in TELCO_PROVIDERS:
return (TELCO_PROVIDERS[telco]["min_amount"], TELCO_PROVIDERS[telco]["max_amount"])
return (5, 500)
def create_crypto_payment_info(crypto_type: str, amount: float) -> str:
"""Create cryptocurrency payment information display"""
if not crypto_type or amount <= 0:
return "Silakan pilih jenis kripto dan masukkan amount"
crypto_calc = calculate_crypto_amount(amount, crypto_type)
info = f"""
### πŸ’³ Maklumat Pembayaran
**Kripto:** {crypto_type}
**Symbol:** {crypto_calc['symbol']}
**Network:** {CRYPTO_OPTIONS[crypto_type]['network']}
**Amount MYR:** RM {amount:.2f}
**Amount Kripto:** {crypto_calc['crypto_amount']:.6f} {crypto_calc['symbol']}
**Rate:** 1 MYR = {crypto_calc['rate']} {crypto_calc['symbol']}
⚠️ **Nota:** Rate kripto berubah mengikut pasaran. Amount akhir mungkin berbeza sedikit.
"""
return info
def create_app():
"""Create the main Gradio application"""
with gr.Blocks() as demo:
# Header with branding
gr.Markdown("""
# πŸ“± Malaysia Telco Topup & SIM Card
### Beli topup internet & SIMkad dengan pembayaran kripto
<div style="text-align: center; margin: 10px;">
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="text-decoration: none;">
<span style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 8px 16px; border-radius: 20px; color: white; font-weight: bold; font-size: 14px;">
Built with anycoder πŸš€
</span>
</a>
</div>
""", elem_classes=["header-markdown"])
with gr.Tabs():
# Tab 1: Topup Purchase
with gr.TabItem("πŸ“± Topup Internet", id=1):
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### πŸ›’ Pilih Telco & Plan")
telco_dropdown = gr.Dropdown(
choices=list(TELCO_PROVIDERS.keys()),
label="Pilih Telco",
info="Pilih penyedia telekomunikasi",
value="Maxis"
)
plan_dropdown = gr.Dropdown(
choices=get_available_plans("Maxis"),
label="Pilih Plan",
info="Pilih plan/topup",
value="Hotlink Prepaid"
)
phone_input = gr.Textbox(
label="Nombor Telefon",
placeholder="Contoh: 0123456789",
info="Masukkan nombor telefon Malaysia",
max_length=11
)
amount_slider = gr.Slider(
minimum=5,
maximum=500,
value=30,
step=5,
label="Amount Topup (MYR)",
info="Pilih amount topup"
)
with gr.Column(scale=1):
gr.Markdown("### πŸ’° Pembayaran Kripto")
crypto_dropdown = gr.Dropdown(
choices=list(CRYPTO_OPTIONS.keys()),
label="Pilih Kripto",
info="Pilih cryptocurrency untuk pembayaran",
value="USDT (BEP20)"
)
crypto_info = gr.Markdown(
create_crypto_payment_info("USDT (BEP20)", 30),
elem_classes=["crypto-info"]
)
submit_btn = gr.Button(
"βœ… Beli Sekarang",
variant="primary",
size="lg"
)
clear_btn = gr.Button(
"πŸ”„ Reset",
variant="secondary"
)
with gr.Accordion("πŸ“‹ Hasil Transaksi", open=False):
transaction_result = gr.Markdown(
label="Transaction Summary",
elem_classes=["transaction-result"]
)
def update_plans(telco):
plans = get_available_plans(telco)
min_amt, max_amt = get_amount_range(telco)
return gr.Dropdown(
choices=plans,
value=plans[0] if plans else None
), gr.Slider(minimum=min_amt, maximum=max_amt)
telco_dropdown.change(
fn=update_plans,
inputs=[telco_dropdown],
outputs=[plan_dropdown, amount_slider]
)
def update_crypto_info(crypto_type, amount):
return create_crypto_payment_info(crypto_type, amount)
crypto_dropdown.change(
fn=update_crypto_info,
inputs=[crypto_dropdown, amount_slider],
outputs=[crypto_info]
)
amount_slider.change(
fn=update_crypto_info,
inputs=[crypto_dropdown, amount_slider],
outputs=[crypto_info]
)
def process_transaction(telco, plan, phone, amount, crypto):
try:
result = process_topup(telco, plan, phone, amount, crypto)
summary = generate_transaction_summary(result)
gr.Success(f"βœ… Transaksi berjaya! ID: {result['transaction_id']}")
return summary
except gr.Error as e:
gr.Error(str(e))
return f"❌ **Error:** {str(e)}"
submit_btn.click(
fn=process_transaction,
inputs=[telco_dropdown, plan_dropdown, phone_input, amount_slider, crypto_dropdown],
outputs=[transaction_result],
api_visibility="public"
)
clear_btn.click(
fn=lambda: (
"Maxis",
"Hotlink Prepaid",
"",
30,
"USDT (BEP20)",
create_crypto_payment_info("USDT (BEP20)", 30)
),
inputs=None,
outputs=[telco_dropdown, plan_dropdown, phone_input, amount_slider, crypto_dropdown, crypto_info],
api_visibility="undocumented"
)
# Tab 2: SIM Card Purchase
with gr.TabItem("πŸ“‡ SIM Card Baru", id=2):
gr.Markdown("""
### πŸ›’ Pilih SIM Card Package
Pilih package SIM card baru dari telco kegemaran anda.
Pembayaran mudah dengan cryptocurrency!
""")
with gr.Row():
with gr.Column():
sim_telco = gr.Dropdown(
choices=list(TELCO_PROVIDERS.keys()),
label="Pilih Telco",
value="Maxis"
)
sim_plan = gr.Dropdown(
choices=["SIM Only Prepaid", "SIM Only Postpaid", "SIM + Device"],
label="Pilih Package",
value="SIM Only Prepaid"
)
sim_name = gr.Textbox(
label="Nama Penuh",
placeholder="Nama seperti dalam kad pengenalan",
info="Nama untuk pendaftaran SIM"
)
sim_ic = gr.Textbox(
label="Nombor Kad Pengenalan",
placeholder="Contoh: 900101-14-5678",
info="No. IC untuk pendaftaran"
)
sim_delivery = gr.Radio(
choices=["Pos Laju", "Pickup Store", "Delivery Same Day"],
label="Kaedah Delivery",
value="Pos Laju"
)
with gr.Column():
sim_crypto = gr.Dropdown(
choices=list(CRYPTO_OPTIONS.keys()),
label="Pilih Kripto",
value="USDT (BEP20)"
)
sim_price = gr.Number(
label="Harga SIM (MYR)",
value=50,
minimum=10,
maximum=500
)
sim_info = gr.Markdown(
"**πŸ’° Info Pembayaran:**\n\nPembayaran akan dikira berdasarkan harga SIM + crypto rate semasa."
)
sim_submit = gr.Button("πŸ“‡ Order SIM Card", variant="primary")
sim_result = gr.Markdown(label="Order Summary")
def process_sim_order(telco, plan, name, ic, delivery, crypto, price):
if not name or not ic:
gr.Error("Sila masukkan nama dan nombor IC")
return "❌ **Error:** Maklumat tidak lengkap"
transaction_id = f"SIM{random.randint(100000, 999999)}{datetime.now().strftime('%Y%m%d%H%M%S')}"
crypto_calc = calculate_crypto_amount(price, crypto)
summary = f"""
## βœ… Order SIM Card Berjaya!
**ID Order:** `{transaction_id}`
### πŸ“‡ Butiran SIM Card
- **Telco:** {telco}
- **Package:** {plan}
- **Nama:** {name}
- **No. IC:** {ic}
- **Delivery:** {delivery}
- **Harga (MYR):** RM {price:.2f}
### πŸ’° Pembayaran Kripto
- **Kripto:** {crypto}
- **Amount:** {crypto_calc['crypto_amount']:.6f} {crypto_calc['symbol']}
**Status:** βœ… Processing
**Estimate Delivery:** 2-3 hari bekerja
"""
gr.Success(f"βœ… Order SIM berjaya! ID: {transaction_id}")
return summary
sim_submit.click(
fn=process_sim_order,
inputs=[sim_telco, sim_plan, sim_name, sim_ic, sim_delivery, sim_crypto, sim_price],
outputs=[sim_result],
api_visibility="public"
)
# Tab 3: Transaction History
with gr.TabItem("πŸ“Š History Transaksi", id=3):
gr.Markdown("""
### πŸ“Š Lihat History Transaksi
Semua transaksi topup dan SIM card akan disimpan di sini.
""")
history_table = gr.Dataframe(
headers=["ID", "Telco", "Type", "Amount (MYR)", "Crypto", "Status", "Date"],
datatype=["str", "str", "str", "number", "str", "str", "str"],
label="Transaction History",
interactive=False
)
sample_history = [
["TXN123456", "Maxis", "Topup", 30.00, "USDT", "Completed", "2024-01-15"],
["TXN123457", "Celcom", "Topup", 50.00, "BTC", "Completed", "2024-01-14"],
["SIM987654", "Digi", "SIM Card", 50.00, "ETH", "Processing", "2024-01-13"],
]
history_table.value = sample_history
gr.Markdown("""
**πŸ’‘ Tips:**
- Simpan ID transaksi untuk rujukan
- Contact support jika ada masalah
- Check status transaksi dalam 24 jam
""")
gr.Markdown("""
---
### ℹ️ Maklumat Tambahan
**Supported Telcos:** Maxis, Celcom, Digi, Telekom Malaysia, U Mobile
**Supported Crypto:** Bitcoin, Ethereum, USDT (BEP20/ERC20), BNB, USDC
**Processing Time:** Instant untuk topup, 2-3 hari untuk SIM card
**⚠️ Disclaimer:** Aplikasi ini adalah demo. Untuk penggunaan sebenar, sila integrate dengan payment gateway yang sah.
""", elem_classes=["footer-markdown"])
return demo
if __name__ == "__main__":
demo = create_app()
demo.launch(
theme=gr.themes.Soft(
primary_hue="blue",
secondary_hue="indigo",
neutral_hue="slate",
font=gr.themes.GoogleFont("Inter"),
).set(
button_primary_background_fill="*primary_600",
button_primary_background_fill_hover="*primary_700",
block_title_text_weight="600",
),
footer_links=[
{"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
{"label": "Gradio Docs", "url": "https://gradio.app/docs"},
],
css="""
.header-markdown {
text-align: center;
margin-bottom: 20px;
}
.crypto-info {
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
border-radius: 12px;
padding: 15px;
border: 1px solid #bde0fe;
}
.transaction-result {
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
border-radius: 12px;
padding: 15px;
border: 1px solid #fcd34d;
}
.footer-markdown {
text-align: center;
margin-top: 30px;
opacity: 0.8;
}
""",
js="""
function() {
console.log('Malaysia Telco Topup App loaded successfully!');
}
""",
)