mcpField
I
israeli-payment-orchestrator

israeli-payment-orchestrator

github.com/skills-il開発38156 回インストール1 日前に更新
リポジトリ

israeli-payment-orchestrator について

イスラエルの決済ゲートウェイを使った決済オーケストレーション設計のスキルです。機能比較、ルーティング、分割払い、金額単位の統一、安全な再試行と照合を扱います。

主な機能

  1. 01ゲートウェイ機能の比較
  2. 02各 API の金額単位の統一
  3. 03機能と稼働状態に基づく決済ルーティング
  4. 04分割払い方式のモデル化
  5. 05フォールバックと照合ロジックの設計

活用シーン

  1. 01必要な決済手段に応じたゲートウェイ選定
  2. 02障害時の取引ルーティング
  3. 03タイムアウト後の二重請求防止
  4. 04複数ゲートウェイ向け共通アダプターの構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/skills-il/tax-and-finance --skill israeli-payment-orchestrator

インストール後、Claude Code で/israeli-payment-orchestratorを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evidence.json
metadata.json
optimization-log.json
SKILL_HE.md
references/
domain-checklist.md
gateway-matrix.md
scripts/
compare_gateways.py

詳細

イスラエルの決済オーケストレーター

手順

ステップ 1:決済要件を確認する

ユーザーに決済ニーズについて尋ねます。

要件ヘブライ語説明ゲートウェイ選択への影響
分割払い(タシュルミーム)תשלומים支払いを月々の分割払いにするすべてのゲートウェイがあらゆる分割払いの種類に対応しているわけではありません
Bit / Apple Payביט / אפל פיי代替決済方法ゲートウェイ固有の連携
ステップ 2:ゲートウェイを比較する

scripts/compare_gateways.py を使って比較表を生成するか、以下の表を参照してください。

ゲートウェイAPI スタイル分割払い継続課金ホスト型ページBit金額フィールドの単位
CardcomREST JSON通常、クレジット対応リダイレクトまたは iframe(Low Profile)対応(UrlToBit)基本単位(小数)
Tranzilaフォームエンコード CGI(レガシー)+ REST JSON(API V2)通常、クレジット対応iframe、リダイレクト、または Hosted Fields対応(専用 Bit API、iframe では bit_pay=1)基本単位(小数)
PayMeREST JSON未確認未確認未確認未確認未確認、最初に確認してください
Meshulam (Grow)multipart/form-data通常、クレジット対応iframe + リダイレクト対応(cancelBitTransaction が存在)基本単位(小数)
iCreditWCF .svc サービス未確認未確認未確認未確認未確認、最初に確認してください
PelecardREST JSON通常、クレジット対応リダイレクトまたは iframe対応(pelecard-payment-gateway に記載)補助単位(アゴラ)

料金について:このスキルでは手数料の範囲を公開していません。 6 つのゲートウェイのうち、料金表を公開しているものはありません。加盟店割引率は契約条件であり、取引量、業種、チャージバックの状況に基づいて加盟店ごとに提示されます。また、このスキルの以前のバージョンには、どのベンダーも保証していないゲートウェイごとの料金範囲が記載されていました。架空の数値で最安のゲートウェイを示す比較表には、評価の根拠がありません。しかも、その順位は実際の交渉で生じるどの差よりも小さな違いで逆転します。ユーザーには各ゲートウェイに問い合わせ、書面で見積もりを取るよう案内してください。

「未確認」は「非対応」ではありません。 公開情報で機能の対応・非対応を確認できない場合、このスキルでは否定と推測せず、その旨を示します。**PayMe と iCredit は、行のほとんどの項目が未確認です。**機能がないからではなく、どちらも参照可能な API ドキュメントを公開していないためです。PayMe または iCredit に関する設計上の判断はすべて、事前にベンダーへ確認する必要があるものとして扱ってください。

各ゲートウェイについては、ゲートウェイごとのスキルが一次情報です。 フィールド名、エラーコード、認証ハンドシェイク、エンドポイントパスについては、cardcom-payment-gateway、tranzila-payment-gateway、grow-payment-gateway、pelecard-payment-gateway を参照してください。PayMe と iCredit には専用のスキルがありません。そのため、これらの項目のいくつかは「未確認」となっています。

ステップ 3:オーケストレーションレイヤーを設計する

統一された決済抽象化を構築します。

