構築Tips

【Python】銀行振込の消込作業を自動化!fincodeのバーチャル口座API&Webhook実装ガイド

fincodeマーケティング担当です。 BtoB取引や高額商品の販売において、依然として根強い人気を誇る「銀行振込」。 しかし、Webサービスの運営担当者や経理担当者にとって、銀行振込は「悩みの種」でもあります。 「毎日、銀行の入出金明細を目視で確認するのが大変…」 「『スズキ』様から入金があったけど、どの鈴木さんの注文かわからない…」 そんな「アナログな消込作業」を一瞬で解決する技術が、fincodeの「銀行振込(バーチャル口座)」です。 今回は、Python(Flask)を使った銀行振込ページの実装から、 入金をリアルタイムに検知する「Webhook」の実装・テスト方法までを一挙にご紹介します。 バックエンドの実装コード(Python) フロントエンドの実装コード(HTML) Webhookによる入金検知と自動化ロジック ローカル環境での疎通テスト方法 まで一通りおさえていきます。 そもそも「バーチャル口座」で何が解決するのか? 技術的な実装に入る前に、銀行振込(バーチャル口座)の仕組みを簡単に解説します。 通常の銀行振込では、会社が持つ「1つの口座」に対して、複数顧客が振込を行います。 そのため、名前(振込依頼人名)だけで誰からの入金かを判断しなければならず、 同姓同名や会社名義での振込があるたびに確認作業が発生します。 対してfincodeの銀行振込(バーチャル口座)は、「注文ごとに専用の口座番号を発行」します。 Aさんの注文には「口座番号:1111111」を表示 Bさんの注文には「口座番号:2222222」を表示 これにより、システムは「1111111番に入金があった=Aさんの支払いが完了した」と、自動消込ができるようになります。 これをAPI経由で、しかも初期費用や月額固定費無料で導入できるのがfincodeの強みです。 今回作成するアプリの完成イメージ 今回は、Pythonの軽量Webフレームワークである「Flask」を使って、以下の機能を持つサンプルアプリを作成します。 口座発行(API):ユーザーが商品購入ボタンを押すと、画面遷移なしで即座に専用の「振込先口座情報」を発行・表示する。 入金検知(Webhook):ユーザーの支払いが完了すると、fincodeからシステムへリアルタイムに入金通知(Webhook)が届く。 デザイン:ブルーを基調としたUI。 完成すると、以下のような画面ができあがります。 バックエンド実装編:Pythonで口座発行&Webhook受信を実装する それでは、サーバーサイド(Python)のコードを見ていきましょう。 fincodeのAPIにおいて、バーチャル口座の決済フローは以下の3ステップで成り立ちます。 1.決済登録(POST):「これから銀行振込の決済を作りますよ」という枠を作成する。 2.決済実行(PUT):実際に固有の口座番号を発番させる。 3.Webhook受信(POST):後日、ユーザーが入金した通知をリアルタイムに受け取る。 以下が完成した app.py です。コピペしてそのまま使えます。 python import os from flask import Flask, jsonify, render_template, request, Response import requests app = Flask(__name__) API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") BASE_URL = "https://api.test.fincode.jp" HEADERS = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } SERVER_AMOUNT = 10000 @app.route("/") def index(): return render_template("index.html", amount=SERVER_AMOUNT) @app.route("/api/virtual_account/start", methods=["POST"]) def start_virtual_account(): amount = SERVER_AMOUNT # ----------------------------------------------------- # 1. 決済登録(POST /v1/payments) # ----------------------------------------------------- register_payload = { "pay_type": "Virtualaccount", "billing_amount": str(amount), } print(f"Registering payment... Payload: {register_payload}") register_res = requests.post( f"{BASE_URL}/v1/payments", headers=HEADERS, json=register_payload, timeout=10, ) if not register_res.ok: print(f"Register Error: {register_res.text}") return jsonify({"error": "register_failed", "detail": register_res.json()}), 502 register_json = register_res.json() payment_id = register_json.get("id") access_id = register_json.get("access_id") if not payment_id or not access_id: return jsonify({"error": "missing_id_or_access_id"}), 502 # ----------------------------------------------------- # 2. 決済実行(PUT /v1/payments/{id}) # ----------------------------------------------------- execute_payload = { "pay_type": "Virtualaccount", "access_id": access_id, } print(f"Executing payment... ID: {payment_id}, Payload: {execute_payload}") execute_res = requests.put( f"{BASE_URL}/v1/payments/{payment_id}", headers=HEADERS, json=execute_payload, timeout=10, ) if not execute_res.ok: print(f"Execute Error: {execute_res.text}") return jsonify({"error": "execute_failed", "detail": execute_res.json()}), 502 execute_json = execute_res.json() # ----------------------------------------------------- # 3. 必要な情報を抽出して返却 # ----------------------------------------------------- response_data = { "status": "success", "payment_id": payment_id, "access_id": access_id, "bank_info": { "branch_name": execute_json.get("va_branch_name"), # 支店名 "account_number": execute_json.get("va_account_number"), # 口座番号 "account_name": execute_json.get("va_account_name"), # 口座名義 }, "amount": execute_json.get("billing_total_amount"), # 合計金額 "payment_term": execute_json.get("payment_term"), # 支払期限日時 } return jsonify(response_data) @app.route("/success") def success(): return "銀行振込(バーチャル口座)の発行が完了しました。" # ===================================================== # Webhook 受信用エンドポイント # ===================================================== @app.route("/webhook", methods=["POST"]) def fincode_webhook(): payload = request.get_json() if not payload: return Response("0", status=200, mimetype="text/plain") event_type = payload.get("event") order_id = payload.get("order_id") status = payload.get("status") print("\n========================================") print("★ fincode Webhookを受信しました ★") print(f"イベント : {event_type}") print(f"注文ID : {order_id}") print(f"ステータス: {status}") print("========================================\n") # バーチャル口座の「入金完了」を検知した場合の処理 if event_type in ["payments.virtualaccount.complete", "payments.virtualaccount.complete.stub"]: if status == "CAPTURED": print(f"【入金確認】注文番号: {order_id} の入金を確認しました。") # ------------------------------------------------- # [ここに実行したい処理を書く] # 例1: データベースの注文ステータスを「支払い済み」に更新する # 例2: ユーザーに「入金を確認しました」と自動メールを送る # ------------------------------------------------- return Response("0", status=200, mimetype="text/plain") if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True) バックエンドの解説ポイント pay_type:"Virtualaccount" を指定しています。 billing_amount パラメータを使用しています。クレジットカード決済などでは amount ですが、バーチャル口座ではこちらを使います。 フロントエンド実装編 次に、ユーザーが触れる画面(HTML/CSS/JS)です。 以下のコードを templates/index.html として保存してください。 html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>お支払い | fincode Bank Transfer</title> <style> /* -------------------------------------------------- Variables & Reset -------------------------------------------------- */ :root { --primary-color: #0068B7; --primary-gradient-start: #0055D0; --primary-gradient-end: #00A1E9; --primary-hover: #005096; --bg-color: #f0f4f8; --card-bg: #ffffff; --text-main: #333333; --text-sub: #767676; --accent-color: #0068B7; --error-color: #e74c3c; --border-radius: 16px; --shadow: 0 10px 30px -5px rgba(0, 85, 208, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1); } * { box-sizing: border-box; } body { font-family: "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, -apple-system, BlinkMacSystemFont, sans-serif; background-color: var(--bg-color); color: var(--text-main); margin: 0; padding: 20px; display: flex; justify-content: center; align-items: center; min-height: 100vh; } /* -------------------------------------------------- Card Container -------------------------------------------------- */ .payment-card { background: var(--card-bg); width: 100%; max-width: 420px; border-radius: var(--border-radius); box-shadow: var(--shadow); overflow: hidden; animation: slideIn 0.5s ease-out; position: relative; } @keyframes slideIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .card-header { background: linear-gradient(135deg, var(--primary-gradient-start) 0%, var(--primary-gradient-end) 100%); padding: 35px 20px; text-align: center; color: white; position: relative; } .card-header::after { content: ''; position: absolute; bottom: -20px; left: 0; right: 0; height: 40px; background: #fff; border-radius: 50% 50% 0 0 / 100% 100% 0 0; transform: scaleX(1.5); } .header-title { margin: 0; font-size: 0.85rem; opacity: 0.9; letter-spacing: 0.1em; text-transform: uppercase; font-weight: bold; } .header-price { margin: 10px 0 5px; font-size: 2.5rem; font-weight: 700; text-shadow: 0 2px 4px rgba(0,0,0,0.1); } .header-price span { font-size: 1rem; font-weight: normal; margin-left: 4px; } .card-body { padding: 20px 30px 40px; position: relative; z-index: 1; } .product-info { text-align: center; margin-bottom: 30px; color: var(--text-sub); font-size: 0.9rem; font-weight: 500; } /* -------------------------------------------------- Button -------------------------------------------------- */ .btn-pay { width: 100%; padding: 18px; background-color: var(--primary-color); color: white; border: none; border-radius: 50px; font-size: 1rem; font-weight: bold; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 4px 15px rgba(0, 104, 183, 0.3); display: flex; justify-content: center; align-items: center; gap: 10px; } .btn-pay:hover { background-color: var(--primary-hover); transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0, 104, 183, 0.4); } .btn-pay:active { transform: translateY(0); } .btn-pay:disabled { background-color: #cbd5e1; cursor: not-allowed; box-shadow: none; transform: none; } /* -------------------------------------------------- Spinner -------------------------------------------------- */ .spinner { display: none; width: 20px; height: 20px; border: 3px solid rgba(255,255,255,0.3); border-radius: 50%; border-top-color: #fff; animation: spin 0.8s ease-in-out infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* -------------------------------------------------- Result Area -------------------------------------------------- */ .result-area { display: none; margin-top: 35px; animation: fadeIn 0.6s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .success-message { text-align: center; color: var(--primary-color); margin-bottom: 25px; } .success-icon { width: 60px; height: 60px; background-color: #e6f2ff; color: var(--primary-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 1.8rem; margin: 0 auto 15px; } .success-text { font-weight: bold; font-size: 1.1rem; color: var(--text-main); } .info-table { width: 100%; border-collapse: separate; border-spacing: 0 10px; } .info-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; font-size: 0.95rem; padding-bottom: 12px; border-bottom: 1px dashed #e1e4e8; } .info-row:last-child { border-bottom: none; } .info-label { color: var(--text-sub); font-size: 0.9rem; } .info-value { font-weight: 600; color: var(--text-main); text-align: right; } .highlight { color: var(--primary-color); font-size: 1.2rem; letter-spacing: 1px; } .note { margin-top: 25px; padding: 15px; background-color: #f8fafc; border-radius: 12px; color: #64748b; font-size: 0.8rem; line-height: 1.6; text-align: left; } /* -------------------------------------------------- Error -------------------------------------------------- */ .error-message { display: none; margin-top: 20px; padding: 15px; background-color: #fef2f2; color: var(--error-color); border-radius: 12px; font-size: 0.9rem; text-align: center; border: 1px solid #fecaca; } </style> </head> <body> <div class="payment-card"> <div class="card-header"> <p class="header-title">TOTAL AMOUNT</p> <h1 class="header-price">{{ amount }}<span>円</span></h1> </div> <div class="card-body"> <p class="product-info">商品A</p> <button id="btn-pay-virtual" class="btn-pay"> <span id="spinner" class="spinner"></span> <span id="btn-text">銀行振込で支払う</span> </button> <div id="error-area" class="error-message"></div> <div id="result-area" class="result-area"> <div class="success-message"> <div class="success-icon">✓</div> <div class="success-text">ご購入ありがとうございます。</div> </div> <p style="text-align: center; font-size: 0.9rem; margin-bottom: 25px; color: var(--text-sub);"> 以下の口座へお振込みをお願いします。 </p> <div class="info-group"> <div class="info-row"> <span class="info-label">銀行名</span> <span class="info-value">GMOあおぞらネット銀行</span> </div> <div class="info-row"> <span class="info-label">支店名</span> <span class="info-value" id="res-branch-name">--</span> </div> <div class="info-row"> <span class="info-label">口座種別</span> <span class="info-value">普通</span> </div> <div class="info-row"> <span class="info-label">口座番号</span> <span class="info-value highlight" id="res-account-number">--</span> </div> <div class="info-row"> <span class="info-label">口座名義</span> <span class="info-value" id="res-account-name">--</span> </div> <div class="info-row" style="border-top: 2px solid #f1f5f9; padding-top: 15px; margin-top: 5px;"> <span class="info-label">お支払金額</span> <span class="info-value highlight" id="res-amount">--</span> </div> <div class="info-row" style="border-bottom: none;"> <span class="info-label">支払期限</span> <span class="info-value" id="res-payment-term" style="color: #e74c3c;">--</span> </div> </div> <div class="note"> <strong>ご注意</strong><br> ※お振込手数料はお客様負担となります。<br> ※期限を過ぎると口座は無効になります。 </div> </div> </div> </div> <script> document.getElementById('btn-pay-virtual').addEventListener('click', async function() { const button = this; const spinner = document.getElementById('spinner'); const btnText = document.getElementById('btn-text'); const resultArea = document.getElementById('result-area'); const errorArea = document.getElementById('error-area'); // UIリセット errorArea.style.display = 'none'; resultArea.style.display = 'none'; // ローディング開始 button.disabled = true; spinner.style.display = 'block'; btnText.textContent = '処理中...'; try { // サーバーサイド(app.py)のAPIを呼び出す const response = await fetch('/api/virtual_account/start', { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (!response.ok) { let errorMsg = '決済処理に失敗しました'; if(data.error) errorMsg += ` (${data.error})`; throw new Error(errorMsg); } // 成功時:取得した口座情報を画面にセット document.getElementById('res-branch-name').textContent = data.bank_info.branch_name; document.getElementById('res-account-number').textContent = data.bank_info.account_number; document.getElementById('res-account-name').textContent = data.bank_info.account_name; const formattedAmount = new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(data.amount); document.getElementById('res-amount').textContent = formattedAmount; document.getElementById('res-payment-term').textContent = data.payment_term; // 結果エリアを表示 resultArea.style.display = 'block'; // ボタンを完了状態にする btnText.textContent = '発行完了'; // button.disabled = true; // スクロール resultArea.scrollIntoView({ behavior: 'smooth', block: 'start' }); } catch (error) { console.error('Error:', error); errorArea.textContent = 'エラー: ' + error.message; errorArea.style.display = 'block'; // ボタンを元に戻す button.disabled = false; btnText.textContent = '銀行振込で支払う'; } finally { if (btnText.textContent !== '発行完了') { spinner.style.display = 'none'; } else { spinner.style.display = 'none'; } } }); </script> </body> </html> フロントエンドの解説ポイント 非同期通信:ページ全体をリロードすることなく、ボタンを押した瞬間にバックエンドと通信を行います。 動的なDOM操作:APIから返ってきた「支店名」や「口座番号」を、JavaScriptでHTML内のプレースホルダー(--の部分)に埋め込みます。 UXへの配慮:処理中は「スピナー(くるくる)」を表示し、完了後は自動的に結果エリアまでスクロールするアニメーションを入れています。 Webhookをローカル環境でテストする3つのステップ プログラム内に /webhook を用意しましたが、開発中の自分のパソコン(localhost)はインターネット上に公開されていないため、fincodeから直接通知を受け取ることができません。 そこで今回は、「一度インターネット上のテスト用URLで本物のデータを受け取り、それをローカルに保存して手動でリクエストを実行する」というテスト手法を解説します。 ステップ1:Webhook.siteで生のデータをキャッチする まずは、fincodeから実際に送られてくるデータの構造を確認しましょう。 1.ブラウザで Webhook.site にアクセスします。 2.画面に表示される 「Your unique URL」(https://webhook.site/...)をコピーします。 3.fincodeテスト環境の管理画面にログインし、「API・Webhook」タブ を開きます。 「Webhookの追加」ボタンを押し、エンドポイントURLには先ほどコピーしたURLをペースト、 トリガーイベントは「銀行振込(バーチャル口座)支払通知(シミュレート)」を選択し、「追加」ボタンを押下。 4.ターミナルで python app.py を実行しhttp://localhost:5000 にアクセス。 「銀行振込で支払う」ボタンを押下し、管理画面から「銀行振込支払実行」を行うと、Webhook.siteにリアルタイムでデータ(JSON)が届きます。 「Raw Content」 に表示されているJSONデータを丸ごとコピーします。 ステップ2:データをローカル(data.json)に保存する 1.プロジェクトのフォルダ(app.py と同じ場所)に、data.json という名前のファイルを新規作成します。 2.先ほどWebhook.siteからコピーしたデータをそのまま貼り付けて保存します。 ステップ3:PowerShellからローカル環境へリクエストを送信する 1.エクスプローラーで data.json があるフォルダを開き、アドレスバーに powershell と入力してEnterキーを押します。 そのフォルダを基準としたPowerShell画面が立ち上がります。 2.起動したPowerShellに、以下のcurlコマンドを貼り付けてEnterを押します。 PowerShell curl.exe --noproxy localhost -X POST http://localhost:5000/webhook -H "Content-Type: application/json" -d "@data.json" コマンドのポイント --noproxy localhost:開発環境が社内ネットワーク等にある場合、プロキシサーバーがlocalhostへの通信を横取りしてアクセス拒否(Access Denied)を起こすのを防ぎます。 "@data.json":PowerShellにおいて @ 記号は特殊な命令として誤認されエラーの原因になるため、全体をダブルクォーテーションで囲んでファイルを正常に読み込ませています。 実行結果の確認 コマンドを実行して、それぞれの画面に以下の反応があればテスト成功です。 ▼ PowerShell(送信側)の表示 Plaintext 0 ▼ Python(Flask実行側)のログ出力 Plaintext ======================================== ★ fincode Webhookを受信しました ★ イベント : payments.virtualaccount.complete.stub 注文ID : o_********************** ステータス: CAPTURED ======================================== 【入金確認】注文番号: o_********************** の入金が完了しました。 127.0.0.1 - - [26/Jun/2026 17:09:52] "POST /webhook HTTP/1.1" 200 - 導入ビフォーアフター 導入前(通常振込) fincodeバーチャル口座導入後 入金先口座  会社共通の1つの口座 注文ごとに異なる口座番号 特定方法 依頼人名(カタカナ)を目視確認 口座番号でシステムが自動特定 消込作業 手動で管理 全自動 誤入金 金額間違いの連絡が必要 金額完全一致のみ受け付け可能 このシステムを導入することで、経理担当者は「入金確認作業」から解放され、より生産的な業務に時間を使えるようになります。 まとめ:fincodeなら「銀行振込」もモダンに実装できる 今回は、Python(Flask)を使った銀行振込ページの実装から、 入金をリアルタイムに検知する「Webhook」の実装・テスト方法までを一挙にご紹介しました。 fincodeは初期費用・月額費用が無料で、アカウント作成後すぐにテスト環境のAPIキーが発行されます。 「まずは手元で動かしてみたい」というエンジニアの方は、ぜひ今回のコードをコピペして試してみてください。   ■ この記事の作成者 fincode マーケティング担当 非エンジニアのバックグラウンドを持ちながら、基本情報技術者試験に合格。 現在はデータ分析にPythonを活用し、プロダクトへの理解を深めるためGo言語の習得にも挑戦中。 読者に近い視点から、複雑な決済技術を噛み砕いてお伝えします。 ■ この記事の監修者 fincode プロダクトマネージャー オンライン決済インフラ『fincode byGMO』の新機能企画・製品ディレクション等を統括。 プロダクトマネジメントの傍ら、個人開発者として自らコードを書く時間も大切にしている。 現場のエンジニアが直面する課題に寄り添い、情報の正確性と実用性を徹底して監修。   fincodeとは fincodeとは、GMOイプシロン株式会社が提供する、スピーディに導入できるオンライン決済サービスです。 シンプルで統一性のあるAPIと充実の開発支援コンテンツを提供し、エンジニアファーストな設計を追求しています。 fincodeが提供する決済画面のUIコンポーネント(JavaScript)をそのまま利用することで開発工数を削減し、簡単に決済を実装できます。 決済を通じてEC/SaaS/プラットフォーム、スタートアップからエンタープライズまで様々なビジネスの成長を支えます。 +FinTechによる新たな収益モデルの構築 fincodeのプラットフォーム機能を実装することで、決済金額に対する利用料が得られる新たな収益モデルの構築が可能です。 貴社のお客様(=テナント)へ提示する決済手数料に、「プラットフォーム利用料」を設定することで、差額が貴社の収益となります。 「貴社プロダクト + FinTech~新たな収益モデル構築のご提案~」資料ダウンロード > fincodeが選ばれる理由 エンジニアファーストの設計/洗練されたUX オープンでアクセスしやすいWEBドキュメント、REST APIと複数開発言語に対応したAPIリファレンス。 決済画面のUIも、Android/iOS対応のモバイルSDKにより、少ない開発工数で柔軟にカスタマイズ可能です。 見えない手数料、ゼロへ 初期費用・月額費用0円。 さらに、義務化されたEMV 3-Dセキュア認証についても追加費用0円で導入できます。 料金表に書かれていない見えない手数料はゼロ。カード決済は決済手数料のみでご利用いただけます。 国際標準を日本品質で fincodeは日本国内で生まれ、日本のビジネス環境に合わせて設計された決済サービスです。 海外発サービスでは難しい、日本ならではの細かな商習慣や感性まで理解して、日本の企業と共に成長していきます。 運営会社 会社名 GMOイプシロン株式会社(英文表記:GMO Epsilon, Inc.) 設立年月日 2002年9月26日 所在地 〒150-0043 東京都渋谷区道玄坂1丁目14番6号 ヒューマックス渋谷ビル7F 資本金 1億5百万円 事業内容 オンライン販売の決済代行、代金回収代行及びそれらに付帯する業務 主要株主 GMOペイメントゲートウェイ株式会社 (東証プライム上場:3769) グループ会社 GMOインターネットグループ 東証プライム上場企業のGMOペイメントゲートウェイの連結会社として、プライバシーマーク認証やPCI DSS、ISMS準拠のセキュリティ基準で安心してご利用いただける環境を提供しています。   事業規模によって決済手数料のご提案が可能です。 見積依頼 > fincodeサービス概要の資料ダウンロードはこちらから 資料請求 >   あわせて読みたいおすすめの記事 【初心者向け】fincodeで請求業務DX|Pythonで”決済機能付き請求書”をAPI発行する方法(インボイス機能) 【初心者向け】Pythonでfincodeの決済APIを実行する実装例(決済URL作成編) 【Python】クレジットカード決済の実装方法(決済登録API+決済実行JS編) Python(Flask)でPayPay決済APIを実装する方法(決済登録API+決済実行API)

