Demo shop is a simple Telegram Mini App providing basic e-commerce functionality. Try this Mini App using @DemoShopMACBot.
Mini Apps can be interpreted as web sites (frontend and backend) running inside Telegram and launched via bots. This Mini App consists of three parts:
- backend (back folder) - Go application using httprouter.
- bot (bot folder) - Go application using gotgbot.
- frontend (miniapp folder) - Vue application using Pinia, Vue Router and Tailwind CSS.
How to create a bot and get the bot token.
How to connect a payment provider and get the payment token.
Backend is based on http.Server - standard HTTP server and httprouter - HTTP request router. Server runs on the port 4001, and serves two API endpoints:
/goods
- GET-request to get the list of shop items. Data is returned as JSON payload./order
- POST-request to place the order. Order data is accepted as JSON request body. During the order processing invoice will be created via Bot API, it will be returned as JSON payload.
It also supports OPTIONS requests.
Backend can be configured with this environment variables:
TOKEN
- bot token (add/test
for test environment).PAY_TOKEN
- pament provider token.
Bot is based on gotgbot - Golang Telegram Bot library. Bot supports one command /start
, to which it responds with the Mini App link (HTTPS URL). It also processes pre_checkout_query
updates, positively replying to all queries.
Bot can be configured with this environment variables:
TOKEN
- bot token.TEST_ENV
- use Telegram test servers.URL
- Mini App HTTPS URL.
There are several ways to launch Mini App. This Mini App uses the next ones:
- When sending
/start
command to @DemoShopMACBot it answers with inline button Order goods which opens the Mini App. - Also @DemoShopMACBot has menu button Order goods which opens the Mini App. Menu button can be added/configured using @BotFather.
- Mini App can be opened by direct link (like
https://t.me/DemoShopMACBot/goods
). Direct link are created by linking Mini App to bot using @BotFather command/newapp
.
Demo shop Mini App is a SPA website created with Vue 3. It also uses Pinia for common state managment, Vue Router for routing and Tailwind CSS as CSS framework. Mini App consists of these main parts:
stores/base.ts
- base store instance, which contains shared state and logic for all pages/components, and interaction with API server (backend).views/GoodsView.vue
- page with the list of shop items.views/OrderView.vue
- page with the list of selected items and total price.components/BackButton.vue
,components/MainButton.vue
-WebApp.BackButton
andWebApp.MainButton
as Vue components.router/index.ts
- routes declaration and router instance.
- user presses the Pay button
- Mini App makes request to the backend, listing selected items
- backend via Bot API (
createInvoiceLink
method) creates invoice link and returns its URL in response - Mini App opens invoice using
WebApp.openInvoice
with provided URL - user fills in payment details, phone number and shipping address and proceed with payment
- Telegram sends
pre_checkout_query
update to the bot, to which it always respond positively WebApp.openInvoice
calls the specified callback with payment status
To build this project you need to install Go and Node.js.
Build backend:
cd back/
go mod download // this will install all dependencies
go build
For cross-compilation you can define GOOS and GOARCH environment variables prior to running
go build
.
Build bot:
cd bot/
go mod download
go build
Build frontend (Mini App) for production:
cd miniapp/
npm install // this will install all dependencies
npm run build // this will create hostable website in "dist/" folder
You should set
VITE_APP_API
parameter in.env.production
file, pointing to your backend server. More in Deploy section.
To help with local deployement we will be using ngrok as a HTTPS-enabling proxy to our HTTP backend and frontend (Mini App) instances. After installation add these lines to ngrok.yml
:
tunnels:
back:
proto: http
addr: 4001
miniapp:
proto: http
addr: 5173
4001 is a backend server port. 5173 is a local Node.js server port (you can see actual port after running
npm run dev
).
To start a proxy run ./ngrok start back miniapp
. The output will be something like this:
Session Status online
Account - (Plan: Free)
Version 3.3.5
Region Europe (eu)
Latency -
Web Interface http://127.0.0.1:4040
Forwarding https://SOME-GUID1.ngrok-free.app -> http://localhost:4001
Forwarding https://SOME-GUID2.ngrok-free.app -> http://localhost:5173
The first address (which points to port 4001) is a HTTPS URL of our backend server, it can be used as VITE_APP_API
parameter for the frontend (Mini App). And then second one (points to port 5173) is a frontend (Mini App) HTTPS URL, it can be used as URL
parameter for the bot.
For free accounts ngrok shows warning page on first visit. To skip it one can add non-empty
Ngrok-Skip-Browser-Warning
to request headers, it's essential for requests to backend.
Run backend:
export TOKEN="" // bot token
export PAY_TOKEN="" // payment token
./back/back
Run frontend:
cd miniapp/
npm run dev // this will start local Node.js server
You should set
VITE_APP_API
in.env
file, pointing to your backend server. Use ngrok proxy address for backend.
Run bot:
export TOKEN="" // bot token
export TEST_ENV="" // any value to use Telegram test servers, empty for production
export URL="" // ngrok proxy address for miniapp
./bot/bot
At this point you should have a VPS, domain name pointing to that VPS and SSL certificate issued to that domain name.
Next instructions applicable for Debian x64 VPS hosting.
Backend and bot should be cross-compiled for Linux x64 (GOOS="linux"
, GOARCH="amd64"
). Frontend will be hosted using nginx.
Upload files:
ssh %SRV% "mkdir -p /mac/back/"
scp back/back %SRV%:/mac/back/
ssh %SRV% "chmod +x /mac/back/back"
ssh %SRV% "mkdir -p /mac/bot/"
scp bot/bot %SRV%:/mac/bot/
ssh %SRV% "chmod +x /mac/bot/bot"
ssh %SRV% "mkdir -p /mac/miniapp/"
scp -r miniapp/dist/* %SRV%:/mac/miniapp/
scp -r misc/deploy/miniapp/images/ %SRV%:/mac/miniapp/
scp misc/deploy/nginx/miniapp %SRV%:/etc/nginx/sites-available/
%SRV% - vps address (user@server_ip).
Sample nginx configuration:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name domain.name www.domain.name;
ssl_certificate domain.name.bundle.cer;
ssl_certificate_key domain.name.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
root /mac/miniapp;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://localhost:4001/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
This configuration describes a HTTPS server with name "domain.name" listening on port 443 and secured with certificate domain.name.bundle.cer
/domain.name.key
. All connections to path /
maps to folder where our Vue application resides. All connections to path /api/
redirects to our backend server.
Run backend:
export TOKEN="" // bot token
export PAY_TOKEN="" // payment token
./back/back
Run frontend:
ln -s /etc/nginx/sites-available/miniapp /etc/nginx/sites-enabled/
systemctl restart nginx
Run bot:
export TOKEN="" // bot token
export TEST_ENV="" // empty for Telegram production servers
export URL="" // https://domain.name
./bot/bot
Open @DemoShopMACBot and run /start
command to open Demo shop Mini App.