# Unified payment interface pattern
class PaymentRequest:
    action: str              # פעולה - "sale" (charge now) or "authorize" (hold now,
                             # capture later). Two different gateway calls, see Step 7.
    amount: int              # סכום - store ONE canonical unit, agorot, as an integer
                             # and convert per gateway on the way out (see below)
    currency: str            # מטבע - "ILS" default
    installments: int        # תשלומים - 1 = regular, 2-36 = installments
    installment_type: str    # סוג תשלומים - "regular", "credit", "club"
    card_token: str          # טוקן כרטיס - for recurring
    description: str         # תיאור עסקה
    customer_id: str         # מזהה לקוח
    idempotency_key: str     # מפתח אידמפוטנטי - prevent duplicates

class PaymentResult:
    outcome: str             # תוצאה - "approved" | "declined" | "unknown"
                             # NOT a bool: "unknown" is a real third state, see Step 6
    gateway_used: str        # שער תשלום שנבחר
    transaction_id: str      # מזהה עסקה
    approval_number: str     # מספר אישור
    shva_reference: str      # מספר שב"א
    gateway_status_code: str # קוד סטטוס גולמי - keep the vendor's own code, not just
    raw_response: dict       # the normalised outcome, so a parked or mis-mapped
                             # transaction stays auditable afterwards
    installment_details: dict

通貨単位の正規化はアダプター内で行い、呼び出し側では行わないでください。 ゲートウェイごとに金額フィールドの単位が異なります。Pelecard はアゴラ(補助単位)を受け取り、Grow はシェケルの小数値を受け取ります。それぞれのゲートウェイについては、専用スキル(pelecard-payment-gateway、grow-payment-gateway)が一次情報です。PayMe と iCredit にはスキルも参照可能な公開ドキュメントもないため、本番運用を開始する前に、1 シェケルのテスト決済で単位を確認してください。オーケストレーター内部では整数の共通単位を 1 つ使い、各ゲートウェイのアダプター内で変換します。100 倍の違いがあるのにアダプター間で共通の float 金額を使うと、どちらの方向でもエラーが発生します。そして、顧客から苦情が寄せられるまで、その間違いに気づけません。

ステップ 4:ゲートウェイのルーティングを実装する

最適なゲートウェイを選択するためのルーティングルールを定義します。

ルール優先度ロジック例
取消・精算コスト中加盟店が自社の契約から実際に把握できるコストに基づいてルーティングします取消の可能性が高い決済は、バッチが最も長く開いたままになるゲートウェイに送ります。取消では何も精算されませんが、返金では2回精算されるためです
機能の適合性高必要な機能に基づいてルーティングしますBit 対応の売上を、端末で Bit が有効になっているゲートウェイに送ります
可用性重大障害または性能低下が発生しているゲートウェイを避けてルーティングしますTranzila が停止した場合、Cardcom にフェイルオーバーします
ボリュームの分散低ゲートウェイ間で負荷を分散しますプライマリとセカンダリに 60/40 で振り分けます
カード種別高特定のカードをより適切に処理できるゲートウェイもありますDiners Club のルーティング

ルーティングロジック:

def select_gateway(request: PaymentRequest, gateways: list) -> str:
    # 1. Filter by feature support (tashlumim type, Bit, etc.)
    eligible = [g for g in gateways if g.supports(request)]
    # 2. Remove unhealthy gateways
    healthy = [g for g in eligible if g.is_healthy()]
    # 3. Sort by cost for this transaction type
    ranked = sorted(healthy, key=lambda g: g.priority_for(request))
    # Rank on merchant-configured priority, NOT on a fee table.
    # No Israeli gateway publishes rates, so a "cheapest gateway" sort
    # can only be built on invented numbers. See Step 2.
    # 4. Return best match (or raise if none available)
    if not ranked:
        raise NoGatewayAvailable()
    return ranked[0]
ステップ 5:分割払い(Tashlumim)を処理する

分割払いの方式は CreditType フィールド(Tranzila のレガシーインターフェースでは cred_type)で指定します。これは取引タイプ(סוג עסקה)とは別のものです。

ベンダーが公開している CreditType の値は 3 つだけです。 Tranzila の現行パラメータ表で公開されているのは、正確にこの 3 つ(1 は 1 回払い、6 はクレジット分割払い、8 は分割払い)です。Cardcom の v11 API スキーマでは CreditType のデフォルトが 1 で、6 のみが明示的に「6 - israel credit for multiple payments」と記載されています。

タイプヘブライ語CreditType仕組み利息の負担者
1 回払いתשלום אחד1即時に 1 回請求します該当なし
クレジット分割払いקרדיט6カード会社が資金を立て替え、顧客は利息を付けて分割払いします顧客がカード発行会社に利息を支払います
通常の分割払いתשלומים8加盟店には全額が支払われ、カード発行会社が顧客から毎月回収します顧客が負担します。デフォルトでは利息はありません
「無利息分割払い」תשלומים ללא ריבית8通常の分割払いと同じ wire 値です。加盟店が商業上、資金調達コストを負担します加盟店がコストを負担します