マーケティングチーム

【初心者向け】Pythonでサブスク決済APIを実装する方法|fincodeで自動課金システムを構築

fincodeマーケティング担当です。 SaaSや定期購入サービスなどを開発する際、避けて通れないのが「サブスクリプション(継続課金)」の実装です。 「初回の決済はいつ走る?」「次回課金日はいつにする?」など、考慮すべき仕様が多く、サブスク実装は複雑になりがちです。 しかし、開発のしやすさに特化した決済サービス「fincode」を使えば、驚くほど少ないコード量でサブスクリプション機能を実装できます。 本記事では、Python(Flask)を使って、購入者がボタンを押した瞬間に「サブスクリプション契約を開始し、初回の決済を即座に完了させる」ための最小実装をご紹介します。 エンジニアの方はもちろん、サービスの仕様を検討しているビジネスサイドの方にも「fincodeならここまでシンプルに実現できる」ということを知っていただければ幸いです。 サブスクリプション決済の全体フロー fincodeでサブスクリプション決済を実装する際の全体フローは以下の通りです。 1.プラン作成:月額料金や課金間隔などを定義したプランを作成 2.顧客登録:fincode上に顧客情報を登録 3.カード登録:顧客の決済に使用するクレジットカード情報を登録 4.サブスクリプション登録:顧客とプランを紐づけて継続課金を開始 特に今回は、「課金開始日を当日に設定する」点がポイントです。 これにより、ユーザーが登録した瞬間にサービス利用を開始(および課金)する、サブスクリプションの流れを実現します。 一度設定してしまえば、あとはfincodeが自動的に毎月の決済処理を行います。システム側で毎月プログラムを動かす必要はありません。 これらの処理は、fincodeの「サブスクリプション機能」で実現しています。 fincodeの「サブスクリプション機能」とは 定期的に顧客に対し定額の請求を行う機能であり、APIや管理画面から指定した金額・支払間隔で顧客に対してサブスクリプション課金をすることが可能です。 fincodeのサブスクリプション機能は、単なる継続課金だけでなく、以下のような柔軟な設定が可能です。 課金間隔の自由な設定:毎月、2ヶ月ごと、毎年など、ビジネスに合わせた課金サイクルを選択可能 初回課金金額の設定:初月無料キャンペーンなど、初回のみ異なる金額を設定できる 課金開始日の指定:課金開始日を指定可能。指定した日付に毎回のサブスクリプションによる請求を実行 プランの柔軟な管理:プラン内容の変更、一時停止、解約などを制御可能 これらの機能により、さまざまなサブスクリプションビジネスモデルに対応できます。 事前準備(初心者向けガイド) ここからは実際に手を動かしていきましょう。まずはPythonでAPIを叩くための準備を行います。 fincodeのAPIキーの取得方法 まだアカウントをお持ちでない方は、fincodeサービスサイトから「アカウント登録」を行ってください。 登録後、管理画面にログインすると「テスト環境」が利用可能な状態になっています。 1. fincodeテスト環境の管理画面にログイン テスト環境のアカウントを作成する > テスト環境管理画面にログインする > 2. 「API・Webhook」タブから シークレットキー をコピー fincodeのテスト用シークレットキーは「m_test_**********************」という形式です。 3. 環境変数に設定する シークレットキーは、セキュリティの観点からコードに直書きせず、環境変数から読み込むことを推奨します。 本記事の実装例では、シークレットキーは環境変数(※1)から読み込みます。 (※1)プログラムが動く環境(パソコンやサーバー)にあらかじめ登録しておく設定情報のことです。APIキーなどの秘密情報をコードに書かず、安全に管理するために使われます。 Pythonライブラリのインストール 本記事では、PythonでHTTPリクエストを送るためのライブラリである requests を使用します。 コマンドプロンプト(またはターミナル)で以下のコマンドを実行してインストールしてください。 bash pip install requests コード全文:サブスクリプション決済の実装 ここからは、Pythonで実装する各ステップのサンプルコードを紹介します。 スクリプト①:プラン(料金体系)の作成 サブスクリプションには「月額いくらなのか」という定義(プラン)が必要です。 プランはユーザーごとに作るものではなく、サービスとして1つ(またはグレードごとに数個)あれば良いものです。 まずは、Pythonスクリプトを使って、fincode上にプランを1つ登録しましょう。 create_plan.py Python import os import requests api_key = os.getenv("FINCODE_TEST_SECRET_KEY") # 例: m_test_**************** base_url = "https://api.test.fincode.jp" # ====== 入力(必要に応じて変更) ====== # id を指定すると「自分で決めた plan_id」になります(重複するとエラー) id = "PLAN001" plan_name = "Gold Plan" amount = "1000" # string interval_pattern = "month" # "month" or "year" interval_count = "1" # "1","2","3","6" # =================================== url = f"{base_url}/v1/plans" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } data = { "id": id, "plan_name": plan_name, "amount": amount, "interval_pattern": interval_pattern, "interval_count": interval_count, } try: r = requests.post(url, headers=headers, json=data) print(r.status_code, r.json()) if r.status_code == 200: print("PLAN_ID =", r.json().get("id")) except requests.RequestException as e: print(f"Request error: {e}") 実行に成功すると、レスポンスが表示されます。 その中にある "id": "pl_**********************" という文字列がプランIDです。 このIDは、後ほどサーバー側のプログラムで使用しますので、メモ帳などに控えておいてください。 スクリプト②:購入者画面の実装(フロントエンド) 次に、ユーザーがカード情報を入力するWeb画面(HTML)を作成します。 ここでのポイントは、fincode.jsの利用です。 ユーザーが入力したカード番号は、JavaScriptによってfincodeのサーバーへ直接送信され、代わりに「トークン」が返却されます。自社のWebサーバーには、このトークンだけを送信します。 ファイル構成は以下の通りです。 templates フォルダを作成し、その中に index.html を保存してください。 プロジェクトフォルダ/ ├─ app.py └─ templates/    └─ index.html templates/index.html html <!doctype html> <html lang="ja"> <head>  <meta charset="utf-8" />  <title>サブスク開始デモ(月末課金)</title>  <!-- テスト環境用 fincode JS -->  <script src="https://js.test.fincode.jp/v1/fincode.js"></script>  <style>   body { font-family: sans-serif; max-width: 720px; margin: 24px auto; padding: 0 12px; }   input { width: 100%; padding: 10px; margin: 6px 0; box-sizing: border-box; }   .row { display: flex; gap: 8px; }   .row input { flex: 1; }   button { padding: 10px 14px; cursor: pointer; }   pre { background: #f6f6f6; padding: 12px; overflow: auto; }   .note { color: #666; font-size: 13px; }  </style> </head> <body>  <h1>サブスク開始</h1>  <p class="note">   カード番号はブラウザでtoken化し、サーバへ送るのはtokenのみ(カード番号は送信しません)  </p>  <h3>購入者情報</h3>  <input id="name" placeholder="お名前" value="" />  <input id="email" placeholder="メール" value="" />  <h3>カード情報</h3>  <input id="card_no" placeholder="カード番号" />  <div class="row">   <input id="expire_yy" placeholder="有効期限YY(例:26)" />   <input id="expire_mm" placeholder="有効期限MM(例:12)" />  </div>  <input id="holder_name" placeholder="名義(例:TARO YAMADA)" />  <input id="security_code" placeholder="CVC" />  <button id="btn">サブスクを開始する</button>  <h3>結果</h3>  <pre id="out">まだ実行していません</pre>  <script>   const PUBLIC_KEY = "p_test_****************"; // ← パブリックキーを入力   const out = document.getElementById("out");   const $ = (id) => document.getElementById(id);   const fincode = Fincode(PUBLIC_KEY);   $("btn").addEventListener("click", () => {    out.textContent = "token発行中...";    const card = {     card_no: $("card_no").value.trim(),     expire: $("expire_yy").value.trim() + $("expire_mm").value.trim(), // YYMM     holder_name: $("holder_name").value.trim(),     security_code: $("security_code").value.trim(),    };    fincode.tokens(card, async (status, response) => {     if (status !== 200) {      out.textContent = "token発行エラー:\n" + JSON.stringify(response, null, 2);      return;     }     const token = response.list[0].token;     out.textContent = "token発行OK。サーバへ送信中...";     const r = await fetch("/api/subscribe", {      method: "POST",      headers: {"Content-Type": "application/json"},      body: JSON.stringify({       token,       name: $("name").value.trim(),       email: $("email").value.trim(),      })     });     const data = await r.json();     out.textContent = JSON.stringify(data, null, 2);    }, () => {     out.textContent = "通信エラー(token発行)";    });   });  </script> </body> </html> ステップ3:サーバーサイドの実装(Python / Flask) ここが本記事のハイライトです。 サーバー側では、フロントエンドから受け取った「トークン」を使って、以下の3つの処理を一連の流れとして実行します。 顧客登録: 決済を行うユーザーを作成します。 カード登録: 作成した顧客に、カード情報を紐づけます。 サブスクリプション登録: 顧客、カード、プランを指定してサブスクリプション情報を作成します。ここで「開始日=今日」とすることで、即時決済を実行させます。 app.py Python import os import uuid import datetime as dt import requests from flask import Flask, request, jsonify, render_template app = Flask(__name__) API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") # m_test_**************** BASE_URL = "https://api.test.fincode.jp" PLAN_ID = "PLAN001" # 事前に作成したプランID def post(path, payload): r = requests.post( f"{BASE_URL}{path}", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=payload, ) return r.status_code, r.json() @app.route("/") def index(): return render_template("index.html") @app.route("/api/subscribe", methods=["POST"]) def subscribe(): token = (request.json.get("token") or "").strip() if not token: return jsonify({"ok": False, "message": "token is required"}), 400 # 1) customer customer_id = f"CUST_{uuid.uuid4().hex[:12]}" st, customer = post("/v1/customers", {"id": customer_id}) if st != 200: return jsonify({"ok": False, "step": "customer", "error": customer}), 400 # 2) card (token) st, card = post(f"/v1/customers/{customer_id}/cards", { "token": token, "default_flag": "1", }) if st != 200: return jsonify({"ok": False, "step": "card", "error": card}), 400 card_id = card.get("id") # 3) subscription (start today) start_date = dt.date.today().strftime("%Y/%m/%d") st, sub = post("/v1/subscriptions", { "pay_type": "Card", "plan_id": PLAN_ID, "customer_id": customer_id, "card_id": card_id, "start_date": start_date, # 当日開始(初回課金が即時試行される) }) if st != 200: return jsonify({"ok": False, "step": "subscription", "error": sub}), 400 return jsonify({ "ok": True, "customer_id": customer_id, "card_id": card_id, "subscription_id": sub.get("id"), "status": sub.get("status"), "start_date": start_date, "next_charge_date": sub.get("next_charge_date"), "error_code": sub.get("error_code"), }) if __name__ == "__main__": app.run("127.0.0.1", 5000, debug=True) 動作確認:実際に動かしてみよう すべてのコードの準備ができたら、実際に動かしてみましょう。 python app.py を実行してサーバーを起動します。 ブラウザで http://127.0.0.1:5000/ にアクセスします。 テスト用のクレジットカード番号を入力します。 fincodeのテスト環境用カード番号は ドキュメントのテスト用リソース を参照してください。 例: 4111111111111111 (VISAテストカード) 「サブスクを開始する」ボタンをクリックします。 成功した場合の確認ポイント 画面の「処理結果」欄にJSONが表示され、status: "ACTIVE" となっていれば成功です。 また、next_charge_date を見てみてください。 今日が2月6日であれば、start_date は 2026/02/06 となり、next_charge_date は翌月の 2026/03/06 となっているはずです。 これが確認できれば、**「登録即時決済」かつ「翌月同日に自動継続」**というサブスクリプションの基本的な挙動が正しく実装されています。 おわりに 今回は、Python (Flask) と fincode を組み合わせて、サブスクリプション決済を最短で実装する方法をご紹介しました。 fincodeのテスト環境は、アカウント登録のみですぐに試すことができます。。 「とりあえず決済機能を動かしてみたい」というエンジニアの方は、ぜひ以下のリンクからアカウント登録をしてみてください。 テスト環境のアカウントを作成する >   ■ この記事の作成者 fincode マーケティング担当 非エンジニアのバックグラウンドを持ちながら、基本情報技術者試験に合格。 現在はデータ分析にPythonを活用し、プロダクトへの理解を深めるためGo言語の習得にも挑戦中。 読者に近い視点から、複雑な決済技術を噛み砕いてお伝えします。 ■ この記事の監修者 fincode プロダクトマネージャー オンライン決済インフラ『fincode byGMO』の新機能企画・製品ディレクション等を統括。 プロダクトマネジメントの傍ら、個人開発者として自らコードを書く時間も大切にしている。 現場のエンジニアが直面する課題に寄り添い、情報の正確性と実用性を徹底して監修。   fincodeとは fincodeとは、GMOイプシロン株式会社が提供する、スピーディに導入できるオンライン決済サービスです。 シンプルで統一性のあるAPIと充実の開発支援コンテンツを提供し、エンジニアファーストな設計を追求しています。 fincodeが提供する決済画面のUIコンポーネント(JavaScript)をそのまま利用することで開発工数を削減し、簡単に決済を実装できます。 決済を通じてEC/SaaS/プラットフォーム、スタートアップからエンタープライズまで様々なビジネスの成長を支えます。 +FinTechによる新たな収益モデルの構築 fincodeのプラットフォーム機能を実装することで、決済金額に対する利用料が得られる新たな収益モデルの構築が可能です。 貴社のお客様(=テナント)へ提示する決済手数料に、「プラットフォーム利用料」を設定することで、差額が貴社の収益となります。 「貴社プロダクト + FinTech~新たな収益モデル構築のご提案~」資料ダウンロード > fincodeが選ばれる理由 エンジニアファーストの設計/洗練されたUX オープンでアクセスしやすいWEBドキュメント、REST APIと複数開発言語に対応したAPIリファレンス。 決済画面のUIも、Android/iOS対応のモバイルSDKにより、少ない開発工数で柔軟にカスタマイズ可能です。 見えない手数料、ゼロへ 初期費用・月額費用0円。 さらに、義務化されたEMV 3-Dセキュア認証についても追加費用0円で導入できます。 料金表に書かれていない見えない手数料はゼロ。カード決済は決済手数料のみでご利用いただけます。 国際標準を日本品質で fincodeは日本国内で生まれ、日本のビジネス環境に合わせて設計された決済サービスです。 海外発サービスでは難しい、日本ならではの細かな商習慣や感性まで理解して、日本の企業と共に成長していきます。 運営会社 会社名 GMOイプシロン株式会社(英文表記:GMO Epsilon, Inc.) 設立年月日 2002年9月26日 所在地 〒150-0043 東京都渋谷区道玄坂1丁目14番6号 ヒューマックス渋谷ビル7F 資本金 1億5百万円 事業内容 オンライン販売の決済代行、代金回収代行及びそれらに付帯する業務 主要株主 GMOペイメントゲートウェイ株式会社 (東証プライム上場:3769) グループ会社 GMOインターネットグループ 東証プライム上場企業のGMOペイメントゲートウェイの連結会社として、プライバシーマーク認証やPCI DSS、ISMS準拠のセキュリティ基準で安心してご利用いただける環境を提供しています。   事業規模によって決済手数料のご提案が可能です。 見積依頼 > fincodeサービス概要の資料ダウンロードはこちらから 資料請求 >   あわせて読みたいおすすめの記事 【初心者向け】fincodeで請求業務DX|Pythonで”決済機能付き請求書”をAPI発行する方法(インボイス機能) 【初心者向け】Pythonでfincodeの決済APIを実行する実装例(決済URL作成編) 【Python】クレジットカード決済の実装方法(決済登録API+決済実行JS編) Python(Flask)でPayPay決済APIを実装する方法(決済登録API+決済実行API)

