Spaces:
Running
Running
| """ | |
| 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!'); | |
| } | |
| """, | |
| ) |