2、3、4、5、9 は送信しないでください。 以前のこのスキルのバージョンでは、ベンダーのドキュメントではなくサードパーティの統合ライブラリを根拠に、これらを「標準列挙値」として記載していました。現在のベンダーのパラメータ表にはどれもなく、Cardcom のスキーマにも含まれていません。Tranzila 自身のパラメータ表で公開されているのは 1、6、8 のみで、それ以外の値には応答コード表で 017 Unauthorized credit type for this transaction が返されます。特に、ルーティング可能な「クラブ分割払い=9」は存在しません。クラブやカード発行会社のロイヤルティプログラムは端末とカード発行会社の設定であり、コードで選択する CreditType ではありません。加盟店がそのような機能を必要とする場合は、フィールド値で指定するのではなく、アクワイアラーに相談してください。

実装上の注意:

  • 分割払いの上限は端末とカード発行会社の設定であり、ゲートウェイ共通の定数ではありません。ハードコードせず、対象端末の上限をアクワイアラーに確認してください。
  • カード発行会社のクレジット(CreditType 6)には、分割回数の下限が設定されています。Tranzila のドキュメントではクレジット分割払いの最低回数を 3 回とし、カード名義人がカード発行会社のクレジット承認を得ている必要があると説明しています。そのため、ゲートウェイとは無関係の理由でクレジット決済が失敗する場合があります。1 回あたりの最低金額はカード発行会社と端末の設定です。各ゲートウェイのスキルに記載されているため、ここではハードコードしないでください。
  • 「無利息分割払い」はアクワイアラーとの商業上の取り決めであり、wire 値ではありません。加盟店が資金調達コストを負担するため、顧客に利息は発生しません。補助率は加盟店ごとに異なり、公開されていないため、提示しないでください。
  • API V2 のインターフェースでは、cred_type が使われない場合があります。たとえば Tranzila では、代わりに payment_plan と installments_number が使用されます。別のインターフェースからパラメータ名をコピーする前に、どのインターフェースを使用しているかを確認してください。
ステップ 6:フォールバックと再試行のロジックを実装する

回復力のある決済処理を設計します。

# Fallback strategy
GATEWAY_PRIORITY = ["cardcom", "tranzila"]   # documented gateways only, see below

async def process_with_fallback(request: PaymentRequest) -> PaymentResult:
    last_error = None
    for gateway_name in GATEWAY_PRIORITY:
        gateway = get_gateway(gateway_name)
        if not gateway.is_healthy():
            continue  # דלג על שער לא זמין
        try:
            result = await gateway.charge(request)
            if result.outcome in ("approved", "declined"):
                return result       # both are settled answers, stop here
            # outcome == "unknown": the charge MAY have gone through.
            # Do not fail over. Park it for reconciliation.
            await park_for_reconciliation(request, gateway_name)
            raise OutcomeUnknown(gateway_name)
        except GatewayTimeoutError:
            # A timeout is NOT a failure. It is an unknown outcome.
            await park_for_reconciliation(request, gateway_name)
            raise OutcomeUnknown(gateway_name)
        except GatewayConnectFailed as e:
            # The request never reached the gateway, so nothing was charged.
            last_error = str(e)
            continue  # נסה שער הבא
    raise AllGatewaysFailedError(last_error)

3 つのルールがあります。3 つ目はコストがかかるルールです。

  1. 銀行による拒否(残高不足、盗難カード)の場合は、別のゲートウェイで決して再試行しないでください。結果は変わらず、カードに対する利用頻度チェックがフラグを立て始めます。
  2. リクエストがゲートウェイに到達していないことが確実な場合に限り、再試行してください(DNS エラー、接続拒否、TLS エラー)。
  3. 未検証のゲートウェイをフェイルオーバーチェーンに決して入れないでください。 ゲートウェイを優先リストに加えるのは、次の 3 点を確認してからにしてください。金額フィールドがどの単位を使うか、どの独自フィールドが冪等性キーを格納するか、そしてそのゲートウェイで請求を取り消す方法です。通貨単位を確認していないゲートウェイにフェイルオーバーすると、フォールバック経路そのものが 100 倍の誤りの原因になります。
  4. タイムアウトは失敗ではありません。 これは第 3 の結果であり、ここでフェイルオーバーするのは重複請求につながる典型的なバグです。Pelecard は独自のステータスコードでこの違いを明示しています。302 は「デビットに成功したが、加盟店が応答していない」という意味なので、実際に資金が移動しています。301 と 303 では、結果は本当に不明のままです。請求が発生したと示すのは 302 だけです。3 つすべてを「失敗、次のゲートウェイを試す」に割り当てるオーケストレーターは、最初の試行の応答が遅かった顧客全員に二重請求します。取引を保留し、ゲートウェイ独自の照会機能で結果を確認してから判断してください。