マーケティングチーム

【初心者向け】fincodeで請求業務DX|Pythonで”決済機能付き請求書”をAPI発行する方法(インボイス機能)

fincodeマーケティング担当です。 「毎月の請求書発行業務を自動化したい」 「Webサービスから直接顧客に請求書を送りたい」 「請求書を送るだけでなく、そのまますぐにクレジットカード等で支払ってもらいたい」 BtoB、BtoCを問わず、ビジネスにおいて「請求・決済」は避けて通れない業務です。 しかし、請求書を作成し、PDF化してメールで送り、入金を確認して消込作業を行う…といったアナログなフローに疲弊している方も多いのではないでしょうか。 もし、これらが簡単なプログラムコードで完結するとしたらどうでしょう? この記事では、オンライン決済サービス「fincode byGMO」が提供する「インボイス機能」を活用し、Pythonを使って”決済機能付き請求書”をAPI経由で発行する方法を徹底解説します。 fincodeは、エンジニアファーストな設計が特徴です。 今回は、プログラミング初心者の方や、ビジネスサイドの方でも概要を理解できるよう詳しく説明していきます。 本実装例で実現できること:請求業務のDX 本記事で紹介するサンプルコードを実装すると、以下のフローを自動化できます。 顧客登録APIで、fincode上に顧客IDを登録 インボイス作成APIで、顧客情報や取引内容等のインボイス情報を登録し、インボイスIDを生成 インボイス発行APIで、生成したインボイスIDに対して、決済機能付き請求書のURL(Invoice URL)を発行 発行されたURLをブラウザで開くだけで、顧客はクレジットカードや銀行振込(バーチャル口座)で即座に支払い可能 fincodeの「インボイス機能」とは 「インボイス機能」とは、単に請求書のPDFを作るだけの機能ではありません。 「請求」と「決済」をシームレスに統合した機能です。 通常、請求書を受け取った顧客は、銀行振込の手続きをする必要があります。 しかし、fincodeのインボイス機能では、発行されるURL自体が「請求書 兼 決済フォーム」になっています。 顧客はそのページで請求内容を確認し、そのままクレジットカード番号を入力して決済を完了できます。 運営側にとっても、「誰から入金があったか」が自動的にシステム上で紐づく(消込が不要になる)ため、経理業務の負担が劇的に軽減されます。 fincodeでは、これらの機能を管理画面から手動で行うことも、APIを使ってプログラムから自動で行うことも可能です。 インボイス機能 サービスページ fincodeが選ばれる理由 決済APIを提供するサービスは世の中に数多く存在しますが、その中でもfincodeは「エンジニアにとっての開発しやすさ」を追求しています。 ① シンプルで直感的なREST API fincodeのAPIは、RESTの原則に基づいて設計されたシンプルで統一性のあるAPIです。 エンジニアにとっては理解がしやすく、直感的に開発を進めることができます。 ② 登録後即座に使えるテスト環境 Webサイトからアカウントを作成するだけで、テスト環境のAPIキーが発行され、開発をスタートできます。 ③ わかりやすいドキュメントと日本語サポート fincodeはGMOグループが運営する国産サービスであり、日本語のドキュメントが充実していることはもちろん、日本のビジネスフローに最適化されています。 事前準備(初心者向けガイド) ここからは実際に手を動かしていきましょう。まずはPythonでAPIを叩くための準備を行います。 fincodeのAPIキーの取得方法 まだアカウントをお持ちでない方は、fincodeサービスサイトから「アカウント登録」を行ってください。 登録後、管理画面にログインすると「テスト環境」が利用可能な状態になっています。 1. fincodeテスト環境の管理画面にログイン テスト環境のアカウントを作成する > テスト環境管理画面にログインする > 2. 「API・Webhook」タブから シークレットキー をコピー fincodeのテスト用シークレットキーは「m_test_**********************」という形式です。 3. 環境変数に設定する シークレットキーは、セキュリティの観点からコードに直書きせず、環境変数から読み込むことを推奨します。 本記事の実装例では、シークレットキーは環境変数(※1)から読み込みます。 (※1)プログラムが動く環境(パソコンやサーバー)にあらかじめ登録しておく設定情報のことです。APIキーなどの秘密情報をコードに書かず、安全に管理するために使われます。 Pythonライブラリのインストール 本記事では、PythonでHTTPリクエストを送るためのライブラリである requests を使用します。 コマンドプロンプト(またはターミナル)で以下のコマンドを実行してインストールしてください。 bash pip install requests コード全文:最小構成で動くPythonサンプル ここからは、Pythonだけで完結する最小構成のサンプルコードを紹介します。 スクリプト①:顧客IDを1件登録する スクリプト②:インボイスを作成 → 発行する の2ファイル構成です。 スクリプト①:顧客IDを登録する(/v1/customers) 請求書を発行するためには、「誰に送るか」という顧客情報が必要です。 まずは最小構成の顧客IDと名前だけで、CUST001 という顧客IDを1件登録します。 Python import os import requests API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") # 例: m_test_**************** BASE_URL = "https://api.test.fincode.jp" HEADERS = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } url = f"{BASE_URL}/v1/customers" data = { "id": "CUST001", "name": "aaa" } # HTTP POSTリクエストの送信 try: response = requests.post(url, headers=HEADERS, json=data) # レスポンスの処理 if response.status_code == 200: # 成功した場合の処理 print(f"Success: {response.json()}") else: # エラーの処理 print(f"Error: {response.json()}") except requests.RequestException as e: # 通信エラーの処理 print(f"Request error: {e}") コードのポイント解説 APIのエンドポイント: /v1/customers に対して POST リクエストを送ることで新規登録が行われます。 スクリプト②:インボイスを作成→発行する(/v1/invoices) 顧客登録ができたら、次はいよいよ「インボイス(請求データ)」の作成です。ここが本記事のメインパートです。 インボイス作成では、請求先の住所、明細(商品ごとの金額)、支払期日、利用可能な決済手段などを細かく指定できます。 「インボイス作成」と「インボイス発行」を1本のスクリプトで実行します。 Python import os import requests API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") # 例: m_test_**************** BASE_URL = "https://api.test.fincode.jp" HEADERS = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } def create_invoice(customer_id: str): """インボイス作成""" url = f"{BASE_URL}/v1/invoices" data = { "customer_id": customer_id, "customer_honorific": "様", "customer_overwrite": { "name": "株式会社テスト", "email": "customer@example.com", "addr_state": "13", "addr_city": "新宿区", "addr_line_1": "1-1-1", "addr_line_2": "テストビル", "addr_line_3": "", "addr_post_code": "1600022", }, "issuer_overwrite": { "addr_state": "13", "addr_city": "新宿区", "addr_line_1": "1-1-1", "addr_line_2": "テストビル", "addr_line_3": "", "addr_post_code": "1600022", "email": "issuer@example.com", "phone_number": "0312345678", }, "lines": [ { "date": "2025/12/25", "name": "商品B", "unit_price": 10000, "quantity": 2, "tax_rate": 10, } ], "pay_types": [ "Virtualaccount", "Card", ], "card": { "job_code": "CAPTURE", }, "due_date": "2026/01/31", } response = requests.post( url, headers=HEADERS, json=data, timeout=10, ) response.raise_for_status() body = response.json() print("Create Invoice:", body) return body def open_invoice(invoice_id: str): """インボイス発行""" url = f"{BASE_URL}/v1/invoices/{invoice_id}/open" data = { "bill_mail_send_flag": "0", "receipt_mail_send_flag": "0", "underpayment_mail_send_flag": "0", } response = requests.put( url, headers=HEADERS, json=data, timeout=10, ) response.raise_for_status() body = response.json() print("Open Invoice:", body) return body if __name__ == "__main__": #登録した顧客IDと合わせる CUSTOMER_ID = "CUST001" #インボイス作成 created = create_invoice(CUSTOMER_ID) invoice_id = created["id"] print("Invoice ID:", invoice_id) #インボイス発行 opened = open_invoice(invoice_id) print("Invoice URL:", opened.get("invoice_url")) コードの流れを分解して理解する ここからは、上記コードの流れをステップごとに分解して見ていきます。 ① APIキーと環境変数を設定する Python API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") BASE_URL = "https://api.test.fincode.jp" テスト環境用のシークレットキーを、環境変数 FINCODE_TEST_SECRET_KEY から取得します。 セキュリティ上、APIキーをPythonコードに直書きするのは推奨されません。環境変数で管理しましょう。 ② 顧客IDを登録する(/v1/customers) Python data = { "id": "CUST001", "name": "aaa" } 主な項目は以下の通りです。 項目 内容 補足 id 顧客ID インボイスAPIから参照するID name 顧客名 任意の文字列 ここで登録した CUST001 を、後続のインボイス作成APIの customer_id に指定します。 ③ インボイス作成APIで請求内容を登録する(/v1/invoices) Python data = { "customer_id": customer_id, "customer_honorific": "様", "customer_overwrite": { "name": "株式会社テスト", "email": "customer@example.com", "addr_state": "13", "addr_city": "新宿区", "addr_line_1": "1-1-1", "addr_line_2": "テストビル", "addr_line_3": "", "addr_post_code": "1600022", }, "issuer_overwrite": { "addr_state": "13", "addr_city": "新宿区", "addr_line_1": "1-1-1", "addr_line_2": "テストビル", "addr_line_3": "", "addr_post_code": "1600022", "email": "issuer@example.com", "phone_number": "0312345678", }, "lines": [ { "date": "2025/12/25", "name": "商品B", "unit_price": 10000, "quantity": 2, "tax_rate": 10, } ], "pay_types": [ "Virtualaccount", "Card", ], "card": { "job_code": "CAPTURE", }, "due_date": "2026/01/31", } 主な項目は以下の通りです。 項目 内容 補足 id 顧客ID 事前に登録した CUST001 customer_honorific 敬称 「様」「御中」など customer_overwrite 顧客情報の上書き 請求書上に表示したい宛名や住所など issuer_overwrite 発行元情報の上書き 自社の住所・連絡先など lines 請求明細の配列 商品名・単価・数量・税率など pay_types 利用可能な決済手段 "Card" / "Virtualaccount" など card.job_code 売上確定方法 "CAPTURE" = 即時売上 / "AUTH" = 仮売上 due_date 支払期日 yyyy/MM/dd 形式 この時点では、インボイスのステータスは「DRAFT(下書き)」の状態です。 請求自体はまだ開始されていません。 ④ インボイス発行APIで請求を開始する(/v1/invoices/{id}/open) Python data = { "bill_mail_send_flag": "0", "receipt_mail_send_flag": "0", "underpayment_mail_send_flag": "0", } 主なフラグは次の通りです。 項目 内容 bill_mail_send_flag 請求書メール送信フラグ("0":送信しない / "1":送信する) receipt_mail_send_flag 領収書メール送信フラグ("0":送信しない / "1":送信する) underpayment_mail_send_flag 差額請求メール送信フラグ("0":送信しない / "1":送信する) 成功すると、レスポンスに status: AWAITING_CUSTOMER_PAYMENT(支払い待ち)などのステータス invoice_url: 顧客向けの請求ページURL が含まれます。この invoice_url を顧客に共有することで、オンラインでの支払いが可能になります。 インボイスのテストを行う テスト環境でインボイスを発行したら、レスポンスに含まれる invoice_url をブラウザで開いてみてください。 請求内容・金額・支払期日などが表示された請求ページが開く カード決済を有効にしている場合、テスト用カード番号を使って支払いテストが可能 fincodeではテスト用のカード番号やテストリソースが用意されています。詳細はドキュメントをご確認ください。 テスト時は、有効期限やカード名義人は任意の値で問題ありません。 想定質問(FAQ) Q1. 決済手段をカードだけにするにはどうすればいいですか? → pay_types を ["Card"] のみにしてください。 バーチャル口座のみを使いたい場合は ["Virtualaccount"] のみにする、という形で制御できます。 Q2. 請求番号(invoice_number)は必須ですか? → 本記事のサンプルでは指定していませんが、指定しない場合はインボイス発行時に自動採番されます。 Q3. 本番環境で使うには何を変えれば良いですか? → 主に以下の2点です。 BASE_URL を https://api.fincode.jp に変更 本番環境用のシークレットキーを環境変数に設定 それ以外のリクエスト形式(ヘッダーやJSON構造など)は基本的に同じです。 おわりに 本記事では、fincodeのテスト環境を使って、Pythonで簡単に”決済機能付き請求書”をAPI経由で発行できる「インボイス機能」の実装について説明しました。 ぜひ、今回のサンプルをベースに、自社サービスの請求・入金まわりの自動化にチャレンジしてみてください。   ■ この記事の作成者 fincode マーケティング担当 非エンジニアのバックグラウンドを持ちながら、基本情報技術者試験に合格。 現在はデータ分析にPythonを活用し、プロダクトへの理解を深めるためGo言語の習得にも挑戦中。 読者に近い視点から、複雑な決済技術を噛み砕いてお伝えします。 ■ この記事の監修者 fincode プロダクトマネージャー オンライン決済インフラ『fincode byGMO』の新機能企画・製品ディレクション等を統括。 プロダクトマネジメントの傍ら、個人開発者として自らコードを書く時間も大切にしている。 現場のエンジニアが直面する課題に寄り添い、情報の正確性と実用性を徹底して監修。   運営会社 会社名 GMOイプシロン株式会社(英文表記:GMO Epsilon, Inc.) 設立年月日 2002年9月26日 所在地 〒150-0043 東京都渋谷区道玄坂1丁目14番6号 ヒューマックス渋谷ビル7F 資本金 1億5百万円 事業内容 オンライン販売の決済代行、代金回収代行及びそれらに付帯する業務 主要株主 GMOペイメントゲートウェイ株式会社 (東証プライム上場:3769) グループ会社 GMOインターネットグループ 東証プライム上場企業のGMOペイメントゲートウェイの連結会社として、プライバシーマーク認証やPCI DSS、ISMS準拠のセキュリティ基準で安心してご利用いただける環境を提供しています。   事業規模によって決済手数料のご提案が可能です。 見積依頼 > fincodeサービス概要の資料ダウンロードはこちらから 資料請求 >   あわせて読みたいおすすめの記事 【初心者向け】Pythonでサブスク決済を実装する方法|fincodeで自動課金システムを構築 【初心者向け】Pythonでfincodeの決済APIを実行する実装例(決済URL作成編) 【Python】クレジットカード決済の実装方法(決済登録API+決済実行JS編) Python(Flask)でPayPay決済APIを実装する方法(決済登録API+決済実行API)

