Enhance payment processing and rental features
- Updated the BTCPay service to support internal Lightning invoices with private route hints, improving payment routing for users with private channels. - Added reconciliation methods for pending rents and subscriptions to ensure missed payments are processed on startup. - Enhanced the rental and subscription services to handle payments in satoshis, aligning with Lightning Network standards. - Improved the rental modal and content detail components to display rental status and pricing more clearly, including a countdown for rental expiration. - Refactored various components to streamline user experience and ensure accurate rental access checks.
This commit is contained in:
@@ -30,18 +30,18 @@
|
||||
: 'text-white/60 hover:text-white'
|
||||
]"
|
||||
>
|
||||
Monthly
|
||||
1 Month
|
||||
</button>
|
||||
<button
|
||||
@click="period = 'annual'"
|
||||
@click="period = 'yearly'"
|
||||
:class="[
|
||||
'px-6 py-2 rounded-lg font-medium transition-all flex items-center gap-2',
|
||||
period === 'annual'
|
||||
period === 'yearly'
|
||||
? 'bg-white text-black'
|
||||
: 'text-white/60 hover:text-white'
|
||||
]"
|
||||
>
|
||||
Annual
|
||||
1 Year
|
||||
<span class="text-xs bg-orange-500 text-white px-2 py-0.5 rounded-full">Save 17%</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -64,12 +64,13 @@
|
||||
@click="selectedTier = tier.tier"
|
||||
>
|
||||
<h3 class="text-xl font-bold text-white mb-2">{{ tier.name }}</h3>
|
||||
<div class="mb-4">
|
||||
<div class="mb-4 flex items-baseline gap-1">
|
||||
<svg class="w-5 h-5 text-yellow-500 self-center" viewBox="0 0 24 24" fill="currentColor"><path d="M13 3l-2 7h5l-6 11 2-7H7l6-11z"/></svg>
|
||||
<span class="text-3xl font-bold text-white">
|
||||
${{ period === 'monthly' ? tier.monthlyPrice : tier.annualPrice }}
|
||||
{{ (period === 'monthly' ? tier.monthlyPrice : tier.annualPrice).toLocaleString() }}
|
||||
</span>
|
||||
<span class="text-white/60 text-sm">
|
||||
/{{ period === 'monthly' ? 'month' : 'year' }}
|
||||
sats / {{ period === 'monthly' ? '1 month' : '1 year' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -91,14 +92,14 @@
|
||||
class="hero-play-button w-full flex items-center justify-center"
|
||||
>
|
||||
<svg v-if="!isLoading" class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M13 10h-3V7H7v3H4v3h3v3h3v-3h3v-3zm8-6a2 2 0 00-2-2H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V4zm-2 0l.01 14H5V4h14z"/>
|
||||
<path d="M13 3l-2 7h5l-6 11 2-7H7l6-11z"/>
|
||||
</svg>
|
||||
<span v-if="!isLoading">Pay with Lightning — ${{ selectedPrice }}</span>
|
||||
<span v-if="!isLoading">Pay with Lightning — {{ Number(selectedPrice).toLocaleString() }} sats</span>
|
||||
<span v-else>Creating invoice...</span>
|
||||
</button>
|
||||
|
||||
<p class="text-center text-xs text-white/40 mt-4">
|
||||
Pay once per period. Renew manually when your plan expires.
|
||||
One-time payment. Renew manually when your plan expires.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
@@ -107,7 +108,7 @@
|
||||
<div class="text-center">
|
||||
<h2 class="text-2xl font-bold text-white mb-2">Pay with Lightning</h2>
|
||||
<p class="text-white/60 text-sm mb-1">
|
||||
{{ selectedTierName }} — {{ period === 'monthly' ? 'Monthly' : 'Annual' }}
|
||||
{{ selectedTierName }} — {{ period === 'monthly' ? '1 Month' : '1 Year' }}
|
||||
</p>
|
||||
<p class="text-white/40 text-xs mb-6">
|
||||
Scan the QR code or copy the invoice to pay
|
||||
@@ -123,10 +124,10 @@
|
||||
|
||||
<!-- Amount -->
|
||||
<div class="mb-4">
|
||||
<div class="text-lg font-bold text-white">
|
||||
{{ formatSats(invoiceData?.sourceAmount?.amount) }} sats
|
||||
<div class="text-lg font-bold text-white flex items-center justify-center gap-1">
|
||||
<svg class="w-5 h-5 text-yellow-500" viewBox="0 0 24 24" fill="currentColor"><path d="M13 3l-2 7h5l-6 11 2-7H7l6-11z"/></svg>
|
||||
{{ displaySats }} sats
|
||||
</div>
|
||||
<div class="text-sm text-white/60">≈ ${{ selectedPrice }} USD</div>
|
||||
</div>
|
||||
|
||||
<!-- Expiration Countdown -->
|
||||
@@ -229,7 +230,7 @@ const emit = defineEmits<Emits>()
|
||||
type PaymentState = 'select' | 'invoice' | 'success' | 'expired'
|
||||
|
||||
const paymentState = ref<PaymentState>('select')
|
||||
const period = ref<'monthly' | 'annual'>('monthly')
|
||||
const period = ref<'monthly' | 'yearly'>('monthly')
|
||||
const selectedTier = ref<string>('film-buff')
|
||||
const tiers = ref<any[]>([])
|
||||
const isLoading = ref(false)
|
||||
@@ -259,6 +260,17 @@ const selectedPrice = computed(() => {
|
||||
return period.value === 'monthly' ? tier.monthlyPrice : tier.annualPrice
|
||||
})
|
||||
|
||||
/**
|
||||
* Display sats — prefer invoice source amount (from BTCPay), fall back to tier price.
|
||||
*/
|
||||
const displaySats = computed(() => {
|
||||
const sourceAmount = invoiceData.value?.sourceAmount?.amount
|
||||
if (sourceAmount) {
|
||||
return formatSats(sourceAmount)
|
||||
}
|
||||
return Number(selectedPrice.value).toLocaleString()
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
tiers.value = await subscriptionService.getSubscriptionTiers()
|
||||
})
|
||||
@@ -372,7 +384,7 @@ async function handleSubscribe() {
|
||||
// Real API call — create Lightning subscription invoice
|
||||
const result = await subscriptionService.createLightningSubscription({
|
||||
type: selectedTier.value as any,
|
||||
period: period.value,
|
||||
period: period.value as 'monthly' | 'yearly',
|
||||
})
|
||||
|
||||
invoiceData.value = result
|
||||
|
||||
Reference in New Issue
Block a user