Skip to Content
🎉 探索 Shopify 的无限可能 结构化知识 + 实战案例,持续更新中...
进阶教程Shopify实现订阅 LINE 到货通知

Shopify实现订阅 LINE 到货通知

在Shopify中实现 “订阅 LINE 到货通知” 功能,让客户能够在商品售罄时订阅通知,当商品补货时自动接收LINE消息。本文将提供完整的技术实现方案。


✅ 目标功能

让客户在商品售罄时,输入 LINE ID 或授权 LINE 登录,当商品补货时,自动通过 LINE 消息通知客户。


方案实现流程

一、准备工具和条件

项目工具或服务
客户订阅表单Shopify前端自定义代码
通知发送LINE 官方账号(Messaging API)
数据存储Shopify metafield / Shopify app / 外部数据库
通知触发Shopify Flow / Shopify App / 自建Webhook逻辑

二、设置 LINE 官方账号 & Messaging API

1. 创建 LINE 官方账号

  1. 访问 LINE Business Manager
  2. 创建新的商业账号
  3. 完成账号验证

2. 设置 Messaging API

  1. 在 LINE Developers Console 创建新的 Provider
  2. 创建”Messaging API”频道
  3. 获取重要信息:
    • Channel ID
    • Channel Secret
    • Access Token

3. 配置 Webhook

# Webhook URL 示例 https://your-app.herokuapp.com/webhook/line

三、Shopify 前端订阅逻辑

1. 添加订阅表单到商品页面

sections/product-form.liquid 或相关模板中添加:

<!-- 缺货时显示的 LINE 订阅表单 --> {% unless current_variant.available %} <div id="line-restock-notification" class="restock-form"> <h3>📢 商品补货通知</h3> <p>此商品暂时缺货,订阅 LINE 通知,补货时第一时间告知您!</p> <div class="line-subscription-form"> <input type="text" id="line-id-input" placeholder="请输入您的 LINE ID" class="form-input" /> <button onclick="subscribeLine()" class="btn btn-primary" id="subscribe-btn" > 订阅到货通知 </button> </div> <div id="line-result-msg" class="notification-msg"></div> <!-- 或者使用 LINE 登录按钮 --> <div class="line-login-option"> <p>或者使用 LINE 账号快速订阅:</p> <div id="line-login-btn" data-client-id="{{ settings.line_login_channel_id }}" data-redirect-uri="{{ shop.secure_url }}/apps/line-auth" > <img src="https://d.line-scdn.net/r/devcenter/downloadables/login_button/login_btn_base.png" alt="LINE登录"> </div> </div> </div> <style> .restock-form { border: 2px solid #00C300; border-radius: 8px; padding: 20px; margin: 20px 0; background: #f8fff8; } .line-subscription-form { display: flex; gap: 10px; margin: 15px 0; } .form-input { flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 4px; } .notification-msg { margin-top: 10px; padding: 10px; border-radius: 4px; } .notification-msg.success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; } .notification-msg.error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } </style> {% endunless %}

2. JavaScript 订阅逻辑

// assets/line-restock-notification.js function subscribeLine() { const lineId = document.getElementById("line-id-input").value.trim(); const subscribeBtn = document.getElementById("subscribe-btn"); const resultMsg = document.getElementById("line-result-msg"); // 验证输入 if (!lineId) { showMessage("请输入您的 LINE ID", "error"); return; } // 获取当前商品变体信息 const variantId = getSelectedVariantId(); const productId = {{ product.id }}; // 禁用按钮,防止重复提交 subscribeBtn.disabled = true; subscribeBtn.textContent = "订阅中..."; // 发送订阅请求 fetch("/apps/line-restock/subscribe", { method: "POST", headers: { "Content-Type": "application/json", "X-Shopify-Web-Token": "{{ form.authenticity_token }}" }, body: JSON.stringify({ lineId: lineId, variantId: variantId, productId: productId, productTitle: "{{ product.title | escape }}", variantTitle: getSelectedVariantTitle() }) }) .then(response => response.json()) .then(data => { if (data.success) { showMessage("订阅成功!商品补货时我们会立即通知您", "success"); document.getElementById("line-id-input").value = ""; } else { showMessage("订阅失败:" + (data.message || "请稍后重试"), "error"); } }) .catch(error => { console.error("订阅错误:", error); showMessage("网络错误,请稍后重试", "error"); }) .finally(() => { subscribeBtn.disabled = false; subscribeBtn.textContent = "订阅到货通知"; }); } function getSelectedVariantId() { // 获取当前选中的变体ID const variantSelect = document.querySelector('[name="id"]'); return variantSelect ? variantSelect.value : {{ product.selected_or_first_available_variant.id }}; } function getSelectedVariantTitle() { const variantSelect = document.querySelector('[name="id"]'); if (variantSelect) { const selectedOption = variantSelect.options[variantSelect.selectedIndex]; return selectedOption.textContent; } return "{{ product.selected_or_first_available_variant.title | escape }}"; } function showMessage(message, type) { const resultMsg = document.getElementById("line-result-msg"); resultMsg.textContent = message; resultMsg.className = `notification-msg ${type}`; // 3秒后自动清除消息 setTimeout(() => { resultMsg.textContent = ""; resultMsg.className = "notification-msg"; }, 3000); } // LINE 登录功能 function initLineLogin() { const lineLoginBtn = document.getElementById("line-login-btn"); if (lineLoginBtn) { lineLoginBtn.addEventListener("click", function() { const clientId = this.dataset.clientId; const redirectUri = this.dataset.redirectUri; const state = generateRandomString(32); const loginUrl = `https://access.line.me/oauth2/v2.1/authorize?` + `response_type=code&` + `client_id=${clientId}&` + `redirect_uri=${encodeURIComponent(redirectUri)}&` + `state=${state}&` + `scope=profile%20openid`; window.location.href = loginUrl; }); } } function generateRandomString(length) { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } // 页面加载时初始化 document.addEventListener('DOMContentLoaded', function() { initLineLogin(); });

四、后端 API 实现

1. Shopify App Proxy 设置

在 Shopify 合作伙伴后台设置 App Proxy:

Subpath prefix: apps Subpath: line-restock URL: https://your-server.com/shopify/proxy

2. 订阅 API 端点

// server.js (Node.js + Express 示例) const express = require('express'); const axios = require('axios'); const crypto = require('crypto'); const app = express(); app.use(express.json()); // LINE API 配置 const LINE_CHANNEL_ACCESS_TOKEN = process.env.LINE_CHANNEL_ACCESS_TOKEN; const LINE_CHANNEL_SECRET = process.env.LINE_CHANNEL_SECRET; // 数据库配置 (示例使用 MongoDB) const mongoose = require('mongoose'); // 订阅记录模型 const RestockSubscription = mongoose.model('RestockSubscription', { shopDomain: String, lineUserId: String, variantId: String, productId: String, productTitle: String, variantTitle: String, isActive: { type: Boolean, default: true }, createdAt: { type: Date, default: Date.now } }); // 处理订阅请求 app.post('/shopify/proxy/subscribe', async (req, res) => { try { const { lineId, variantId, productId, productTitle, variantTitle } = req.body; const shopDomain = req.get('X-Shopify-Shop-Domain'); // 验证 LINE ID 格式 if (!lineId || lineId.length < 3) { return res.json({ success: false, message: 'LINE ID 格式不正确' }); } // 检查是否已经订阅 const existingSubscription = await RestockSubscription.findOne({ shopDomain, lineUserId: lineId, variantId, isActive: true }); if (existingSubscription) { return res.json({ success: false, message: '您已经订阅了此商品的到货通知' }); } // 创建新的订阅记录 const subscription = new RestockSubscription({ shopDomain, lineUserId: lineId, variantId, productId, productTitle, variantTitle }); await subscription.save(); // 发送确认消息到 LINE await sendLineMessage(lineId, `订阅成功!\n\n商品:${productTitle}\n规格:${variantTitle}\n\n补货时我们会立即通知您!`); res.json({ success: true, message: '订阅成功' }); } catch (error) { console.error('订阅失败:', error); res.json({ success: false, message: '系统错误,请稍后重试' }); } }); // 发送 LINE 消息 async function sendLineMessage(userId, message) { try { await axios.post('https://api.line.me/v2/bot/message/push', { to: userId, messages: [{ type: 'text', text: message }] }, { headers: { 'Authorization': `Bearer ${LINE_CHANNEL_ACCESS_TOKEN}`, 'Content-Type': 'application/json' } }); } catch (error) { console.error('LINE 消息发送失败:', error.response?.data || error.message); } }

五、库存变更监听与通知发送

1. 设置 Shopify Webhook

在 Shopify 后台或通过 API 设置库存更新 Webhook:

// 注册 Webhook app.post('/webhooks/inventory/update', async (req, res) => { try { // 验证 Webhook 签名 const hmac = req.get('X-Shopify-Hmac-Sha256'); const body = JSON.stringify(req.body); const hash = crypto.createHmac('sha256', process.env.SHOPIFY_WEBHOOK_SECRET) .update(body, 'utf8') .digest('base64'); if (hash !== hmac) { return res.status(401).send('Unauthorized'); } const inventoryLevel = req.body; const variantId = inventoryLevel.inventory_item_id; // 检查库存是否从0变为有库存 if (inventoryLevel.available > 0) { await processRestockNotification(variantId); } res.status(200).send('OK'); } catch (error) { console.error('Webhook 处理错误:', error); res.status(500).send('Internal Server Error'); } });

2. 补货通知处理

async function processRestockNotification(variantId) { try { // 查找所有订阅此变体的用户 const subscriptions = await RestockSubscription.find({ variantId: variantId, isActive: true }); if (subscriptions.length === 0) { return; } // 获取商品信息 const variant = await getShopifyVariant(subscriptions[0].shopDomain, variantId); if (!variant) { console.error('无法获取变体信息:', variantId); return; } // 构建通知消息 const message = `🎉 好消息!您订阅的商品已经补货了!\n\n` + `商品:${subscriptions[0].productTitle}\n` + `规格:${subscriptions[0].variantTitle}\n` + `价格:${variant.price}\n\n` + `立即购买:${getProductUrl(subscriptions[0].shopDomain, subscriptions[0].productId, variantId)}\n\n` + `数量有限,先到先得!`; // 发送通知给所有订阅用户 const notifications = subscriptions.map(subscription => sendRestockNotification(subscription, message) ); await Promise.all(notifications); // 将订阅标记为已通知 await RestockSubscription.updateMany( { variantId: variantId, isActive: true }, { isActive: false, notifiedAt: new Date() } ); console.log(`补货通知已发送给 ${subscriptions.length} 位用户`); } catch (error) { console.error('补货通知处理错误:', error); } } async function sendRestockNotification(subscription, message) { try { await sendLineMessage(subscription.lineUserId, message); // 记录通知发送日志 console.log(`通知已发送: ${subscription.lineUserId} - ${subscription.productTitle}`); } catch (error) { console.error(`通知发送失败: ${subscription.lineUserId}`, error); } } function getProductUrl(shopDomain, productId, variantId) { return `https://${shopDomain}/products/${productId}?variant=${variantId}`; }

六、高级功能增强

1. LINE Rich Menu 集成

// 创建 Rich Menu async function createLineRichMenu() { const richMenu = { size: { width: 2500, height: 1686 }, selected: true, name: "购物助手菜单", chatBarText: "购物助手", areas: [ { bounds: { x: 0, y: 0, width: 1250, height: 843 }, action: { type: "postback", data: "action=view_subscriptions" } }, { bounds: { x: 1250, y: 0, width: 1250, height: 843 }, action: { type: "uri", uri: "https://yourshop.com" } } ] }; try { const response = await axios.post('https://api.line.me/v2/bot/richmenu', richMenu, { headers: { 'Authorization': `Bearer ${LINE_CHANNEL_ACCESS_TOKEN}`, 'Content-Type': 'application/json' } }); console.log('Rich Menu 创建成功:', response.data); return response.data.richMenuId; } catch (error) { console.error('Rich Menu 创建失败:', error.response?.data); } }

2. 取消订阅功能

// 处理 LINE Postback 事件 app.post('/webhook/line', (req, res) => { const events = req.body.events; events.forEach(async (event) => { if (event.type === 'postback') { const userId = event.source.userId; const data = new URLSearchParams(event.postback.data); const action = data.get('action'); switch (action) { case 'view_subscriptions': await handleViewSubscriptions(userId); break; case 'cancel_subscription': const variantId = data.get('variantId'); await handleCancelSubscription(userId, variantId); break; } } }); res.status(200).send('OK'); }); async function handleViewSubscriptions(userId) { try { const subscriptions = await RestockSubscription.find({ lineUserId: userId, isActive: true }); if (subscriptions.length === 0) { await sendLineMessage(userId, '您目前没有任何商品订阅'); return; } let message = '📋 您的订阅列表:\n\n'; subscriptions.forEach((sub, index) => { message += `${index + 1}. ${sub.productTitle}\n`; message += ` 规格:${sub.variantTitle}\n\n`; }); // 创建取消订阅的快捷回复 const quickReply = { items: subscriptions.map(sub => ({ type: 'action', action: { type: 'postback', label: `取消 ${sub.productTitle}`, data: `action=cancel_subscription&variantId=${sub.variantId}` } })) }; await sendLineMessage(userId, message, quickReply); } catch (error) { console.error('查看订阅失败:', error); } }

七、技术选项总结

目标实现方式推荐工具
客户授权/获取 Line IDLINE 登录 / 表单输入LINE Login API
储存订阅数据Metafields / 外部数据库MongoDB / PostgreSQL
自动检测库存变化Shopify WebhookInventory Levels Update
发送 LINE 消息LINE Messaging APINode.js/Express API
服务器部署云服务Heroku / Vercel / AWS

八、部署清单

环境变量配置

# .env LINE_CHANNEL_ACCESS_TOKEN=your_line_channel_access_token LINE_CHANNEL_SECRET=your_line_channel_secret LINE_LOGIN_CHANNEL_ID=your_line_login_channel_id SHOPIFY_API_KEY=your_shopify_api_key SHOPIFY_API_SECRET=your_shopify_api_secret SHOPIFY_WEBHOOK_SECRET=your_webhook_secret MONGODB_URI=your_mongodb_connection_string

Shopify 主题设置

config/settings_schema.json 中添加:

{ "name": "LINE 通知设置", "settings": [ { "type": "text", "id": "line_login_channel_id", "label": "LINE Login Channel ID" }, { "type": "checkbox", "id": "enable_line_restock_notification", "label": "启用 LINE 到货通知", "default": true } ] }

九、测试验证

1. 功能测试步骤

  1. 订阅测试:在缺货商品页面测试订阅功能
  2. 通知测试:手动触发库存更新,验证通知发送
  3. 取消订阅测试:通过 LINE 消息测试取消订阅
  4. 错误处理测试:测试各种异常情况的处理

2. 监控和日志

// 添加日志记录 const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'line-notifications.log' }) ] }); // 在关键操作中添加日志 logger.info('订阅创建', { userId: lineId, variantId, timestamp: new Date() });

十、优化建议

1. 性能优化

  • 使用消息队列处理大量通知
  • 实现通知发送的批量处理
  • 添加缓存机制减少数据库查询

2. 用户体验优化

  • 支持多语言通知消息
  • 添加商品图片到通知中
  • 实现智能推荐相关商品

3. 业务功能扩展

  • 支持价格降低通知
  • 添加 VIP 用户优先通知
  • 实现限时抢购提醒

通过以上完整的实现方案,您可以为 Shopify 商店添加强大的 LINE 到货通知功能,提升客户购物体验和商店转化率。

最后更新时间: