Update: 2026-05-16 01:51:22

This commit is contained in:
Hamza-Ayed
2026-05-16 01:51:22 +03:00
parent 6e4dbf25ba
commit dec472dea9
7 changed files with 550 additions and 166 deletions

View File

@@ -1,37 +1,56 @@
package com.jordanbot.autoride
import android.os.Bundle
import android.widget.Button
import android.view.View
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.jordanbot.autoride.api.ActivateSubscriptionRequest
import com.jordanbot.autoride.api.ApiClient
import com.jordanbot.autoride.api.CheckPaymentRequest
import com.jordanbot.autoride.api.InitPaymentRequest
import com.jordanbot.autoride.subscription.SubscriptionManager
import com.jordanbot.autoride.utils.DeviceUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.*
class SubscriptionActivity : AppCompatActivity() {
private lateinit var tvStatus: TextView
private lateinit var btnBasic: Button
private lateinit var btnPro: Button
private lateinit var btnAnnual: Button
// Payment Overlay UI
private lateinit var layoutOverlay: LinearLayout
private lateinit var tvRefCode: TextView
private lateinit var tvTimer: TextView
private lateinit var btnCancel: Button
private var pollingJob: Job? = null
private var timerJob: Job? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_subscription)
tvStatus = findViewById(R.id.tv_current_status)
btnBasic = findViewById(R.id.btn_subscribe_basic)
btnPro = findViewById(R.id.btn_subscribe_pro)
btnAnnual = findViewById(R.id.btn_subscribe_annual)
layoutOverlay = findViewById(R.id.layout_payment_overlay)
tvRefCode = findViewById(R.id.tv_ref_code)
tvTimer = findViewById(R.id.tv_timer)
btnCancel = findViewById(R.id.btn_cancel_payment)
updateStatusUI()
btnBasic.setOnClickListener { activatePlan("basic") }
btnPro.setOnClickListener { activatePlan("pro") }
btnPro.setOnClickListener { startPaymentFlow("pro", 10.0) }
btnAnnual.setOnClickListener { startPaymentFlow("annual", 80.0) }
btnCancel.setOnClickListener {
stopPaymentFlow()
}
}
private fun updateStatusUI() {
@@ -40,39 +59,99 @@ class SubscriptionActivity : AppCompatActivity() {
val today = SubscriptionManager.ridesToday
val planText = when(plan) {
"basic" -> "أساسي ($limit طلب / يوم)"
"pro" -> "احترافي (لا محدود)"
"annual" -> "سنوي (لا محدود)"
else -> "مجاني (1 طلب / يوم)"
}
tvStatus.text = "الخطة الحالية: $planText\nاستهلاك اليوم: $today"
tvStatus.text = "الخطة الحالية: $planText\nاستهلاك اليوم: $today / $limit"
}
private fun activatePlan(plan: String) {
// In a real app, integrate payment gateway here.
// For demonstration, we just call the API directly.
private fun startPaymentFlow(plan: String, amount: Double) {
val fingerprint = DeviceUtils.getDeviceFingerprint(this)
lifecycleScope.launch {
try {
val response = withContext(Dispatchers.IO) {
ApiClient.service.activateSubscription(
ActivateSubscriptionRequest(fingerprint, plan, "DEMO_REF_123")
)
ApiClient.service.initPayment(InitPaymentRequest(fingerprint, plan, amount))
}
if (response.success) {
Toast.makeText(this@SubscriptionActivity, "تم تفعيل الاشتراك بنجاح!", Toast.LENGTH_SHORT).show()
// Re-check subscription to update local cache
SubscriptionManager.checkSubscription(this@SubscriptionActivity)
updateStatusUI()
if (response.success && response.reference_code != null) {
showPaymentOverlay(response.reference_code, amount)
startPolling(response.reference_code)
} else {
Toast.makeText(this@SubscriptionActivity, "فشل تفعيل الاشتراك: ${response.message}", Toast.LENGTH_SHORT).show()
Toast.makeText(this@SubscriptionActivity, "فشل إنشاء طلب الدفع", Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
Toast.makeText(this@SubscriptionActivity, "حدث خطأ في الاتصال", Toast.LENGTH_SHORT).show()
Toast.makeText(this@SubscriptionActivity, "حدث خطأ في الاتصال بالسيرفر", Toast.LENGTH_SHORT).show()
}
}
}
private fun showPaymentOverlay(refCode: String, amount: Double) {
tvRefCode.text = refCode
layoutOverlay.visibility = View.VISIBLE
// Start 10 minute timer
var secondsLeft = 600
timerJob?.cancel()
timerJob = lifecycleScope.launch {
while (secondsLeft > 0) {
val mins = secondsLeft / 60
val secs = secondsLeft % 60
tvTimer.text = "ننتظر وصول الدفعة... (${String.format("%02d:%02d", mins, secs)})"
delay(1000)
secondsLeft--
}
stopPaymentFlow()
Toast.makeText(this@SubscriptionActivity, "انتهى وقت طلب الدفع", Toast.LENGTH_LONG).show()
}
}
private fun startPolling(refCode: String) {
val fingerprint = DeviceUtils.getDeviceFingerprint(this)
pollingJob?.cancel()
pollingJob = lifecycleScope.launch {
while (isActive) {
delay(5000) // Poll every 5 seconds
try {
val response = withContext(Dispatchers.IO) {
ApiClient.service.checkPayment(CheckPaymentRequest(refCode, fingerprint))
}
if (response.status == "paid") {
onPaymentSuccess()
break
} else if (response.status == "expired") {
stopPaymentFlow()
Toast.makeText(this@SubscriptionActivity, "انتهت صلاحية الطلب", Toast.LENGTH_SHORT).show()
break
}
} catch (e: Exception) {
// Ignore connection errors during polling
}
}
}
}
private fun onPaymentSuccess() {
stopPaymentFlow()
Toast.makeText(this, "✅ تم تفعيل الاشتراك بنجاح!", Toast.LENGTH_LONG).show()
lifecycleScope.launch {
SubscriptionManager.checkSubscription(this@SubscriptionActivity)
updateStatusUI()
}
}
private fun stopPaymentFlow() {
pollingJob?.cancel()
timerJob?.cancel()
layoutOverlay.visibility = View.GONE
}
override fun onDestroy() {
super.onDestroy()
pollingJob?.cancel()
timerJob?.cancel()
}
}

View File

@@ -67,11 +67,24 @@ data class ActivateSubscriptionRequest(
)
@Keep
data class ActivateSubscriptionResponse(
data class InitPaymentRequest(val fingerprint: String, val plan: String, val amount: Double)
@Keep
data class InitPaymentResponse(
val success: Boolean,
val message: String?,
val plan: String?,
val expires_at: String?
val reference_code: String?,
val amount: Double?,
val cliq_alias: String?,
val expires_in_minutes: Int?
)
@Keep
data class CheckPaymentRequest(val reference_code: String, val fingerprint: String)
@Keep
data class CheckPaymentResponse(
val success: Boolean,
val status: String // pending, paid, expired
)
interface BackendApiService {
@@ -86,6 +99,12 @@ interface BackendApiService {
@POST("api/subscription/activate.php")
suspend fun activateSubscription(@Body request: ActivateSubscriptionRequest): ActivateSubscriptionResponse
@POST("api/subscription/init_payment.php")
suspend fun initPayment(@Body request: InitPaymentRequest): InitPaymentResponse
@POST("api/subscription/check_payment.php")
suspend fun checkPayment(@Body request: CheckPaymentRequest): CheckPaymentResponse
}
object ApiClient {

View File

@@ -1,163 +1,236 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1A1A2E"
android:fillViewport="true">
android:background="#121222">
<LinearLayout
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="💎 باقات التميّز"
android:textColor="#00D4AA"
android:textSize="28sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="سرّع عملك وضاعف دخلك اليوم"
android:textColor="#AAAAAA"
android:textSize="14sp" />
<!-- Current Status -->
<TextView
android:id="@+id/tv_current_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:background="@drawable/bg_card"
android:padding="12dp"
android:text="الحالة: جاري جلب البيانات..."
android:textAlignment="center"
android:textColor="#FFFFFF"
android:textSize="14sp" />
<!-- Pro Plan -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:elevation="4dp"
android:orientation="vertical"
android:padding="20dp"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="الخطة الاحترافية"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10.00 JOD / شهر"
android:textColor="#00D4AA"
android:textSize="20sp"
android:textStyle="bold" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginVertical="12dp"
android:background="#33FFFFFF" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="✅ طلبات غير محدودة (Unlimited)\n✅ أولوية قصوى في القبول\n✅ دعم جميع التطبيقات\n✅ فلاتر السعر والمسافة المتقدمة"
android:textColor="#CCCCCC"
android:textSize="13sp"
android:lineSpacingExtra="4dp" />
<Button
android:id="@+id/btn_subscribe_pro"
android:layout_width="match_parent"
android:layout_height="54dp"
android:layout_marginTop="16dp"
android:background="@drawable/bg_button_primary"
android:text="تفعيل عبر CliQ"
android:textColor="#FFFFFF"
android:textStyle="bold" />
</LinearLayout>
<!-- Annual Plan -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:orientation="vertical"
android:padding="20dp"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="الخطة السنوية (الأكثر توفيراً)"
android:textColor="#FFD700"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="80.00 JOD / سنة"
android:textColor="#00D4AA"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="وفر 40 دينار سنوياً مع تفعيل دائم\nشامل جميع التحديثات القادمة"
android:textColor="#AAAAAA"
android:textSize="13sp" />
<Button
android:id="@+id/btn_subscribe_annual"
android:layout_width="match_parent"
android:layout_height="54dp"
android:layout_marginTop="16dp"
android:background="@drawable/bg_button"
android:text="تفعيل سنوي عبر CliQ"
android:textColor="#FFFFFF" />
</LinearLayout>
</LinearLayout>
</ScrollView>
<!-- Payment Overlay (Hidden by default) -->
<LinearLayout
android:id="@+id/layout_payment_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F2121222"
android:gravity="center"
android:orientation="vertical"
android:padding="24dp">
android:padding="32dp"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="💳 الاشتراكات"
android:textColor="#00D4AA"
android:textSize="32sp"
android:text="انتظار الدفع عبر CliQ"
android:textColor="#FFFFFF"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="اختر الخطة المناسبة لعملك"
android:layout_marginTop="8dp"
android:text="يرجى إرسال المبلغ إلى الاسم المستعار التالي:"
android:textColor="#AAAAAA"
android:textSize="16sp" />
android:textAlignment="center" />
<TextView
android:id="@+id/tv_current_status"
android:layout_width="match_parent"
android:id="@+id/tv_cliq_alias"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="الخطة الحالية: مجاني (1 طلب / يوم)"
android:layout_marginTop="8dp"
android:text="JordanBot"
android:textColor="#00D4AA"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="الرقم المرجعي (هام جداً):"
android:textColor="#FFFFFF" />
<TextView
android:id="@+id/tv_ref_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#3300D4AA"
android:padding="12dp"
android:text="JB-XXXXXX"
android:textColor="#00D4AA"
android:textSize="32sp"
android:textStyle="bold"
android:layout_marginTop="8dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="⚠️ يجب كتابة الرقم أعلاه في خانة الملاحظات داخل تطبيق البنك لضمان التفعيل الآلي."
android:textColor="#FF5252"
android:textAlignment="center"
android:textColor="#FFFFFF"
android:textSize="16sp" />
android:textSize="12sp" />
<!-- Free Plan -->
<LinearLayout
android:layout_width="match_parent"
<ProgressBar
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="32dp"
android:indeterminateTint="#00D4AA" />
<TextView
android:id="@+id/tv_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:orientation="vertical"
android:padding="16dp"
android:layout_marginBottom="16dp">
android:layout_marginTop="8dp"
android:text="ننتظر وصول الدفعة... (10:00)"
android:textColor="#AAAAAA" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="المجانية"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0 JOD"
android:textColor="#00D4AA"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="• طلب واحد يومياً\n• تجربة الأساسيات"
android:textColor="#AAAAAA"
android:textSize="14sp" />
</LinearLayout>
<!-- Basic Plan -->
<LinearLayout
android:layout_width="match_parent"
<Button
android:id="@+id/btn_cancel_payment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:orientation="vertical"
android:padding="16dp"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="الأساسية"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1 JOD / شهر"
android:textColor="#00D4AA"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="• 10 طلبات يومياً\n• إحصائيات أساسية\n• فلاتر متقدمة"
android:textColor="#AAAAAA"
android:textSize="14sp" />
<Button
android:id="@+id/btn_subscribe_basic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:backgroundTint="#00D4AA"
android:textColor="#FFFFFF"
android:text="اشترك الآن" />
</LinearLayout>
<!-- Pro Plan -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:orientation="vertical"
android:padding="16dp"
android:layout_marginBottom="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="الاحترافية"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2.5 JOD / شهر"
android:textColor="#00D4AA"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="• طلبات غير محدودة\n• أولوية القبول\n• دعم فني مخصص"
android:textColor="#AAAAAA"
android:textSize="14sp" />
<Button
android:id="@+id/btn_subscribe_pro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:backgroundTint="#FF9800"
android:textColor="#FFFFFF"
android:text="اشترك الآن" />
</LinearLayout>
android:layout_marginTop="32dp"
android:background="?attr/selectableItemBackground"
android:text="إلغاء الطلب"
android:textColor="#888888" />
</LinearLayout>
</ScrollView>
</FrameLayout>