【初心者向け】Pythonでサブスク決済を実装する方法|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とは 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)

