Add PaymentService integration to enhance ticket purchasing and lightning payment functionality
- Introduce PAYMENT_SERVICE token in di-container for dependency injection. - Update base module to register and initialize PaymentService, ensuring it is available for use. - Refactor useTicketPurchase and useLightningPayment composables to utilize PaymentService for wallet management, payment processing, and QR code generation. - Delegate payment handling and error management to PaymentService, streamlining the payment workflow and improving user experience.
This commit is contained in:
parent
adf32c0dca
commit
0bced11623
5 changed files with 372 additions and 137 deletions
|
|
@ -1,60 +1,36 @@
|
|||
import { ref, computed } from 'vue'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
import { computed } from 'vue'
|
||||
import { useMarketStore } from '../stores/market'
|
||||
import { payInvoiceWithWallet } from '@/lib/api/events'
|
||||
import { toast } from 'vue-sonner'
|
||||
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
|
||||
import type { PaymentService } from '@/core/services/PaymentService'
|
||||
|
||||
export function useLightningPayment() {
|
||||
const { isAuthenticated, currentUser } = useAuth()
|
||||
const paymentService = injectService(SERVICE_TOKENS.PAYMENT_SERVICE) as PaymentService
|
||||
const marketStore = useMarketStore()
|
||||
|
||||
// State
|
||||
const isPayingWithWallet = ref(false)
|
||||
const paymentError = ref<string | null>(null)
|
||||
|
||||
// Computed properties
|
||||
const userWallets = computed(() => currentUser.value?.wallets || [])
|
||||
const hasWalletWithBalance = computed(() =>
|
||||
userWallets.value.some((wallet: any) => wallet.balance_msat > 0)
|
||||
)
|
||||
// Computed properties - delegate to PaymentService
|
||||
const userWallets = computed(() => paymentService.userWallets)
|
||||
const hasWalletWithBalance = computed(() => paymentService.hasWalletWithBalance)
|
||||
const isPayingWithWallet = computed(() => paymentService.isProcessingPayment)
|
||||
const paymentError = computed(() => paymentService.paymentError)
|
||||
|
||||
// Get wallet with sufficient balance
|
||||
const getWalletWithBalance = (requiredAmount?: number) => {
|
||||
const wallets = userWallets.value
|
||||
if (!wallets.length) return null
|
||||
|
||||
if (requiredAmount) {
|
||||
return wallets.find((wallet: any) => wallet.balance_msat >= requiredAmount * 1000) // Convert sats to msat
|
||||
}
|
||||
|
||||
return wallets.find((wallet: any) => wallet.balance_msat > 0)
|
||||
// Get wallet with sufficient balance - delegate to PaymentService
|
||||
const getWalletWithBalance = (requiredAmountSats?: number) => {
|
||||
return paymentService.getWalletWithBalance(requiredAmountSats)
|
||||
}
|
||||
|
||||
// Pay Lightning invoice with user's wallet
|
||||
async function payInvoice(paymentRequest: string, orderId?: string): Promise<boolean> {
|
||||
if (!isAuthenticated.value || !currentUser.value) {
|
||||
throw new Error('User must be authenticated to pay with wallet')
|
||||
}
|
||||
|
||||
const wallet = getWalletWithBalance()
|
||||
if (!wallet) {
|
||||
throw new Error('No wallet with sufficient balance found')
|
||||
}
|
||||
|
||||
try {
|
||||
isPayingWithWallet.value = true
|
||||
paymentError.value = null
|
||||
|
||||
console.log('💰 Paying invoice with wallet:', wallet.id.slice(0, 8))
|
||||
|
||||
// Use the same API function as events
|
||||
const paymentResult = await payInvoiceWithWallet(paymentRequest, wallet.id, wallet.adminkey)
|
||||
|
||||
console.log('✅ Payment successful:', {
|
||||
paymentHash: paymentResult.payment_hash,
|
||||
feeMsat: paymentResult.fee_msat,
|
||||
orderId
|
||||
})
|
||||
// Use PaymentService with custom success message
|
||||
const paymentResult = await paymentService.payInvoiceWithUserWallet(
|
||||
paymentRequest,
|
||||
undefined, // No specific amount requirement
|
||||
{
|
||||
successMessage: orderId
|
||||
? `Order ${orderId.slice(-8)} has been paid`
|
||||
: 'Lightning invoice paid successfully'
|
||||
}
|
||||
)
|
||||
|
||||
// Update order status to paid if orderId is provided
|
||||
if (orderId) {
|
||||
|
|
@ -77,72 +53,56 @@ export function useLightningPayment() {
|
|||
}
|
||||
}
|
||||
|
||||
toast.success('Payment successful!', {
|
||||
description: orderId ? `Order ${orderId.slice(-8)} has been paid` : 'Lightning invoice paid successfully'
|
||||
})
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Payment failed'
|
||||
paymentError.value = errorMessage
|
||||
console.error('💸 Payment failed:', error)
|
||||
|
||||
toast.error('Payment failed', {
|
||||
description: errorMessage
|
||||
})
|
||||
|
||||
throw error
|
||||
} finally {
|
||||
isPayingWithWallet.value = false
|
||||
throw error // PaymentService already handled error notifications
|
||||
}
|
||||
}
|
||||
|
||||
// Open external Lightning wallet (fallback)
|
||||
// Open external Lightning wallet (fallback) - delegate to PaymentService
|
||||
function openExternalLightningWallet(paymentRequest: string) {
|
||||
if (!paymentRequest) {
|
||||
toast.error('No payment request available')
|
||||
return
|
||||
}
|
||||
|
||||
// Try lightning: protocol first
|
||||
const lightningUrl = `lightning:${paymentRequest}`
|
||||
|
||||
try {
|
||||
window.open(lightningUrl, '_blank')
|
||||
toast.info('Opening Lightning wallet...', {
|
||||
description: 'If no wallet opens, copy the payment request manually'
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn('Failed to open lightning: URL, showing payment request for copy:', error)
|
||||
// Fallback: copy to clipboard or show for manual copy
|
||||
navigator.clipboard?.writeText(paymentRequest).then(() => {
|
||||
toast.success('Payment request copied to clipboard')
|
||||
}).catch(() => {
|
||||
toast.info('Please copy the payment request manually')
|
||||
})
|
||||
}
|
||||
paymentService.openExternalLightningWallet(paymentRequest)
|
||||
}
|
||||
|
||||
// Main payment handler - tries wallet first, falls back to external
|
||||
async function handlePayment(paymentRequest: string, orderId?: string): Promise<void> {
|
||||
if (!paymentRequest) {
|
||||
toast.error('No payment request available')
|
||||
return
|
||||
}
|
||||
try {
|
||||
// Use PaymentService's automatic fallback handling
|
||||
const result = await paymentService.handlePaymentWithFallback(
|
||||
paymentRequest,
|
||||
undefined, // No specific amount requirement
|
||||
{
|
||||
successMessage: orderId
|
||||
? `Order ${orderId.slice(-8)} has been paid`
|
||||
: 'Lightning invoice paid successfully'
|
||||
}
|
||||
)
|
||||
|
||||
// Try wallet payment first if user has balance
|
||||
if (hasWalletWithBalance.value) {
|
||||
try {
|
||||
await payInvoice(paymentRequest, orderId)
|
||||
return // Payment successful with wallet
|
||||
} catch (error) {
|
||||
console.log('Wallet payment failed, offering external wallet option:', error)
|
||||
// Don't throw here, continue to external wallet option
|
||||
// If payment was successful with wallet, update order
|
||||
if (result && orderId) {
|
||||
const order = marketStore.orders[orderId]
|
||||
if (order) {
|
||||
const updatedOrder = {
|
||||
...order,
|
||||
paymentStatus: 'paid' as const,
|
||||
status: 'paid' as const,
|
||||
paidAt: Math.floor(Date.now() / 1000),
|
||||
paymentHash: result.payment_hash,
|
||||
feeMsat: result.fee_msat,
|
||||
items: [...order.items], // Convert readonly to mutable
|
||||
shippingZone: order.shippingZone ? {
|
||||
...order.shippingZone,
|
||||
countries: order.shippingZone.countries ? [...order.shippingZone.countries] : undefined
|
||||
} : order.shippingZone
|
||||
}
|
||||
marketStore.updateOrder(orderId, updatedOrder)
|
||||
}
|
||||
}
|
||||
// If result is null, external wallet was opened (fallback case)
|
||||
} catch (error) {
|
||||
// PaymentService already handled error notifications
|
||||
throw error
|
||||
}
|
||||
|
||||
// Fallback to external wallet
|
||||
openExternalLightningWallet(paymentRequest)
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue