基于Shopify新OTP账户系统实现邮箱自动创建并登录新客户
解决方案概述
完全可以基于Shopify新的OTP账户系统实现你的需求,无需使用面向无头场景的Customer Account API。核心思路是结合Storefront API(前端查询客户)、你的自定义API-only应用后端(调用Admin API创建客户),再配合Shopify官方的OTP登录AJAX端点完成流程,完全适配主题内嵌JavaScript的场景。
步骤1:主题中添加邮箱登录UI
在主题模板(如customer/login.liquid或自定义section)中嵌入以下表单:
<div class="email-login-form"> <input type="email" id="customer-email" placeholder="输入你的邮箱" required> <button id="submit-email">提交并登录</button> <div id="otp-input-container" style="display:none;"> <input type="text" id="otp-code" placeholder="输入验证码" maxlength="6"> <button id="verify-otp">验证登录</button> </div> <div id="form-message" class="form-error"></div> </div>
步骤2:主题内嵌JavaScript逻辑
2.1 查询客户是否存在(Storefront API)
先在Shopify后台生成Storefront API令牌(需开启read_customers权限),然后用以下代码查询客户:
const STOREFRONT_TOKEN = '你的Storefront API令牌'; const SHOP_DOMAIN = '你的店铺域名.myshopify.com'; async function checkCustomerExists(email) { const query = ` query GetCustomer($email: String!) { customer(email: $email) { id } } `; const res = await fetch(`https://${SHOP_DOMAIN}/api/2024-07/graphql.json`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': STOREFRONT_TOKEN }, body: JSON.stringify({ query, variables: { email } }) }); const data = await res.json(); return !!data.data.customer; }
2.2 调用自定义后端创建客户
前端无法直接调用Admin API(会泄露令牌),所以需要你的API-only应用暴露一个接口,后端持有Admin API令牌并调用Shopify的POST /admin/api/{version}/customers.json接口创建客户。前端调用示例:
async function createCustomer(email) { const res = await fetch('https://你的应用域名/api/create-customer', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email }) }); return res.ok; }
2.3 OTP发送与登录验证逻辑
提交邮箱后,无论客户是否存在,都触发Shopify官方OTP端点,然后处理验证:
// 提交邮箱事件 document.getElementById('submit-email').addEventListener('click', async () => { const email = document.getElementById('customer-email').value.trim(); const msgEl = document.getElementById('form-message'); const otpContainer = document.getElementById('otp-input-container'); try { // 检查客户是否存在,不存在则创建 const exists = await checkCustomerExists(email); if (!exists) { const createSuccess = await createCustomer(email); if (!createSuccess) { msgEl.textContent = '创建客户失败,请重试'; return; } } // 发送OTP验证码 const otpRes = await fetch(`https://${SHOP_DOMAIN}/account/login/request`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, body: JSON.stringify({ email }) }); if (otpRes.ok) { msgEl.textContent = '验证码已发送至你的邮箱'; otpContainer.style.display = 'block'; } else { msgEl.textContent = '发送验证码失败,请重试'; } } catch (err) { msgEl.textContent = '请求出错,请重试'; console.error(err); } }); // 验证OTP并登录 document.getElementById('verify-otp').addEventListener('click', async () => { const email = document.getElementById('customer-email').value.trim(); const otpCode = document.getElementById('otp-code').value.trim(); const msgEl = document.getElementById('form-message'); try { const verifyRes = await fetch(`https://${SHOP_DOMAIN}/account/login/verify`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, body: JSON.stringify({ email, code: otpCode }) }); if (verifyRes.ok) { // 登录成功,跳转至账户页或刷新当前页 window.location.href = '/account'; } else { const errData = await verifyRes.json(); msgEl.textContent = errData.message || '验证码错误,请重试'; } } catch (err) { msgEl.textContent = '验证出错,请重试'; console.error(err); } });
关键注意事项
- Admin API安全:绝对不能在前端暴露Admin API令牌,必须通过你的后端代理调用。
- OTP端点限制:
/account/login/request和/account/login/verify是Shopify为主题提供的官方AJAX端点,无需额外授权,可直接在主题JS中调用。 - 自动登录局限性:新OTP系统强制要求验证码验证,无法完全“自动”登录,但可在创建客户后自动触发验证码发送,最大化简化用户操作。
内容的提问来源于stack exchange,提问作者afjaramilg-balto
相关产品推荐
相关产品推荐

