ヘッドレス側の実装と請求書払い

タグ読み取り、価格計算、クーポン自動適用、ドラフトオーダーの実装

ヘッドレスNext.jsクーポン自動適用請求書払いドラフトオーダー
読了時間: 13分

ヘッドレス側で実装すること

Shopify側の設定が完了したら、ヘッドレス(Next.js)側で以下を実装します。

  1. ログイン時にタグを取得
  2. タグから割引率を算出
  3. 会員価格を表示
  4. 決済時にクーポンを自動適用
  5. 請求書払いの処理(オプション)

ステップ1: ログイン時にタグを取得

お客様がログインしたら、Storefront APIを使ってタグ一覧を取得します。

GraphQLクエリ

query getCustomer($customerAccessToken: String!) {
  customer(customerAccessToken: $customerAccessToken) {
    id
    email
    tags
  }
}

レスポンス例

{
  "data": {
    "customer": {
      "id": "gid://shopify/Customer/12345",
      "email": "dealer@example.com",
      "tags": ["standard-35", "premium-25", "b2b-account"]
    }
  }
}

この顧客は standard-35premium-25 のタグを持っているので、2種類の割引が適用されます。

ステップ2: タグから割引率を算出

タグ名から割引率を抽出するロジックを実装します。

基本的な考え方

// タグ名: "standard-35"
// 抽出したい値: 35(割引率)

function getDiscountRateFromTag(tag: string): number | null {
  // タグ名の形式: カテゴリ-割引率
  const match = tag.match(/^(.+)-(\d+)$/);
  if (!match) return null;

  const discountRate = parseInt(match[2], 10);
  return discountRate;
}

// 使用例
getDiscountRateFromTag("standard-35"); // → 35
getDiscountRateFromTag("premium-25");  // → 25

カテゴリと割引率のマッピング

どのタグがどのコレクション(商品カテゴリ)に対応するかを設定ファイルで管理します。

// config/b2b-discounts.ts
export const B2B_DISCOUNT_CONFIG = [
  {
    tagPrefix: "standard",
    collectionHandle: "b2b-standard-products",
    // 割引率はタグ名から動的に取得
  },
  {
    tagPrefix: "premium",
    collectionHandle: "b2b-premium-products",
  },
  {
    tagPrefix: "elite",
    collectionHandle: "b2b-elite-products",
  },
  {
    tagPrefix: "special",
    collectionHandle: "b2b-special-products",
  },
];

ステップ3: 会員価格を表示

タグ情報をもとに、商品の会員価格を計算・表示します。

価格計算ロジック

function calculateMemberPrice(
  originalPrice: number,
  customerTags: string[],
  productCollections: string[]
): { memberPrice: number; discountRate: number } | null {

  for (const config of B2B_DISCOUNT_CONFIG) {
    // この商品が対象コレクションに含まれているか
    if (!productCollections.includes(config.collectionHandle)) {
      continue;
    }

    // 顧客がこのカテゴリの割引タグを持っているか
    const matchingTag = customerTags.find(tag =>
      tag.startsWith(`${config.tagPrefix}-`)
    );

    if (matchingTag) {
      const discountRate = getDiscountRateFromTag(matchingTag);
      if (discountRate) {
        const memberPrice = originalPrice * (1 - discountRate / 100);
        return { memberPrice, discountRate };
      }
    }
  }

  return null; // 割引対象外
}

カート画面での表示例

商品A(標準カテゴリ)
通常価格¥10,000
会員価格¥6,500(35%OFF)
商品B(プレミアムカテゴリ)
通常価格¥20,000
会員価格¥15,000(25%OFF)
元の合計
金額¥30,000
会員割引
金額-¥8,500
お支払い額
金額¥21,500

ステップ4: クーポンを自動適用

「購入手続きへ」ボタンを押したとき、タグ名と同名のクーポンを自動でカートに適用します。

処理の流れ

クーポン自動適用フロー
購入手続きへをクリック

カート内の商品を確認・各商品のコレクションを取得

顧客タグと照合

適用すべきタグを特定

クーポン適用

タグ名=クーポン名でカートに適用

Shopify決済画面へ遷移

割引が適用された状態

実装例(概念)

async function proceedToCheckout(
  cartId: string,
  customerTags: string[],
  cartItems: CartItem[]
) {
  // 適用すべきクーポン(タグ名)を特定
  const applicableCoupons = getApplicableCoupons(customerTags, cartItems);

  // 各クーポンをカートに適用
  for (const couponCode of applicableCoupons) {
    await applyDiscountCode(cartId, couponCode);
  }

  // チェックアウトURLを取得して遷移
  const checkoutUrl = await getCheckoutUrl(cartId);
  window.location.href = checkoutUrl;
}