保留は作業の半分にすぎません。再試行をリリースする前に、照合の設計を済ませてください。 park_for_reconciliation は後で埋めるスタブではなく、不明な結果を再び金銭または商品に結び付ける仕組みです。最初の請求後ではなく、最初の請求前に次の 3 点を用意しておく必要があります。

  • 呼び出し前に保存し、後から取引を照会するために使えるキー。 リクエストがタイムアウトした時点では、ゲートウェイ独自の取引 ID はまだ存在しないため、照会キーにはできません。自分で管理するパススルーフィールドを使ってください。ここでは、互いに正反対のルールを持つ 2 種類のフィールドが使われます。混同すると、それ自体が二重請求につながります。 相関 ID は 1 回の試行を識別するため、試行ごとに一意であり、照合では注文 ID による前方一致を使います。Pelecard の ParamX はこの方式で機能し、<order-id>-<attempt-n> のように指定します。冪等性キー はゲートウェイが重複排除に使うため、論理上の請求ごとに固定し、再試行のたびに変更せず再送する必要があります。Grow の transactionUniqueIdentifier はこの方式で機能するため、試行ごとに新しい値を生成すると Grow 独自の重複検出が無効になります。値を生成する前に、各ゲートウェイのスキルで、対象フィールドがどちらの種類かを確認してください。
  • 再試行時にも同じキーを使うこと。 タイムアウトまたは 5xx エラーの際に、新しい冪等性キーで再送すると顧客への二重請求につながります。同じキーで再送するか、先に照合してください。
  • ゲートウェイごとの照会方法、ポーリング期間、そして最終判断(確定して出荷、返金、または担当者へのエスカレーション)。references/gateway-matrix.md には各ゲートウェイの照会呼び出しが記載されています。期間の終了時点でも不明なままなら、それは運用上のタスクであり、担当者を決める必要があります。この 3 つのメッセージは Pelecard 独自の文言であり、errorCode パラメーターを指定して /services/GetErrorMessageEn を呼び出せば、認証情報なしで取得できます。割り当てのないコードには、Pelecard の誤記である UnkownError が返されます。これにより、実在するコードと捏造したコードを見分けられます。再試行ロジックを書く前に、ルーティング対象となる各ゲートウェイについて、そのゲートウェイ独自のコード表をもとに同等の 3 状態マップを作成してください。
ステップ 7:オーソリ、取消、返金、一部返金を処理する

オーソリは売上ではなく、オーソリの解除は返金ではありません。 これらのゲートウェイの多くは、金額を今すぐ仮押さえし、後で回収する2段階のフローに対応しています(Pelecard ActionType J5、Tranzila verify_mode=5 / tranmode=V、Cardcom Operation: SuspendedDeal)。この仕組みを無視すると、2つの問題が起きます。オーソリを「承認済み」として記録し、キャプチャを実行しないオーケストレーターは、代金を回収できず、仮押さえも通知なく期限切れになります。また、返金呼び出しで仮押さえを解除するオーケストレーターは、誤った操作を使っています。Tranzilaでは cancel ではなく txn_type=reversal で与信枠を解除し、Pelecardでは DeleteTran ではなく /services/DeleteIshur で解除します。リクエストに action(ステップ3)を含め、void() と refund() に加えて capture() と release() もアダプターに用意してください。ゲートウェイごとの呼び出しについては references/gateway-matrix.md を参照してください。

すでに引き落とした資金を取り消す処理は、オーケストレーターだけが担う操作であり、ゲートウェイごとの差が最も大きい操作です。実装上、性質の異なる2つのアクションがあり、誤ったほうを選ぶと加盟店は二重のコストを負担します。

  • void(ביטול)は、決済確定前に取引を取り消します。クリアリングネットワークには到達しないため、クリアリング手数料は発生せず、通常、顧客に請求が表示されることもありません。
  • 返金/クレジット(זיכוי)は、すでに決済確定した請求に対する、新たな反対取引です。それ自体がクリアリングされるため、加盟店は両方の取引についてクリアリング手数料を支払います。

境目となるのは決済確定で、そのタイミングはすぐに訪れます。ほとんどの端末では、バッチは同じ営業日に締められます。この点を無視してコストを最適化するルーター(ステップ4)は、台帳の半分しか最適化していません。

ゲートウェイ決済確定前の void決済確定後の返金/クレジット一部返金
CardcomTransactions/RefundByTransactionId の CancelOnly: true(「取引の入金前に取り消しのみを行う」)CancelOnly を指定せず、同じエンドポイントを使用はい。PartialSum。AllowMultipleRefunds のデフォルトは false です
TranzilaAPI V2 で txn_type=cancel従来の tranmode=C{index}(別途 CreditPass 資格情報が必要)。API V2 では txn_type=creditはい
PayMe未確認api/refund-sale が存在します未確認
Meshulam(Grow)カードの void には対応していません。Bit のみ cancelBitTransaction に対応しています。これには pageCode が必要です。パラメーター一式を grow-payment-gateway で確認してくださいrefundTransaction を使用します。金額フィールドは refundSum で、sum は拒否されますはい。ただし、取引が決済確定または送信された後は実行できません。また、資金が銀行に届いた後は手動承認が必要です。Growは各ケースを個別のエラーコードで通知します。grow-payment-gateway を参照してください
iCredit未確認未確認未確認
Pelecardバッチが開いている間に /services/DeleteTran を使用します。/services/GetTransDataBeforeBc で、まだ void 可能な取引を確認できます/PaymentGW に返金エンドポイントはありません。クレジットは新たな反対取引です。パスを推測しないでくださいいいえ。DeleteTran は取引全体のみが対象です

設計時に考慮すべき点は3つあります。

  • 対称だと決めつけないでください。 返金処理は、金額にマイナスを付けた決済処理ではありません。Pelecardでは特に、合計金額を負の値で送ると、取消ではなく追加の課金が発生する可能性のほうが高くなります。
  • Bitの返金は、Bitに対応するすべてのゲートウェイで独自の処理経路になります。 Bitはカードのオーソリではなく、口座間の送金だからです。
  • 「未検証」のセルは、この表にある実際の未確認事項であり、「非対応」を意味するものではありません。 PayMeとiCreditについては、想定を前提に取消フローを構築する前に、ベンダーに確認してください。
  • 取引ごとに返金済み金額を自分で記録し、ゲートウェイを呼び出す前に過剰返金を拒否してください。 これを防止するかどうかはゲートウェイによって異なります。Cardcomではデフォルトで AllowMultipleRefunds が false ですが、Growでは元の合計金額を超えるまで連続して部分返金を受け付けます。ゲートウェイが検出してくれると頼ると、6つのうち1つでは防止できません。
  • 返金では、決済時には不要だった追加の認証情報が必要になることがよくあります。 Tranzilaの旧式のクレジット処理経路では、端末で有効化する必要がある別個の CreditPass が必要です。また、Cardcomの RefundByTransactionId では ApiPassword が必要ですが、同社の決済エンドポイントではまったく受け付けられません。エンドツーエンドで一度もテストされていない返金フローは、通常まさにこの点で失敗します。
  • 分割払いの返金はアクワイアラーによって異なり、単純に金額を回数で割るものではありません。 発行会社が残りの支払い請求を止めるかどうかや、すでに全額支払い済みの金額を加盟店からどのように回収するかは、アクワイアラーによって異なります。分割払いの取引で返金フローを稼働させる前に確認してください。
  • 返金期限はゲートウェイではなく法律で定められており、義務の対象は顧客が返金を受け取ることではなく、返金を実行することです。 クレジット処理は発行会社独自のサイクルで決済されるため、キューに入れたクレジットは、処理を依頼して放置するのではなく、状況を監視する必要があります。pelecard-payment-gateway には、消費者保護法の通信販売規則について、出典を明記した概要があります。これは概要であり、法令そのものではないものとして扱ってください。

python scripts/compare_gateways.py --refunds を実行すると、このマトリックスが出力されます。

Step 8: 規制への準拠を徹底する

イスラエル銀行およびShvaの規制を遵守してください。

規制ヘブライ語要件影響
取引データの保持שמירת נתוני עסקאות法定期間にわたり取引記録を保持する保持期間は税法および会計法で定められており、ゲートウェイやPCIによって定められているものではありません。消去ポリシーを設計する前に、税務当局または加盟店の会計士に現在の期間を確認してください。連携ガイドに記載された期間をそのまま流用しないでください
PCI DSSתקן PCIカードデータのセキュリティトークン化を使用し、カード番号全桁を保存しないでください。イスラエルのアクワイアラーは、国際基準に加えて現地の要件を課すことがあります
消費者保護הגנת הצרכן通信販売における法定のキャンセル権キャンセル可能期間、返金期限、キャンセル手数料の上限、特定の消費者層により長い期間が適用されるかどうかは、すべて消費者保護法およびその規則で定められており、ゲートウェイによって定められているものではありません。このスキルには、これらの内容は意図的に一切組み込まれていません。返金フローを構築する前に、消費者保護当局または法律顧問に確認してください
不正防止מניעת הונאה3D Secure、取引頻度のチェックCNP取引には3DS2を導入してください

例

例1:複数ゲートウェイの設定

ユーザーの要望:「分割払いに対応し、いずれかのゲートウェイが停止した場合に切り替えられるようにしたいです」 アクション:

  1. 評価:分割払い(通常およびクレジット)と高可用性。
  2. 比較:python scripts/compare_gateways.py --features installments,recurring を実行します。未検証ではなく、記録済みのセルがあるゲートウェイを2つ選びます。
  3. 設計:統一された金額単位、各ゲートウェイ固有のフィールドに対応付ける冪等性キー、3状態の結果。
  4. 実装:分割払いの取引をプライマリにルーティングし、接続失敗が確実に確認できた場合に限りフェイルオーバーします。 結果:プライマリ/フォールバックのルーティングと分割払い処理に対応するオーケストレーション層
例2:Bitを追加する場合

ユーザーの発言:「Tranzilaを使っていますが、Bitで決済を受け付けられるようにPayMeも追加したいです」 対応:

  1. まず前提を確認します。Tranzilaは専用のBit APIと、iframeで指定するbit_pay=1フラグを使って、すでにBitに対応しています。Cardcom(UrlToBit)、Grow、Pelecardも同様です。現在のゲートウェイにすでにある機能を利用するために、2つ目のゲートウェイを丸ごと追加するのは、何も得られない大規模な連携作業です。
  2. ゲートウェイではなく、端末を確認します。Bitを使うには、アクワイアラーが加盟店の端末で有効にする必要があります。「APIが対応している」ことと「端末で利用できるよう設定されている」ことは別の問題で、利用を妨げるのは後者です。
  3. Bitに振り分ける前に、アクワイアラーと各ゲートウェイのスキルを参照して、Bit固有の制約を確認します。この表ではなく、そちらを確認してください。Bitは口座間のプッシュ決済であり、適用される制約はカード決済のものとは異なります。分割払い、通貨、取引額と月間金額に制限があり、取消しの手順もカード決済とは異なると想定してください。加盟店の端末に適用される実際の数値を確認してください。Bitを単なる真偽値として扱うルーターでは、Bitでは処理できない売上を送信し、最悪のタイミングで失敗します。
  4. 2つ目のゲートウェイが必要になるのは、端末をどうしても利用可能な状態に設定できない場合だけです。その場合の判断は技術的なものではなく、商業上のものです。 結果:ほとんどの場合、2つ目の連携ではなく、有効化の問い合わせ1回で済みます
例3:コストの比較

ユーザーの発言:「1日あたり500件、平均200 NISの取引を処理する場合、どのゲートウェイが最も安いですか?」 対応:

  1. 公開情報だけでは誰にも答えられないことを率直に伝えます。6社のいずれも料金表を公開しておらず、料率は取引量、業種、チャージバックの状況に応じて加盟店ごとに交渉されます。勝者を示す表があれば、必要な情報をでっち上げていることになります。
  2. 実際に判断材料となる情報を提示します。交渉時に伝える月間取引額は、ここでは500 * 30 * 200 = 3,000,000 NISです。この取引量で各ゲートウェイから書面で見積もりを取るよう案内します。
  3. 割引後の料率には表れず、この規模では日常的に大きな影響を与えるコストを挙げます。加盟店が負担する無利息分割払いの利息、入金サイクルに伴う運転資金コスト、返金ごとおよびチャージバックごとの手数料、さらに売上と返金の組み合わせでは決済が2回処理される一方、オーソリ取消しでは一度も処理されないことです。
  4. 機能が分かる範囲では、機能面で比較します。python scripts/compare_gateways.py --example 結果:誤った順位付けではなく、交渉材料と機能比較を得られます

同梱リソース

スクリプト
  • scripts/compare_gateways.py -- 6つのゲートウェイの機能マトリックスと、取消し/返金/一部返金のマトリックスを出力します。文書化された機能で絞り込み、認識できない機能名は、すべてに暗黙的に一致させるのではなく、エラーとして拒否します。意図的にコストの見積もりは行いません。実行方法:python scripts/compare_gateways.py --help、--example、--refunds、--features bit
参考資料
  • references/gateway-matrix.md -- ゲートウェイ横断の比較資料です。API形式とベースURL、認証方式、分割払いへの対応、Bitとウォレットへの対応、金額の単位、オーソリ/キャプチャ/リリースの呼び出し、取消し/返金/一部返金のマトリックス、照合に使う各ゲートウェイの取引照会方法、資金が移動したかどうかを判定するPelecardのステータスコードを掲載しています。意図的に手数料表は含めていません。ゲートウェイの評価や切り替えを検討する際に参照してください。

参考リンク

