🏦

決済前に BIN をチェックして不正利用を防ぐ実装パターンまとめ(Stripe / PAY.JP / Square 対応)

に公開

はじめに

JP BIN Lookup API を使うと、
決済前に BIN(カード番号の最初の6桁)を照合して不正利用をブロックできます。

✔️ 海外BIN
✔️ プリペイド / デビット
✔️ ブランドごとの挙動
✔️ 発行会社ごとの成功率

こうしたリスク要因を 決済前に排除 できるため、
サブスク事業・EC事業・API従量課金などで非常に有効です。

本記事では、実際に使える Stripe / PAY.JP / Square の実装例 をまとめます。


なぜ「決済前に BIN をチェックする」のか?

カード不正の多くは BIN(先頭6桁)の時点でほぼ判別できます。

よくあるケース:

  • 海外BINから高額の不正注文が入る
  • 国内プリペイドカードで高額サブスク→未払い
  • Mastercardデビット=オーソリOKでも後日落ちない
  • 3Dセキュア非対応BINでのトラブル

JP BIN Lookup は日本国内の BIN に特化しており、
brand / type / issuer / level / 3ds などを返すため、
事業者側で柔軟にリスク管理ができます。


APIの呼び出し方法

GET https://api.jpbinlookup.com/v1/lookup?bin=457123
Authorization: Bearer {API_KEY}

レスポンス例:

{
  "bin": "457123",
  "brand": "Visa",
  "type": "Debit",
  "issuer": "三井住友銀行",
  "country": "JP",
  "level": "Classic",
  "prepaid": false,
  "3ds": true
}

Stripe の実装例(Node.js)

import Stripe from "stripe";
import fetch from "node-fetch";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

async function createCheckoutSession(cardBin) {

  // 1. BIN Lookup
  const r = await fetch(`https://api.jpbinlookup.com/v1/lookup?bin=${cardBin}`, {
    headers: { Authorization: `Bearer ${process.env.JP_BIN_API_KEY}` }
  });
  const bin = await r.json();

  // 2. 不正利用判定
  if (bin.country !== "JP") {
    throw new Error("海外BINのため決済を拒否します");
  }

  if (bin.type === "Prepaid") {
    throw new Error("プリペイドカードは現在ご利用いただけません");
  }

  // 3. Stripe 決済へ
  return await stripe.checkout.sessions.create({
    mode: "subscription",
    payment_method_types: ["card"],
    line_items: [
      {
        price: process.env.STRIPE_PRICE_ID,
        quantity: 1,
      },
    ],
    success_url: "https://example.com/success",
    cancel_url: "https://example.com/cancel",
  });
}

PAY.JP の実装例(JavaScript)

PAY.JP は payment_token 作成前に cardNumber を取得できるため、前段で BIN を照合可能。

async function beforePayJPCharge(cardNumber) {
  const bin = cardNumber.substring(0, 6);

  // BIN Lookup
  const r = await fetch(`https://api.jpbinlookup.com/v1/lookup?bin=${bin}`, {
    headers: { Authorization: `Bearer ${process.env.JP_BIN_API_KEY}` },
  });
  const info = await r.json();

  if (info.country !== "JP") {
    alert("海外発行カードのご利用はできません。");
    return;
  }

  if (info.type === "Prepaid") {
    alert("プリペイドカードでのご登録はできません。");
    return;
  }

  // PAY.JP トークンを作成
  const token = await Payjp.createToken(cardNumber);
  return token;
}

Square(Web Payments SDK)実装例

Square もカード番号前半を取得できるので同様に判定可能。

async function verifyBinBeforeSquarePayment(cardNumber) {
  const bin = cardNumber.slice(0, 6);

  const res = await fetch(`https://api.jpbinlookup.com/v1/lookup?bin=${bin}`, {
    headers: { Authorization: `Bearer ${process.env.JP_BIN_API_KEY}` }
  });
  const binInfo = await res.json();

  // ルール例
  if (binInfo.country !== "JP") {
    throw new Error("Square決済:海外BINは利用できません");
  }

  if (binInfo.type === "Debit" && binInfo.brand === "Mastercard") {
    throw new Error("Masterデビットは高額決済に利用不可");
  }

  return true;
}

まとめ

  • 不正利用の8割は BIN 情報で事前に防げる
  • JP BIN Lookup は 日本国内の BIN 特有の挙動に最適化
  • Stripe / PAY.JP / Square で共通して実装可能
  • 数行で導入できるため、小規模サービス〜大規模ECまで幅広く有効

JP BIN Lookup についての詳しい使い方は、今後も発信していきます。
質問や改善要望などあれば、お気軽にどうぞ!

https://jpbinlookup.com/

Discussion