Vue 3 + Pinia 打造 Telegram 小程序商城:持久化购物车与结账流程
译注:本文编译自 dev.to 社区文章《Vue Catalog Mini App with Pinia Cart and Telegram Checkout》,作者为 serhii。原文链接见文末。文章以教程形式介绍如何构建一个基于 Vue 3 的 Telegram Mini App 前端,涵盖商品目录、由 Pinia 管理并借助
localStorage持久化的购物车,以及可通过 Telegram 机器人生成账单或跳转外部支付服务商的结账流程。
Telegram Mini App 正在成为轻量级电商的新入口。这篇教程完整演示了一个前端方案:使用 Vue 3 构建动态商品目录,用 Pinia 管理购物车状态,并通过 localStorage 实现跨会话持久化;结账环节则支持两种路径——由 Telegram 机器人生成账单,或跳转到外部支付服务商。
文章假设读者已经通过 @meta/telegram SDK 或 BotFather 配置好了 Telegram 机器人,并且后端已暴露用于开票和支付处理的接口。前端是一个自包含的 .vue 包,通过标准的 updateMessageId 模式与 webhook 通信。
一、项目初始化
首先用官方模板脚手架创建一个 Vue 3 项目:
npm create vite@latest telegram-catalog-miniapp --template vue
cd telegram-catalog-miniapp
npm install接着安装 Telegram 客户端 SDK 与 Pinia:
npm install @meta/telegram @meta/telegram-bot-sdk pinia在 .env 中配置机器人 token 与 webhook 地址:
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrSTU
WEBHOOK_URL=https://your-domain.com/webhook
PAYMENT_GATEWAY_API_KEY=sk_test_xxxxx二、Telegram 客户端集成
Mini App 的核心是 @meta/telegram SDK。它在每个会话中初始化一次,并通过 getUpdates() 方法接收来自服务端 webhook 的消息。
// src/store/cart.js
import { defineStore } from 'pinia'
import { inject, ref } from 'vue'
const TELEGRAM_CLIENT = inject('telegramClient')
// Initialize the client when the app starts
const initTelegram = async () => {
const token = process.env.TELEGRAM_BOT_TOKEN
if (!token) throw new Error('Telegram token missing')
await TELEGRAM_CLIENT.init({ token })
}
export const useCart = defineStore('cart', {
state: () => ({
items: [],
total: 0,
}),
actions: {
addToCart(product) {
// If item already exists, increase quantity; otherwise push new entry
const existing = this.items.find(i => i.id === product.id)
if (existing) {
existing.quantity += 1
} else {
this.items.push({
...product,
quantity: 1
})
}
this.total = this.items.reduce((sum, i) => sum + i.price * i.quantity, 0)
},
removeFromCart(id) {
this.items = this.items.filter(item => item.id !== id)
this.total = this.items.reduce((sum, i) => sum + i.price * i.quantity, 0)
},
clearCart() {
this.items = []
this.total = 0
}
}
})将购物车持久化到 localStorage,这样即使用户关闭 Mini App,再次打开时仍能保留此前的选择:
// src/stores/cart.js (persistence layer)
import { useCart } from './cart'
const saveCart = (items) => {
try {
localStorage.setItem('telegram-catalog-cart', JSON.stringify(items))
} catch (e) {
console.warn('Failed to persist cart', e)
}
}
const loadCart = () => {
try {
const raw = localStorage.getItem('telegram-catalog-cart')
return raw ? JSON.parse(raw) : []
} catch (e) {
console.error('Failed to load cart', e)
return []
}
}
export function usePersistedCart() {
const cartState = useCart()
const persisted = loadCart()
cartState.items = persisted
return { ...cartState, persisted }
}三、商品目录组件
目录组件负责展示从后端拉取的商品,每张商品卡片都支持加入或移出购物车。
<!-- src/components/ProductCatalog.vue -->
<template>
<div class="catalog">
<h1>Shop</h1>
<div v-for="product" :key="product.id" class="product-card">
<img :src="product.image" alt="Product" />
<h2>{{ product.name }}</h2>
<p>{{ product.description }}</p>
<span class="price">{{ formatPrice(product.price) }}</span>
<button @click="addToCart(product)">Add to Cart</button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useCart } from '@/stores/cart'
import { useTelegram } from '@/store/telegram' // see below
const product = ref(null)
const cart = useCart()
onMounted(() => {
// Fetch products from your API
fetch('/api/products')
.then(r => r.json())
.then(data => {
product.value = data[0] // or iterate over all
})
.catch(e => console.error('Failed to load products', e))
})
const addToCart = (prod) => {
cart.addToCart(prod)
// Optionally refresh cart state
const persisted = usePersistedCart().persisted
cart.items = persisted
}
const formatPrice = (price) => new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(price)
</script>
</vue>四、Telegram 客户端 Store
作者将 Telegram 客户端的初始化与消息处理封装进一个 store,使 UI 无需直接 import 即可响应更新。
// src/store/telegram.js
import { defineStore } from 'pinia'
import { inject, watch } from 'vue'
const TELEGRAM_CLIENT = inject('telegramClient')
// Listen for incoming updates
watch(
() => TELEGRAM_CLIENT.getUpdates(),
(updates) => {
if (updates.length > 0) {
updates.注:原文在此处截断,后续代码未完整给出。
小结
该教程展示了一条相对完整的 Telegram Mini App 电商前端链路:Vue 3 负责视图与交互,Pinia 承担购物车状态管理,localStorage 解决会话间的数据留存,Telegram SDK 则打通了消息与支付环节。对于希望在 Telegram 生态内快速搭建轻量商城的开发者,这套组合具备较强的可复用性。需要注意的是,文中部分代码(如 Telegram 客户端 store 的更新处理逻辑)在原文中并未完整呈现,实际落地时需结合官方 SDK 文档补全。