ソースURL確認する内容
Cardcom v11 API スキーマhttps://secure.cardcom.solutions/swagger/v11/swagger.json信頼できるフィールド一覧:CreditType の値、UrlToBit、および PartialSum と CancelOnly を含む RefundByTransactionId リクエスト
Tranzila ドキュメントhttps://docs.tranzila.com/4つのインターフェースのうちどれを使用しているか、公開されている cred_type の値、API V2 の4ヘッダー HMAC 認証
PayMehttps://payme.io/PayMe は、一般にアクセスできる開発者向けドキュメントの URL を公開していません(payme.io/developers はホームページに 301 リダイレクトし、docs.paymeservice.com は Cloudflare 1014 を返します)。API リファレンスを PayMe に直接請求し、最初の課金の前に、金額の単位と返金パラメーター名を確認してください
Meshulam(Grow)リファレンスhttps://developers.grow.business/reference/overview本番環境のベース URL は secure.meshulam.co.il、返金時は refundSum を使用すること、部分返金の可否を左右するエラーコード
Rivhit(iCredit)https://www.rivhit.co.il/iCredit は Rivhit の製品です。API は WCF .svc サービスで、返金インターフェースは公開されていません
Pelecard サービス一覧https://gateway21.pelecard.biz/servicesDeleteTran と GetTransDataBeforeBc を含む、稼働中のエンドポイント一覧。gateway20 と gateway21 は環境ではなく、世代を表します
イスラエル銀行:決済システム監督https://www.boi.org.il/en/economic-roles/supervision-and-regulation/payment-systems-oversight/どのシステムが「管理対象決済システム」に該当し、イスラエル銀行の監督範囲に含まれるかに加え、監督指令と決済システムへの接続要件を確認します。このページでは、銀行以外の決済サービスプロバイダーを誰が監督するのかは確定できない点に注意してください。ここから推測せず、規制当局に直接確認してください

落とし穴

  • これらのゲートウェイでは、HTTP 200 が決済成功を意味するとは限りません。 Tranzila はレスポンスコードの表の冒頭で明言しています。これらはアプリケーションエラーコードであり、レスポンスコードは成功(200)になります。Grow は status: "0" と err オブジェクトを含む 200 を返します。Pelecard の init は Error.ErrCode を返します。Tranzila の旧式 CGI は、JSON ではなく HTML のアラートページを返します。これらを正規化するのはオーケストレーターの役割であり、エージェントが作成したインテグレーションで、失敗した決済を支払い済みとして報告してしまう最もよくある原因です。ステータスではなく、本文を解析してください。
  • このスキルで扱うイスラエルの各決済ゲートウェイ(Cardcom、Tranzila、PayMe、Meshulam、iCredit、Pelecard)は、それぞれまったく異なる API 形式を使用しています。Cardcom は JSON、Tranzila は旧式のインターフェースではフォームエンコードされたキーと値のペア、API V2 では JSON、Meshulam は別個のページコードパラメーターを含む multipart/form-data、iCredit は WCF の .svc サービスを使用します。エージェントが別のゲートウェイの形式を流用することがあります。
  • ホスト名は環境の切り替えではありません。 Pelecard では、gateway20 と gateway21 はゲートウェイの世代を示すもので、バイト単位で同一のレスポンスを返します。呼び出しがテストか実際の課金かを決めるのは、端末番号と認証情報です。「サンドボックスホストに切り替え」たうえでテストデータを実行すると、実際に課金してしまいます。
  • 冪等性キーには、それに対応するベンダー側のフィールドが必要です。 各ゲートウェイには独自の重複検出機構と重複エラーコードがあります。オーケストレーターが生成したキーをゲートウェイ独自のフィールドに割り当てなければ、それは飾りにすぎません。ゲートウェイは同じ課金を問題なく二度受け付けます。Grow では重複検出フィールドは transactionUniqueIdentifier であり、同じ論理的な課金の再試行では値を維持する必要があります。Pelecard では、パススルーの ParamX は試行ごとの照合用であり、重複排除キーではありません。重複排除は、返されたトランザクション ID に基づいて行われます。この 2 つは相互に置き換えられません。ほかのゲートウェイについては、再試行の安全性を前提とする前に、各ゲートウェイのスキルでフィールドと重複コードを確認してください。
  • イスラエルで決済処理を行うには、イスラエルでの事業登録(osek murshe/patur)が必要です。エージェントは、事業が税務当局に適切に登録されているかを確認する前に、決済処理の設定を勧めることがあります。
  • Bit(イスラエルで主流のモバイル決済)の返金には、ほとんどのゲートウェイでクレジットカード返金とは異なる API エンドポイントを使用します。エージェントが Bit の取引にクレジットカードの返金エンドポイントを使用することがあります。
  • 保存済みカードのトークンは、ゲートウェイ間で移行できません。 Cardcom のトークン、Tranzila の TranzilaTK、PayMe の buyer_key は、それぞれ独自仕様で相互に互換性がなく、発行元のゲートウェイでのみ使用できます。そのため、このスキルでのフォールバック/フェイルオーバーパターンが適用されるのは、初回課金と一回限りの取引のみです。トークン化された課金や継続課金は、2 番目のゲートウェイにフェイルオーバーできません。継続課金は、開始時のゲートウェイに固定されます。保存済みカードで真のクロスゲートウェイ耐障害性を実現するには、ネットワークトークン化または複数のトークン保管庫を使う戦略が必要であり、このトークンフィールドでは実現できません。エージェントが、保存済みのトークンは優先順位リスト内のどのゲートウェイでも使えると誤って想定することがあります。
  • ゲートウェイのクライアント側での「成功」は偽装可能です。必ずサーバー側で再検証してください。 ブラウザーのリダイレクトやクライアントから送信されたステータスを、決済の証拠として信頼しないでください。注文を履行する前に、発行元のゲートウェイにサーバー間クエリを行い、すべての取引を確認してください(Meshulam/Grow の場合は getPaymentProcessInfo/承認、その他の場合はゲートウェイの取引照会、または Webhook 署名/通知の検証を使用します)。Webhook/IPN のペイロードは、各ゲートウェイ固有の方式で認証する必要があり、互いに置き換えることはできません。
  • 3DS2 は非同期のチャレンジフローであり、単一の呼び出しではありません。 カード非対面課金では、「フリクションレス」(インラインで承認)になる場合と、チャレンジが発生して顧客をカード発行会社にリダイレクトし、コールバック URL 経由で戻ってくる場合があります。オーケストレーターは取引を永続化し、コールバック時に処理を再開し、チャレンジからの復帰を開始時と同じゲートウェイで処理する必要があります(3DS セッションはゲートウェイ単位です)。エージェントが 3DS を同期的なブール値としてモデル化すると、チャレンジ中の取引が失われることがあります。