function getApplicableCoupons(
  customerTags: string[],
  cartItems: CartItem[]
): string[] {
  const coupons: string[] = [];

  for (const item of cartItems) {
    for (const config of B2B_DISCOUNT_CONFIG) {
      // 商品が対象コレクションに含まれているか
      if (!item.collections.includes(config.collectionHandle)) {
        continue;
      }

      // 顧客がこのカテゴリの割引タグを持っているか
      const matchingTag = customerTags.find(tag =>
        tag.startsWith(`${config.tagPrefix}-`)
      );

      if (matchingTag && !coupons.includes(matchingTag)) {
        coupons.push(matchingTag); // タグ名 = クーポン名
      }
    }
  }

  return coupons;
}

お客様はコード入力不要

この仕組みにより、お客様はクーポンコードを知る必要も、入力する必要もありません。ログインしているだけで、自動的に割引が適用されます。

ステップ5: 請求書払い(掛け売り)機能

B2Bでは、クレジットカード払いではなく請求書払いのニーズがあります。

ドラフトオーダーを使った実装

Shopifyの「ドラフトオーダー(下書き注文)」機能を使って、請求書払いを実現します。

処理の流れ:

  1. お客様が「請求書払いで注文」を選択
  2. Admin APIでドラフトオーダーを作成
  3. ドラフトオーダーには以下の情報を記録:
    • 商品情報(会員価格適用後)
    • 割引率と節約額
    • 顧客情報
  4. 販売担当にメールで通知
  5. 確認後、請求書を発行

ドラフトオーダー作成の実装例

async function createInvoiceOrder(
  customer: Customer,
  cartItems: CartItemWithDiscount[]
) {
  const lineItems = cartItems.map(item => ({
    variantId: item.variantId,
    quantity: item.quantity,
    // 会員価格を適用
    appliedDiscount: {
      value: item.discountRate,
      valueType: "PERCENTAGE",
      title: `B2B割引(${item.discountRate}%OFF)`,
    },
  }));

  const draftOrder = await adminApi.draftOrderCreate({
    input: {
      lineItems,
      customerId: customer.id,
      note: `請求書払い注文\n割引タグ: ${customer.tags.join(", ")}`,
      tags: ["invoice-payment", "b2b-order"],
    },
  });

  // 担当者に通知
  await sendNotificationEmail({
    to: "sales@example.com",
    subject: `新規B2B注文(請求書払い): ${customer.email}`,
    body: `
      顧客: ${customer.email}
      合計金額: ¥${draftOrder.totalPrice}
      元の金額: ¥${draftOrder.subtotalPrice}
      割引額: ¥${draftOrder.totalDiscounts}
    `,
  });

  return draftOrder;
}

請求書払いのUI

クレジットカードで購入
説明Shopify決済へ進む
請求書払いで注文
説明後日請求書をお送りします(月末締め翌月末払い)

優先順位の管理

同じ商品に複数のルールが適用可能な場合の制御方法です。

設定例

export const B2B_DISCOUNT_CONFIG = [
  // 優先順位が高いものを先に定義
  {
    tagPrefix: "vip",
    collectionHandle: "b2b-vip-products",
    priority: 1, // 最優先
  },
  {
    tagPrefix: "standard",
    collectionHandle: "b2b-standard-products",
    priority: 2,
  },
  // ...
];

優先順位が高いルールが先にマッチしたら、それを適用して終了します。

まとめ

ヘッドレス側の実装ポイントを整理します。

タグ取得
実装内容Storefront API でログイン顧客のタグを取得
価格計算
実装内容タグから割引率を抽出し、会員価格を算出
価格表示
実装内容カート画面で通常価格と会員価格を並べて表示
クーポン適用
実装内容決済時にタグ名と同名のクーポンを自動適用
請求書払い
実装内容Admin API でドラフトオーダーを作成

この仕組みの最大のメリット:

  • コード変更不要: 新しいB2B顧客やカテゴリを追加しても、Shopify設定だけで対応
  • お客様体験: ログインするだけで自動的に会員価格が適用される
  • 運用効率: 設定ファイル1箇所の編集でカテゴリ追加可能

Shopify Plus不要で、通常プランでも本格的なB2B機能を実現できる設計です。

関連記事