マーケティングチーム

【Python】PayPay決済APIを実装する方法(決済登録API+決済実行API)

fincodeマーケティング担当です。 本記事では、Python(Flask)からfincodeのPayPay決済APIを実行する方法を、コピペで動くサンプルコード付きで解説します。 Python初心者〜バックエンドエンジニアまで、誰でも迷わず実装できるように、 事前準備(APIキー・Python環境) サーバーサイドの実装コード(Python/Flask) フロントエンドの実装コード(HTML) 成功レスポンスの読み解き方 エラーレスポンスの読み解き方 まで一通りおさえていきます。 PayPayとは PayPayは、日本国内で広く普及しているスマホ決済のひとつです。 実店舗での利用イメージが強いですが、オンライン決済でも利用が拡大しています。 fincodeでは、Webページ(本記事のサンプルでは index.html) → PayPayの支払い画面 → 自社サービスの完了画面というオンライン決済フローを、API経由で簡単に実装できます。 PythonでのPayPay決済処理の全体フロー PayPay決済の流れは、シンプルにまとめると次の3ステップです。 1. サーバー(Python/Flask)で決済登録API を呼ぶ 2. 決済実行API を呼び、PayPayの支払い画面に遷移するURL(code_url)を取得 3.フロントエンドから code_url にリダイレクト → 購入者がPayPayの支払い画面で支払う サーバー側(Python/Flask)がやること 今回のシンプルな実装例では、サーバー側の役割は次の通りです。 1.POST /v1/payments で PayPayの決済登録API を呼ぶ 2.レスポンスで返ってきた id / access_id を使って PUT /v1/payments/{id} で 決済実行API を呼ぶ 3.返却された code_url をフロントへ返す この時点ではステータスは AWAITING_CUSTOMER_PAYMENT(お客様の支払い待ち)で、実際の引き落としはまだ行われていません。 購入者の支払いフロー 購入者側の流れは以下の通りです。 1. Webページで「PayPayで支払う」を押す 2. PayPayの支払い画面に自動遷移 3. 決済内容を確認 4. 支払い確定 5. 成功画面(本記事の例では http://localhost:5000/success)へリダイレクト 以上が全体の大まかな流れです。 次からは、実際の実装について解説していきます。 事前準備(APIキー・Python環境) fincodeのAPIキーの取得方法 1. fincodeテスト環境の管理画面にログイン テスト環境のアカウントを作成する > テスト環境管理画面にログインする > 2. 「API・Webhook」タブから シークレットキー をコピー fincodeのテスト用シークレットキーは「m_test_**********************」という形式です。 3. 環境変数に設定する シークレットキーは、セキュリティの観点からコードに直書きせず、環境変数から読み込むことを推奨します。 本記事の実装例では、シークレットキーは環境変数(※1)から読み込みます。 (※1)プログラムが動く環境(パソコンやサーバー)にあらかじめ登録しておく設定情報のことです。APIキーなどの秘密情報をコードに書かず、安全に管理するために使われます。 Python環境のセットアップ 今回のサンプルで使用するライブラリは次の2つです。 Flask:簡易サーバー&HTMLテンプレート用 requests:fincode API を叩くためのHTTPクライアント bash pip install flask requests サーバーサイド実装(Python / Flask) まずは、fincodeのPayPay決済APIを実行するサーバー側のコードです。 app.py として保存します。 Python import os from flask import Flask, jsonify, render_template import requests app = Flask(__name__) API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") BASE_URL = "https://api.test.fincode.jp" HEADERS = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } # PayPay決済後のリダイレクト先 REDIRECT_URL = "http://localhost:5000/success" SERVER_AMOUNT = 1500 @app.route("/") def index(): return render_template("index.html", amount=SERVER_AMOUNT) @app.route("/api/paypay/start", methods=["POST"]) def start_paypay(): amount = SERVER_AMOUNT # 1. 決済登録(POST /v1/payments) register_res = requests.post( f"{BASE_URL}/v1/payments", headers=HEADERS, json={ "pay_type": "Paypay", "job_code": "CAPTURE", "amount": str(amount), }, timeout=10, ) if not register_res.ok: return jsonify({"error": "register_failed"}), 502 register_json = register_res.json() payment_id = register_json.get("id") access_id = register_json.get("access_id") if not payment_id or not access_id: return jsonify({"error": "missing_id_or_access_id"}), 502 # 2. 決済実行(PUT /v1/payments/{id}) execute_res = requests.put( f"{BASE_URL}/v1/payments/{payment_id}", headers=HEADERS, json={ "pay_type": "Paypay", "access_id": access_id, "redirect_url": REDIRECT_URL, }, timeout=10, ) if not execute_res.ok: return jsonify({"error": "execute_failed"}), 502 execute_json = execute_res.json() code_url = execute_json.get("code_url") if not code_url: return jsonify({"error": "missing_code_url"}), 502 # フロント側では code_url にリダイレクト return jsonify( { "payment_id": payment_id, "access_id": access_id, "code_url": code_url, } ) @app.route("/success") def success(): return "PayPay決済が完了しました。" if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True) ポイントは POST /v1/payments で決済登録 → レスポンスから id と access_id を取得 PUT /v1/payments/{id} で決済実行 → code_url を取得 です。 フロントエンド実装(HTML) 次に、「PayPayで支払う」ボタンだけを持ったシンプルなフロントエンドです。 templates/index.html として保存します(Flaskのテンプレートディレクトリ)。 html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>PayPay決済テスト</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; max-width: 640px; margin: 40px auto; padding: 0 16px; line-height: 1.6; } h1 { font-size: 1.4rem; margin-bottom: 1rem; } p { margin-top: 0.5rem; } button { margin-top: 1.5rem; padding: 10px 16px; font-size: 1rem; cursor: pointer; } </style> </head> <body> <h1>PayPay決済テスト</h1> <p style="font-size: 1.2rem; font-weight: 700; margin-top: 0.5rem;"> お支払い金額: <span style="font-size: 1.4rem;"> {{ "{:,}".format(amount) }} </span> 円 </p> <button id="paypay-button">PayPayで支払う</button> <script> document.getElementById("paypay-button").addEventListener("click", async () => { try { const res = await fetch("/api/paypay/start", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({}), }); const data = await res.json(); if (!res.ok) { alert("エラーが発生しました。コンソールを確認してください。"); console.error("Error response:", data); return; } if (data.code_url) { window.location.href = data.code_url; } else { alert("code_url が取得できませんでした。コンソールを確認してください。"); console.error("No code_url:", data); } } catch (err) { alert("通信エラーが発生しました"); console.error(err); } }); </script> </body> </html> ここでは 金額は サーバー側から渡された amount を表示 ボタンを押すと /api/paypay/start に POST 返ってきた code_url に window.location.href で遷移 という、シンプルな構成にしています。 成功レスポンスの読み解き方 PUT /v1/payments/{id} の成功時レスポンス(抜粋)は、次のようなイメージです。 json { "id": "o_**********************", "access_id": "a_**********************", "code_url": "https://**********************" } 項目 意味 id オーダーID。決済情報ID(今回はこれを {id} に使う) access_id 取引ID code_url PayPayの支払い画面へ遷移するためのURL エラーレスポンスの読み解き方 本記事のサンプルコードでは、最低限のエラーハンドリングとして、 決済登録APIが 200 以外 → {"error": "register_failed"} 決済実行APIが 200 以外 → {"error": "execute_failed"} id / access_id / code_url が欠けている → missing_... エラー を返すようにしています。 FAQ Q1. Python初心者でも実装できますか? →はい。この記事のコードをそのまま実行するだけで動作します。 Q2. どんなフォルダ構成にすればいいですか? →今回のサンプルでは、次のようなシンプルな構成にしています。 プロジェクトフォルダ/ ├─ app.py └─ templates/    └─ index.html app.py … Python(Flask)の本体 templates/index.html … 画面(HTML)のファイル この形にしておけば、python app.py を実行して ブラウザで http://localhost:5000/ を開くだけで動きます。 Q3. サンプルコードはどうやって起動すればいいですか? →以下4ステップを実行すると起動します。 1.ターミナル(またはPowerShell、コマンドプロンプト)を開く 2. app.py があるフォルダに移動 bash cd プロジェクトフォルダ 3.Flaskアプリを起動 bash python app.py 4.ブラウザで http://localhost:5000/ を開く 「PayPayで支払う」ボタンが表示されていれば成功です。 まとめ 本記事では、fincodeを使ってPayPay決済をPython(Flask)から実行する方法を紹介しました。 非エンジニアであるマーケティング担当者でも数十行の簡単なコードで実装ができたので、fincodeが開発しやすいことを実感しました。   ■ この記事の作成者 fincode マーケティング担当 非エンジニアのバックグラウンドを持ちながら、基本情報技術者試験に合格。 現在はデータ分析にPythonを活用し、プロダクトへの理解を深めるためGo言語の習得にも挑戦中。 読者に近い視点から、複雑な決済技術を噛み砕いてお伝えします。 ■ この記事の監修者 fincode プロダクトマネージャー オンライン決済インフラ『fincode byGMO』の新機能企画・製品ディレクション等を統括。 プロダクトマネジメントの傍ら、個人開発者として自らコードを書く時間も大切にしている。 現場のエンジニアが直面する課題に寄り添い、情報の正確性と実用性を徹底して監修。   fincodeとは fincodeとは、GMOイプシロン株式会社が提供する、スピーディに導入できるオンライン決済サービスです。 シンプルで統一性のあるAPIと充実の開発支援コンテンツを提供し、エンジニアファーストな設計を追求しています。 fincodeが提供する決済画面のUIコンポーネント(JavaScript)をそのまま利用することで開発工数を削減し、簡単に決済を実装できます。 決済を通じてEC/SaaS/プラットフォーム、スタートアップからエンタープライズまで様々なビジネスの成長を支えます。 +FinTechによる新たな収益モデルの構築 fincodeのプラットフォーム機能を実装することで、決済金額に対する利用料が得られる新たな収益モデルの構築が可能です。 貴社のお客様(=テナント)へ提示する決済手数料に、「プラットフォーム利用料」を設定することで、差額が貴社の収益となります。 「貴社プロダクト + FinTech~新たな収益モデル構築のご提案~」資料ダウンロード > fincodeが選ばれる理由 エンジニアファーストの設計/洗練されたUX オープンでアクセスしやすいWEBドキュメント、REST APIと複数開発言語に対応したAPIリファレンス。 決済画面のUIも、Android/iOS対応のモバイルSDKにより、少ない開発工数で柔軟にカスタマイズ可能です。 見えない手数料、ゼロへ 初期費用・月額費用0円。 さらに、義務化されたEMV 3-Dセキュア認証についても追加費用0円で導入できます。 料金表に書かれていない見えない手数料はゼロ。カード決済は決済手数料のみでご利用いただけます。 国際標準を日本品質で fincodeは日本国内で生まれ、日本のビジネス環境に合わせて設計された決済サービスです。 海外発サービスでは難しい、日本ならではの細かな商習慣や感性まで理解して、日本の企業と共に成長していきます。 運営会社 会社名 GMOイプシロン株式会社(英文表記:GMO Epsilon, Inc.) 設立年月日 2002年9月26日 所在地 〒150-0043 東京都渋谷区道玄坂1丁目14番6号 ヒューマックス渋谷ビル7F 資本金 1億5百万円 事業内容 オンライン販売の決済代行、代金回収代行及びそれらに付帯する業務 主要株主 GMOペイメントゲートウェイ株式会社 (東証プライム上場:3769) グループ会社 GMOインターネットグループ 東証プライム上場企業のGMOペイメントゲートウェイの連結会社として、プライバシーマーク認証やPCI DSS、ISMS準拠のセキュリティ基準で安心してご利用いただける環境を提供しています。   事業規模によって決済手数料のご提案が可能です。 見積依頼 > fincodeサービス概要の資料ダウンロードはこちらから 資料請求 >   あわせて読みたいおすすめの記事 【Python】クレジットカード決済の実装方法(決済登録API+決済実行JS編) 【初心者向け】Pythonでfincodeの決済APIを実行する実装例(決済URL作成編) 【初心者向け】fincodeで請求業務DX|Pythonで”決済機能付き請求書”をAPI発行する方法(インボイス機能) 【初心者向け】Pythonでサブスク決済を実装する方法|fincodeで自動課金システムを構築

マーケティングチーム

【Python】クレジットカード決済の実装方法(決済登録API+決済実行JS編)

fincodeマーケティング担当です。 クレジットカード決済を実装したい開発者向けに、「決済登録(サーバー側 / API)+決済実行(フロント側 / fincodeJS)」を組み合わせて最小構成で動作する決済実装方法をまとめました。 サーバー側はPython(Flask)で構築しています。 ※本記事の実装例は、非エンジニアが記述しているので、決済導入が初めてのエンジニアの方や、ビジネスサイドの方でも概要をイメージできる内容になっています。 本実装例で実現できること 本記事で紹介する「決済登録API+決済実行JS」の実装を行うと、以下を実現できます。 APIでクレジットカード決済を実行 3Dセキュア2.0の認証 fincodeの決済フローを簡単に理解する fincodeのクレジットカード決済は、以下の「2段階」で構成されます。 ① 決済登録(サーバー側 / API) サーバー側で/v1/paymentsにリクエストし、決済オブジェクト(支払情報)を作成します。 ② 決済実行(フロント側 / fincodeJS) ブラウザ側のJavaScriptでカード番号などの情報を入力し、決済を実行(オーソリ・売上処理)します。 カード番号などの機密情報は、サーバー側は扱わずfincodeJSで完結できるため、セキュリティ面は安心です。 必要なAPIキー(パブリックキー/シークレットキー) fincodeのテスト環境管理画面にログイン後、「API・Webhook」タブからAPIキーを確認できます。 テスト環境のアカウントを作成する > テスト環境管理画面にログインする > 種類 用途 例 パブリックキー ブラウザ(決済実行JS)で使用 p_test_********************** シークレットキー サーバー側からfincodeのAPIにアクセスする際に使用 m_test_********************** パブリックキーはフロント側に埋め込めますが、シークレットキーはセキュリティ上、コード内に直接書くことは推奨されません。 本記事の実装例では、シークレットキーは環境変数(※1)から読み込みます。 (※1)プログラムが動く環境(パソコンやサーバー)にあらかじめ登録しておく設定情報のことです。APIキーなどの秘密情報をコードに書かず、安全に管理するために使われます。 プロジェクト構成(最小構成) v1payments/Card/ ├─ app.py       ← 決済登録API(Flask) └─ static/    └─ index.html  ← 決済実行画面(フロント) サーバー側(Python / Flask)の実装 以下のコードを app.py に保存します。 python import os import requests from flask import Flask, jsonify, request, send_from_directory app = Flask(__name__, static_folder="static", static_url_path="/static") API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") # m_test_********************** BASE_URL = "https://api.test.fincode.jp" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } @app.route("/api/payment", methods=["POST"]) def create_payment(): data = { "pay_type": "Card", "amount": "1000", "job_code": "CAPTURE", "tds_type": "2" } response = requests.post( f"{BASE_URL}/v1/payments", headers=headers, json=data, timeout=20, ) response.raise_for_status() return jsonify(response.json()) @app.route("/") def root(): return send_from_directory("static", "index.html") if __name__ == "__main__": app.run(host="0.0.0.0", port=3000, debug=True) フロント(決済実行JS+入力画面)の実装 以下を static/index.html に保存します。 html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>fincode 決済テスト</title> <script src="https://js.test.fincode.jp/v1/fincode.js"></script> <style> body { font-family: sans-serif; max-width: 480px; margin: 40px auto; } input { width: 100%; padding: 8px; margin: 4px 0; } button { width: 100%; padding: 10px; margin-top: 12px; } pre { background: #f5f5f5; padding: 10px; } </style> </head> <body> <h2>fincode 決済テスト</h2> <label>カード番号</label> <input id="card_no" type="text" placeholder="4100000000000100"> <label>有効期限(YYMM)</label> <input id="expire" type="text" placeholder="2711"> <label>セキュリティコード</label> <input id="security_code" type="text" placeholder="123"> <button id="pay">決済する</button> <h3>レスポンスログ</h3> <pre id="log">{}</pre> <script> const FINCODE_PUBLIC_KEY = "p_test_**********************"; // ← パブリックキーを入力 const fincode = Fincode(FINCODE_PUBLIC_KEY); const el = id => document.getElementById(id); const log = data => el("log").textContent = JSON.stringify(data, null, 2); document.getElementById("pay").addEventListener("click", async () => { // ① 決済登録(サーバー → fincode) const regRes = await fetch("/api/payment", { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify({}) }); const reg = await regRes.json(); log({ register: reg }); // ② 決済実行(ブラウザ → fincodeJS) const tx = { id: reg.id, pay_type: "Card", access_id: reg.access_id, card_no: el("card_no").value, expire: el("expire").value, security_code: el("security_code").value, method: "1" }; fincode.payments( tx, (status, response) => log({ execute_status: status, response }), () => log({ error: "network_error" }) ); }); </script> </body> </html> これで以下が実現します: カード番号などの入力 /api/payment で決済登録 fincode.payments() で決済実行 完了後のレスポンスを画面表示   実行方法(最短4ステップ) ① Flask を起動 bash python app.py ②ブラウザからアクセス http://localhost:3000/   ③カード情報等を入力し、決済実行 テスト用のカード番号はdocsからご確認いただけます。 今回は、3Dセキュア2.0がすぐに認証成功するテストカード番号「4100000000000100」を利用しました。 ④レスポンスログ内の redirect_url にアクセス → 即時3Dセキュア認証成功 まとめ 本記事では、fincodeの「決済実行JS」を使って、最小構成でクレジットカード決済を実装する方法を紹介しました。 非エンジニアであるマーケティング担当者でも数十行の簡単なコードで実装ができたので、fincodeが開発しやすいことを実感しました。   ■ この記事の作成者 fincode マーケティング担当 非エンジニアのバックグラウンドを持ちながら、基本情報技術者試験に合格。 現在はデータ分析にPythonを活用し、プロダクトへの理解を深めるためGo言語の習得にも挑戦中。 読者に近い視点から、複雑な決済技術を噛み砕いてお伝えします。 ■ この記事の監修者 fincode プロダクトマネージャー オンライン決済インフラ『fincode byGMO』の新機能企画・製品ディレクション等を統括。 プロダクトマネジメントの傍ら、個人開発者として自らコードを書く時間も大切にしている。 現場のエンジニアが直面する課題に寄り添い、情報の正確性と実用性を徹底して監修。   fincodeとは fincodeとは、GMOイプシロン株式会社が提供する、スピーディに導入できるオンライン決済サービスです。 シンプルで統一性のあるAPIと充実の開発支援コンテンツを提供し、エンジニアファーストな設計を追求しています。 fincodeが提供する決済画面のUIコンポーネント(JavaScript)をそのまま利用することで開発工数を削減し、簡単に決済を実装できます。 決済を通じてEC/SaaS/プラットフォーム、スタートアップからエンタープライズまで様々なビジネスの成長を支えます。 +FinTechによる新たな収益モデルの構築 fincodeのプラットフォーム機能を実装することで、決済金額に対する利用料が得られる新たな収益モデルの構築が可能です。 貴社のお客様(=テナント)へ提示する決済手数料に、「プラットフォーム利用料」を設定することで、差額が貴社の収益となります。 「貴社プロダクト + FinTech~新たな収益モデル構築のご提案~」資料ダウンロード > fincodeが選ばれる理由 エンジニアファーストの設計/洗練されたUX オープンでアクセスしやすいWEBドキュメント、REST APIと複数開発言語に対応したAPIリファレンス。 決済画面のUIも、Android/iOS対応のモバイルSDKにより、少ない開発工数で柔軟にカスタマイズ可能です。 見えない手数料、ゼロへ 初期費用・月額費用0円。 さらに、義務化されたEMV 3-Dセキュア認証についても追加費用0円で導入できます。 料金表に書かれていない見えない手数料はゼロ。カード決済は決済手数料のみでご利用いただけます。 国際標準を日本品質で fincodeは日本国内で生まれ、日本のビジネス環境に合わせて設計された決済サービスです。 海外発サービスでは難しい、日本ならではの細かな商習慣や感性まで理解して、日本の企業と共に成長していきます。 運営会社 会社名 GMOイプシロン株式会社(英文表記:GMO Epsilon, Inc.) 設立年月日 2002年9月26日 所在地 〒150-0043 東京都渋谷区道玄坂1丁目14番6号 ヒューマックス渋谷ビル7F 資本金 1億5百万円 事業内容 オンライン販売の決済代行、代金回収代行及びそれらに付帯する業務 主要株主 GMOペイメントゲートウェイ株式会社 (東証プライム上場:3769) グループ会社 GMOインターネットグループ 東証プライム上場企業のGMOペイメントゲートウェイの連結会社として、プライバシーマーク認証やPCI DSS、ISMS準拠のセキュリティ基準で安心してご利用いただける環境を提供しています。   事業規模によって決済手数料のご提案が可能です。 見積依頼 > fincodeサービス概要の資料ダウンロードはこちらから 資料請求 >   あわせて読みたいおすすめの記事 Python(Flask)でPayPay決済APIを実装する方法(決済登録API+決済実行API) 【初心者向け】Pythonでfincodeの決済APIを実行する実装例(決済URL作成編) 【初心者向け】fincodeで請求業務DX|Pythonで”決済機能付き請求書”をAPI発行する方法(インボイス機能) 【初心者向け】Pythonでサブスク決済を実装する方法|fincodeで自動課金システムを構築

マーケティングチーム

【初心者向け】Pythonでfincodeの決済APIを実行する実装例(決済URL作成編)

fincodeマーケティング担当です。 この記事では、fincodeのテスト環境を使って、たった数十行のPythonコードでカード決済を開始できる「決済URL作成API」の実装について説明します。 ※本記事の実装例は、非エンジニアが記述しているので、決済導入が初めてのエンジニアの方や、ビジネスサイドの方でも概要をイメージできる内容になっています。 本実装例で実現できること 本記事で紹介する「決済URL作成API」の実装を行うと、以下を実現できます。 fincodeが提供するリダイレクト型決済ページを発行し、その決済ページへのURLを出力 リダイレクト型決済ページから決済のテストを実行 リダイレクト型決済とは リダイレクト型決済は、fincodeが提供する決済画面を使用して購入者が決済を行う方法です。 ショップ自身で決済画面を構築することなく、fincodeの決済URLに購入者を誘導するだけで決済を行うことができます。 「オンライン決済接続方式比較ガイド」資料ダウンロード > コード全文:最小構成で動くPythonサンプル Python import os, requests, json API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") BASE_URL = "https://api.test.fincode.jp" ENDPOINT = "/v1/sessions" SUCCESS_URL = "http://localhost:8000/success" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } data = { "success_url": SUCCESS_URL, "transaction": { "pay_type": ["Card"], "amount": "1500" }, "card": { "job_code": "CAPTURE", "tds_type": "2", "tds2_type": "2" } } try: resp = requests.post(f"{BASE_URL}{ENDPOINT}", headers=headers, json=data, timeout=20) resp.raise_for_status() print("OK:\n" + json.dumps(resp.json(), ensure_ascii=False, indent=2)) except requests.exceptions.HTTPError: try: print(json.dumps(resp.json(), ensure_ascii=False, indent=2)) except Exception: print(resp.text) コードの流れを分解して理解する ①認証キーの設定 Python API_KEY = os.getenv("FINCODE_TEST_SECRET_KEY") テスト用シークレットキーを環境変数(※1)から取得します。 fincodeのテスト用シークレットキーは「m_test_**********************」という形式です。 fincodeのテスト環境管理画面にログイン後、「API・Webhook」タブからAPIキーを確認できます。 テスト環境のアカウントを作成する > テスト環境管理画面にログインする > セキュリティ上、APIキーをコード内に直接書くことは推奨されません。 ②リクエストヘッダーとリクエストボディ Python headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } Authorizationヘッダーは "Bearer <キー>" の形式で送信します。 fincodeではBearer認証(※2)またはBasic認証が使用できます。本記事ではBearer認証で実装しています。 ヘッダーでは認証とJSON形式の指定を行い、ボディには以下の内容を指定します。 項目 内容 補足 success_url 決済完了後の戻り先 ローカル開発時はlocalhostでもOK pay_type 利用する決済手段 今回は「Card」のみ amount 決済金額 文字列で送信(例: "1500") job_code 売上確定方法 「CAPTURE」=即時売上、「AUTH」=仮売上 tds_type / tds2_type 3Dセキュア設定 「2」は3Dセキュア2.0対応 ※カード決済以外の決済手段を追加する方法はAPIリファレンスをご参照ください。 APIリファレンス > ③APIを実行 Python resp = requests.post(f"{BASE_URL}{ENDPOINT}", headers=headers, json=data, timeout=20) requests.post()で決済URL作成APIを呼び出します。 成功すると、以下のようなJSONレスポンスが返ってきます。 json { "id": "lk_**********************", "link_url": "https://secure.test.fincode.jp/v1/links/lk_**********************", } この link_url をブラウザで開くと、テスト用のリダイレクト型決済ページが表示されます。 ④エラー時の挙動 Python rexcept requests.exceptions.HTTPError: try: print(json.dumps(resp.json(), ensure_ascii=False, indent=2)) except Exception: print(resp.text) APIキーが誤っているなどの理由でエラーが発生した場合、APIが返したエラーメッセージを整形して表示します。 決済のテストを行う リダイレクト型決済ページにおいて、テストカードの番号を用いることで、カード決済のテストを行うことができます。 テストカードの番号はこちらからご確認いただけます。 カードの「有効期限、CVC、名前」は適当な内容で問題ないです。 (※1)プログラムが動く環境(パソコンやサーバー)にあらかじめ登録しておく設定情報のことです。APIキーなどの秘密情報をコードに書かず、安全に管理するために使われます。 (※2)APIキー(アクセストークン)をAPIリクエスト時に送ることで認証する方式です。認証に成功した場合のみリソースを参照・操作できます。 想定質問(FAQ) Q1. timeout は削除しても動きますか?→ 動作はしますが、サーバー応答が途絶えた際にプログラムが止まるリスクがあります。実運用では必須です。 Q2. CAPTURE と AUTH の違いは?→ CAPTUREは即時売上、AUTHは仮売上(後から確定)。 Q3. Bearerを付け忘れると?→ 認証エラー(401)が返ります。ヘッダーの形式 "Authorization": "Bearer <キー>" を必ず確認しましょう。 Q4. 本番環境では何を変える?→ BASE_URL を https://api.fincode.jp に変更し、本番用APIキーを設定します。 おわりに 本記事では、fincodeのテスト環境を使って、たった数十行のPythonコードでカード決済を開始できる「決済URL作成API」の実装について説明しました。 非エンジニアであるマーケティング担当者でも数十行の簡単なコードで実装ができたので、fincodeが開発しやすいことを実感しました。   ■ この記事の作成者 fincode マーケティング担当 非エンジニアのバックグラウンドを持ちながら、基本情報技術者試験に合格。 現在はデータ分析にPythonを活用し、プロダクトへの理解を深めるためGo言語の習得にも挑戦中。 読者に近い視点から、複雑な決済技術を噛み砕いてお伝えします。 ■ この記事の監修者 fincode プロダクトマネージャー オンライン決済インフラ『fincode byGMO』の新機能企画・製品ディレクション等を統括。 プロダクトマネジメントの傍ら、個人開発者として自らコードを書く時間も大切にしている。 現場のエンジニアが直面する課題に寄り添い、情報の正確性と実用性を徹底して監修。   fincodeとは fincodeとは、GMOイプシロン株式会社が提供する、スピーディに導入できるオンライン決済サービスです。 シンプルで統一性のあるAPIと充実の開発支援コンテンツを提供し、エンジニアファーストな設計を追求しています。 fincodeが提供する決済画面のUIコンポーネント(JavaScript)をそのまま利用することで開発工数を削減し、簡単に決済を実装できます。 決済を通じてEC/SaaS/プラットフォーム、スタートアップからエンタープライズまで様々なビジネスの成長を支えます。 +FinTechによる新たな収益モデルの構築 fincodeのプラットフォーム機能を実装することで、決済金額に対する利用料が得られる新たな収益モデルの構築が可能です。 貴社のお客様(=テナント)へ提示する決済手数料に、「プラットフォーム利用料」を設定することで、差額が貴社の収益となります。 「貴社プロダクト + FinTech~新たな収益モデル構築のご提案~」資料ダウンロード > fincodeが選ばれる理由 エンジニアファーストの設計/洗練されたUX オープンでアクセスしやすいWEBドキュメント、REST APIと複数開発言語に対応したAPIリファレンス。 決済画面のUIも、Android/iOS対応のモバイルSDKにより、少ない開発工数で柔軟にカスタマイズ可能です。 見えない手数料、ゼロへ 初期費用・月額費用0円。 さらに、義務化されたEMV 3-Dセキュア認証についても追加費用0円で導入できます。 料金表に書かれていない見えない手数料はゼロ。カード決済は決済手数料のみでご利用いただけます。 国際標準を日本品質で fincodeは日本国内で生まれ、日本のビジネス環境に合わせて設計された決済サービスです。 海外発サービスでは難しい、日本ならではの細かな商習慣や感性まで理解して、日本の企業と共に成長していきます。 運営会社 会社名 GMOイプシロン株式会社(英文表記:GMO Epsilon, Inc.) 設立年月日 2002年9月26日 所在地 〒150-0043 東京都渋谷区道玄坂1丁目14番6号 ヒューマックス渋谷ビル7F 資本金 1億5百万円 事業内容 オンライン販売の決済代行、代金回収代行及びそれらに付帯する業務 主要株主 GMOペイメントゲートウェイ株式会社 (東証プライム上場:3769) グループ会社 GMOインターネットグループ 東証プライム上場企業のGMOペイメントゲートウェイの連結会社として、プライバシーマーク認証やPCI DSS、ISMS準拠のセキュリティ基準で安心してご利用いただける環境を提供しています。   事業規模によって決済手数料のご提案が可能です。 見積依頼 > fincodeサービス概要の資料ダウンロードはこちらから 資料請求 >   あわせて読みたいおすすめの記事 【初心者向け】fincodeで請求業務DX|Pythonで”決済機能付き請求書”をAPI発行する方法(インボイス機能) 【初心者向け】Pythonでサブスク決済を実装する方法|fincodeで自動課金システムを構築 【Python】クレジットカード決済の実装方法(決済登録API+決済実行JS編) Python(Flask)でPayPay決済APIを実装する方法(決済登録API+決済実行API)

マーケティングチーム

新機能追加のお知らせ:リダイレクト型決済でコンビニ決済が利用できるようになりました!

リダイレクト型決済でもコンビニ決済をご利用いただけるようになりました! 本記事では、メールリンク機能を用いてコンビニ決済をご利用いただくための方法をご紹介いたします。   なお、WEBサイトなどの貴サービスへfincodeの決済機能を組み込んで決済処理を実行される方はシステム仕様など詳細について下記ページをご参照ください。 ▼fincode Docs https://docs.fincode.jp/ ▼API reference https://docs.fincode.jp/api ▼Product Blog「fincodeの決済APIの利用する仕組みと方法」 https://blog.fincode.jp/product_blog/244-2/    メールリンクの送信方法 ①ログイン後、左メニュー>メールリンクをクリックし、「決済作成」ボタンをクリック ②クリック後、以下の画面が表示されるので、「金額」まで項目に沿って入力 ※今回は「メールアドレスを直接入力して送信する」送信方法でご紹介いたします。 ③「決済手段(最低1つ選択)」にて、「コンビニ決済」を選択。その他、必要項目を入力し「確認」をクリック ※カード決済、コンビニ決済を2種類選んだ際は、購入者の画面で決済手段が選べるようになります。今回はコンビニ決済のみ選択します。 ※成功URLおよびキャンセルURLの指定がない場合は、fincodeのデフォルトの画面が表示されます ④メールリンクの設定詳細画面が表示されます。こちらでコンビニ決済のメールリンク作成は完了です。 お客様の実際のお支払い画面 ①指定したメールアドレスに支払い依頼のメールが届きます。「お支払いページに進む」をクリックします。 ②支払い画面が表示されます。「お支払い」ボタンをクリックします。 ③指定のメールアドレスへお支払い用バーコードのご案内メールが別途送信されます。 メールまたは支払い画面の「今すぐバーコードを表示して支払う」からバーコードを確認します。 ▼メールでのご案内 「お支払いへ進む」ボタンをクリック ④内容確認画面が表示されるので、「バーコードを表示」をクリック ⑤支払い用のバーコードが表示されるので、コンビニのレジで提示し、支払い完了となります。 いかがでしたでしょうか? コンビニ決済の支払いもシステム構築なし、管理画面上の操作のみで簡単に作成・送信できました。 こちらの機能についてはテスト環境でも実際に触ることができるので、一度お試しくださいませ! あわせて読みたいコンビニ決済関連記事 スマホで支払える「コンビニ決済」がリリースされました! コンビニ決済の重要性|その背後にある日本の文化とは

マーケティングチーム

UIコンポーネントのデモページを作成しました

fincode開発チームです! UIコンポーネントの「コーディングを始める」というページを作成したのでそのご紹介です。 https://docs.fincode.jp/payment/ui_component/demo fincodeでは、UIコンポーネントというWebサイトに埋め込めるカード情報入力フォームを提供しています。 詳しくはこちら UIコンポーネントは利用者が自由にカスタマイズできるようになっていて、 文字色や背景、ラベルの内容...などを任意の値に指定できるようにしています。 今回はdocs上に実際にUIコンポーネントのカスタマイズを試してどんなUIになるのか?をインタラクティブに試せるページを作成しました。 1.初期表示 ページを開くとこの画面が表示されます。 2.各パラメータを変更 今回はテキストを変えてみようと思います。 ラベルテキストの各項目を英語にし、プレースホルダーテキストのカード名義人を変更し、「更新」を選択します。 すると... 3.更新後画面 UIコンポーネントが更新され、変更したパラメータ通りの表示になっていますね! また、左に記載されているコードブロックはUIコンポーネントのサンプルコードです。 このページでお好みの文字や色に調整したあと、コードをコピーすればローカルでも利用できます! 今回はdocsに追加したUIコンポーネントの「コーディングを始める」ページの紹介でした。 あわせて読みたい開発者におすすめの記事 fincodeの構築方法~UIコンポーネント編~ エンジニアファーストの決済ソリューション–fincodeの強みとは

開発チーム