トラブルシューティング

エラー:「Installment type not supported」/Tranzila 017

原因:ほとんどの場合、ゲートウェイではなく、CreditType の値そのものに問題があります。どのベンダーでも公開しているのは 1、6、8 のみです。2、3、4、5、9 はサードパーティーライブラリで使われていますが、現在のベンダーのパラメーターテーブルには記載がなく、Tranzila はこれらに対して 017 Unauthorized credit type for this transaction を返します。 解決策:通常の分割払いには 8、発行会社負担のクレジットには 6 を送信します。加盟店がクラブまたはロイヤルティプログラムを本当に必要としている場合、それはフィールド値ではなく、端末とアクワイアラーの設定に関するものです。そのため、別の番号で再試行するのではなく、アクワイアラーに問い合わせてください。確認済みの否定事項:拒否された CreditType はゲートウェイより上流で拒否されるため、ゲートウェイを切り替えても解決しません。

エラー:「Gateway timeout on fallback」

原因:設定されているすべてのゲートウェイが劣化しているか、もっとよくあるケースとして、1 つのゲートウェイがタイムアウトし、オーケストレーターがそれを失敗とみなして次に進んでいます。 解決策:この 2 つを区別します。タイムアウトでは結果が不明なままなので、フェイルオーバーせず、照合のために保留する必要があります(Step 6)。次のゲートウェイに進むのが妥当なのは、接続失敗が明確に確認できた場合のみです。この違いを反映したうえで、ヘルスチェックを備えたサーキットブレーカーを追加し、劣化を検知したらアラートを出します。

エラー:「Duplicate transaction detected」

原因:通常はタイムアウトを失敗として扱った後、リトライロジックが同じ支払いを 2 回送信しています。 解決策:冪等性キーをゲートウェイ独自の重複検出フィールドに対応付け、タイムアウトは失敗ではなく結果不明として扱います(Step 6)。何かを再試行する前に、取引を照会してください。銀行による拒否は決して再試行しないでください。

エラー:返金呼び出しは成功を返すが、顧客が返金されていないと言っている

原因:最も可能性の高い原因ですが、すべてのゲートウェイで確認されているわけではありません。クレジットが完了せずキューに入っているか、すでに決済済みの取引に対する取消処理だった可能性があります。確認済みの否定事項:Pelecard では /PaymentGW 返金エンドポイント自体が存在しないため、これが返金エンドポイントの失敗であることはありません。 解決策:呼び出しを選ぶ前に、元の取引が決済の前か後かを確認します(Step 7)。取消呼び出しの応答ではなく、ゲートウェイ独自の取引照会結果と照合してください。

コメント