BigCommerce
Email checker for BigCommerce. Verify customer emails at checkout and registration.
BigCommerce ストアに EmailVerify を統合し、チェックアウト時や顧客登録時にメールアドレスを検証しましょう。
連携方法
| 方法 | 最適な用途 | 複雑さ |
|---|---|---|
| Webhook | 注文後の検証 | 低 |
| スクリプトマネージャー | フロントエンド検証 | 中 |
| カスタムアプリ | フル連携 | 高 |
方法 1:Webhook 連携
顧客作成時や注文作成時に Webhook で検証をトリガーします。
Webhook のセットアップ
// BigCommerce Webhook ハンドラー
import express from 'express';
import crypto from 'crypto';
import EmailVerify from '@emailverify/node';
const app = express();
const bv = new EmailVerify(process.env.EMAILVERIFY_API_KEY);
// Webhook 署名の検証
function verifyWebhook(req) {
const signature = req.headers['x-bc-webhook-signature'];
const payload = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', process.env.BC_WEBHOOK_SECRET)
.update(payload)
.digest('base64');
return signature === expected;
}
// 顧客作成 Webhook
app.post('/webhooks/bigcommerce/customer-created', express.json(), async (req, res) => {
if (!verifyWebhook(req)) {
return res.status(401).send('Invalid signature');
}
const { data } = req.body;
const customerId = data.id;
// BigCommerce API から顧客詳細を取得
const customer = await getCustomer(customerId);
const email = customer.email;
// メールを検証
const result = await bv.verify({ email });
// 結果を保存
await saveVerificationResult(customerId, result);
// 無効なメールの場合は顧客にタグ付け
if (result.status === 'invalid' || result.result.disposable) {
await tagCustomer(customerId, 'email_risky');
}
res.sendStatus(200);
});
// 注文作成 Webhook
app.post('/webhooks/bigcommerce/order-created', express.json(), async (req, res) => {
if (!verifyWebhook(req)) {
return res.status(401).send('Invalid signature');
}
const { data } = req.body;
const orderId = data.id;
// BigCommerce API から注文詳細を取得
const order = await getOrder(orderId);
const email = order.billing_address.email;
// メールを検証
const result = await bv.verify({ email });
// 検証結果を注文メタデータに保存
await updateOrderMetafield(orderId, 'email_verification', {
status: result.status,
score: result.score,
disposable: result.result.disposable,
});
// リスクのある注文をフラグ
if (result.status === 'invalid' || result.result.disposable) {
await flagOrderForReview(orderId);
}
res.sendStatus(200);
});
async function getCustomer(customerId) {
// BigCommerce API 呼び出し
}
async function getOrder(orderId) {
// BigCommerce API 呼び出し
}
async function saveVerificationResult(customerId, result) {
// データベースまたは BigCommerce メタフィールドに保存
}
async function tagCustomer(customerId, tag) {
// BigCommerce API で顧客グループを更新
}
async function updateOrderMetafield(orderId, key, value) {
// BigCommerce API で注文メタフィールドを更新
}
async function flagOrderForReview(orderId) {
// 注文ステータスを更新または通知を送信
}
app.listen(3000);BigCommerce で Webhook を登録
BigCommerce API を使用して Webhook を登録:
const webhooks = [
{
scope: 'store/customer/created',
destination: 'https://yourapp.com/webhooks/bigcommerce/customer-created',
is_active: true,
},
{
scope: 'store/order/created',
destination: 'https://yourapp.com/webhooks/bigcommerce/order-created',
is_active: true,
},
];
for (const webhook of webhooks) {
await bigcommerce.post('/hooks', webhook);
}方法 2:スクリプトマネージャー
BigCommerce のスクリプトマネージャーを使用してフロントエンド検証を追加します。
検証スクリプト
<!-- BigCommerce スクリプトマネージャーに追加 -->
<script>
(function() {
const API_ENDPOINT = 'https://your-proxy-server.com/verify';
// チェックアウトページでのみ実行
if (!window.location.pathname.includes('/checkout')) {
return;
}
let verifyTimeout;
// メールフィールドを監視
const observer = new MutationObserver(function(mutations) {
const emailInput = document.querySelector('input[type="email"]');
if (emailInput && !emailInput.hasAttribute('data-bv-attached')) {
emailInput.setAttribute('data-bv-attached', 'true');
attachVerification(emailInput);
}
});
observer.observe(document.body, { childList: true, subtree: true });
function attachVerification(input) {
const statusEl = document.createElement('div');
statusEl.className = 'bv-status';
statusEl.style.cssText = 'margin-top: 5px; font-size: 12px;';
input.parentNode.appendChild(statusEl);
input.addEventListener('blur', function() {
const email = input.value;
if (!email || !isValidFormat(email)) {
statusEl.textContent = '';
return;
}
clearTimeout(verifyTimeout);
verifyTimeout = setTimeout(function() {
verifyEmail(email, statusEl, input);
}, 500);
});
}
function verifyEmail(email, statusEl, input) {
statusEl.textContent = '確認中...';
statusEl.style.color = '#666';
fetch(API_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email }),
})
.then(function(response) { return response.json(); })
.then(function(result) {
if (result.status === 'valid' && !result.result.disposable) {
statusEl.textContent = '✓ メール確認済み';
statusEl.style.color = '#28a745';
input.style.borderColor = '#28a745';
} else {
statusEl.textContent = '✗ 有効なメールアドレスを入力してください';
statusEl.style.color = '#dc3545';
input.style.borderColor = '#dc3545';
}
})
.catch(function() {
statusEl.textContent = '';
});
}
function isValidFormat(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
})();
</script>プロキシサーバー
API キーを保護するためのプロキシサーバー:
// proxy-server.js
import express from 'express';
import cors from 'cors';
import EmailVerify from '@emailverify/node';
const app = express();
const bv = new EmailVerify(process.env.EMAILVERIFY_API_KEY);
app.use(cors({
origin: ['https://your-store.mybigcommerce.com'],
}));
app.use(express.json());
app.post('/verify', async (req, res) => {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: 'Email required' });
}
try {
const result = await bv.verify({ email });
res.json(result);
} catch (error) {
res.status(500).json({ error: 'Verification failed' });
}
});
app.listen(3000);方法 3:カスタムアプリ
BigCommerce アプリとして完全な連携を構築します。
アプリの構造
// app.js
import express from 'express';
import BigCommerce from 'node-bigcommerce';
import EmailVerify from '@emailverify/node';
const app = express();
const bv = new EmailVerify(process.env.EMAILVERIFY_API_KEY);
// BigCommerce クライアント
const bigCommerce = new BigCommerce({
clientId: process.env.BC_CLIENT_ID,
accessToken: process.env.BC_ACCESS_TOKEN,
storeHash: process.env.BC_STORE_HASH,
responseType: 'json',
});
// 顧客一覧を取得して検証
app.get('/verify-customers', async (req, res) => {
const customers = await bigCommerce.get('/customers');
const results = [];
for (const customer of customers.data) {
const verification = await bv.verify({ email: customer.email });
results.push({
id: customer.id,
email: customer.email,
status: verification.status,
score: verification.score,
});
// メタフィールドを更新
await bigCommerce.put(`/customers/${customer.id}/metafields`, {
key: 'email_verification_status',
value: verification.status,
namespace: 'emailverify',
permission_set: 'read',
});
}
res.json(results);
});
// 一括検証ジョブ
app.post('/bulk-verify', async (req, res) => {
const { customerIds } = req.body;
// 非同期でジョブを開始
processCustomers(customerIds);
res.json({ message: 'Verification started' });
});
async function processCustomers(customerIds) {
for (const customerId of customerIds) {
const customer = await bigCommerce.get(`/customers/${customerId}`);
const verification = await bv.verify({ email: customer.email });
await bigCommerce.put(`/customers/${customerId}/metafields`, {
key: 'email_verification_status',
value: verification.status,
namespace: 'emailverify',
permission_set: 'read',
});
// レート制限を考慮
await sleep(100);
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
app.listen(3000);ベストプラクティス
1. Webhook 署名を検証
function verifyWebhook(req) {
const signature = req.headers['x-bc-webhook-signature'];
const payload = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', process.env.BC_WEBHOOK_SECRET)
.update(payload)
.digest('base64');
return signature === expected;
}2. API エラーを適切に処理
try {
const result = await bv.verify({ email });
// 結果を処理
} catch (error) {
console.error('検証に失敗:', error);
// エラー時は続行を許可
}3. 結果をキャッシュ
const cache = new Map();
const CACHE_TTL = 24 * 60 * 60 * 1000; // 24 時間
async function verifyWithCache(email) {
const cached = cache.get(email);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.result;
}
const result = await bv.verify({ email });
cache.set(email, { result, timestamp: Date.now() });
return result;
}