WordPressで会員制サイトを作る方法(プラグイン無し・Stripe定額課金対応)

Cocoonテーマカスタマイズ範囲内で作業します。主にコピペで作業できます。StripeのプラグインはDirectStripeを使用します。WordpressやStripe初心者の方にもなるべく分かりやすく説明します。


今回どんなタイトルにするか迷いました。

  • WordPressで会員制サイトを作る方法(コピペでOK)
  • Cocoonでプラグインを使わずに会員制サイトを作る方法
  • Stripe定期購読の会員制サイトを作る方法

どれも正解です。

いきなり作業に入りたい人は2章から読んでください。

会員制サイト概要

完成図

工事中です。

会員制サイトの特徴

上記では触れていませんが、以下のような工夫があります。

  • 会員制サイトのプラグインは一切使用しません
  • ⇒サイトはそんなに重くなりません
  • 記事のカテゴリーで有料/無料を切り替えます
  • ⇒投稿一覧画面でまとめて簡単に有料/無料切り替えができます

  • Stripeの支払いを使います
  • ⇒支払い手順が簡単です。支払いまでの離脱を極力少なくします
  • 有料コンテンツは途中まで無料会員にも見せます。その内容にページの目次が含まれています
  • ⇒無料会員の興味を引き付け課金を促します

【補足】有料設定するとGoogleにクロールされるのは無料会員版のコンテンツです。有料会員しか見えない部分はGoogleにもクロールされないことに注意してください。

現状では以下のことはできません。

  • 定期支払いを複数パターン作る。現状は1パターンのみ
  • 固定ページにも制限をかける
  • WeChatPay、Alipay(支付宝)での支払い

前提知識

本投稿では、

表現を簡単にするのと、長い説明を省くためにWordpress周辺の用語はそのまま使用します。

  • 固定ページを追加
  • プラグインの追加
  • 子テーマのfunctions.php
  • テーマ/子テーマのディレクト

本投稿は、読者の方がこれらの意味が分かっている前提で執筆しています。(その都度、調べて進むのは問題ないです)

WordPressの条件

  • WordPressテーマで「Cocoon」を使っていること
  • ⇒Cocoonでなくても可能ですが多くの手直しが必要です
  • 他の会員制サイトプラグインが導入されていないこと

  • 「Theme my logon」プラグインが導入されていないこと
  • ⇒共存は可能ですが、ソースコードのURL参照箇所を手直しする必要があります
  • 「WP Mail SMTP」プラグインでメール送信ができるようになっていること

  • 一般の投稿は「h2」タグ(いわゆる大見出し)が二つ以上ある構成になっていること
  • カテゴリーで、スラッグ「free」または「limited」のカテゴリーが追加できること。それを元に有料/無料の区別します。
  • 「特定商取引法」のページがあること(Webサイトで物を売る時に必要)

その他の前提条件

  • Stripeの会員になって本人確認が完了していること
  • サイトがHTTPS化されていること。これが無いとStripeの本番環境が使えません
以降の内容は

読んでも読まなくてもどちらもOK

作業したい人は2章へ

外部的な検討内容

usermetaに以下を追加します。

メタデータ名 意味
member_rank 会員ランク(後述)
member_start_timestamp 会員になった日
member_end_timestamp 会員が終わる日
stripe_customer Stripe側のユーザー名(customer)
stripe_subscription Stripe定期購読のID

stripe_customerは、StripeのユーザーとWordpressのユーザーを関連付けるために持っておきます。stripe_subscriptionは定期購読のキャンセル処理で使います。

会員ランクは以下とします。

会員ランク 意味
0 期限切れ
2 30日会員
3 90日会員(自動更新)
9 キャンセル

今日の日付と、会員が終わる日を比較して、過ぎていたら会員ランクを0にします。

あと、ランク3の人には自動更新が付きます。自動更新はキャンセル可能ですが、キャンセルした場合でも、期限が残っているうちはこれまで通り有料会員と同じように扱うのでランク9とします。

Stripeでは支払いなどが発生するとWebhookで通知する機能があるので、それをサーバ側で受信します。

Stripeイベント きっかけ サーバーの処理概要
customer.created 初めて会員になった WordPressのユーザーを作る
customer.subscription.created 定期購読の申し込みがあった 誰が申し込んだのかを覚える
invoice.payment_succeeded 定期購読の支払いが完了した 会員ランク3をセットする
charge.succeeded 普通に支払われた 会員ランク2をセットする
customer.subscription.deleted 定期購読がキャンセルされた 会員ランク9をセットする

プログラムの検討内容

◆◆何を使って有料/無料を識別するか

  1. カテゴリー
  2. 記事に新しくメタデータを追加

⇒記事の一覧画面で↑みたいな感じで有料/無料を切り替えたいので「1.」カテゴリー案を採用

◆◆いつ有料会員のフラグを設定するか

  1. 支払いボタンが押された時
  2. StripeからのWebhook(invoice.payment_succeededまたはcharge.succeeded)を受信した時

⇒Stripe側で支払いが認識されて初めて課金されたと言えるので「2.」採用

◆◆Stripeの支払いを何プラグインでやるか

  1. Direct Stripe
  2. Stripe Payments
  3. Stripe Payments for WordPress – WP Simple Pay

「1.Direct Stripe」採用。無料機能で定期支払に対応しているのがこれしかないです。重いのが難点。環境にもよるけどPageSpeed Insightsテストで-50くらいもっていかれます。後述で対処します。

◆◆会員期限切れの確認をどうやるか

  1. My SQL DBにトリガを定義(定時実行)
  2. WP-Cron(定時実行)
  3. 直書き(即時実行)

CREATE EVENT e_vip_return_03 ON SCHEDULE EVERY 86400 SECOND DO update $users set mrank = 0 where mrank = 3 and datediff(current_timestamp,vip_registered ) > 30;

「1.」だったら↑みたいな感じでトリガを毎日0時実行で定義しておけば、自動で期限切れチェックしてくれます。X Serverでは使えなかったので却下です。AWSならこれでいけます。

「2.」タイムラグが心配なので却下。仕方ないので「3.」直書きすることに。ページを読み込むたびにいちいちチェックします。

送信メール

システムからは3種類のメールが送信されます。メールひな形はfunctions.phpに直書きしているので変更可能です。

◆最初にお金を払った時(ユーザ登録完了)

◆支払い完了

上記は「30日1000円プラン」の例ですが、「90日2400円(自動更新)」の場合でもほぼ同じ内容のメールが送信されます。

自動更新の場合は、更新される度に上記のメールが送信されます。

◆自動更新キャンセル

作業フロー

以下の順番で作業を進めます。

  1. Stripeの設定
  2. 固定ページの追加
  3. 関連プラグインのインストール、設定
  4. カテゴリー追加、有料コンテンツ設定
  5. functions.phpファイルに設定値を埋め込む
  6. functions.phpのアップロード
  7. テスト
  8. 本番移行

「1.」から「5.」までが準備作業です。

「6.」に進んだ段階で、「8.」が終わっていなくても有料/無料設定は適用されます。

準備作業

Stripeの商品登録

まず商品を登録し、その後に料金プランを設定します。

Stripeのダッシュボードを開き、テストモードにしてから、商品をクリックします。

【補足】今はテストモードですが、後で本番モードにして全く同じ作業を行います。

「新規」ボタンをクリックします。(画像では既に商品が登録されています。)

「定期利用する商品」を選択し、商品名を[自サイト名]+有料コンテンツ(自動更新)とします。「完了」ボタンをクリックします。

料金体系の無い商品が作成されます。料金体系の欄に「料金プランがありません」と表示されています。

商品をクリックし、

料金プランを追加します。

ニックネームに「90日有効自動更新」と入力します。

※「3か月」ではないことに注意。理由は後述。

単価を入力し、請求間隔を「カスタム:90日」とします。請求間隔3カ月という内容もありますが、選ばないでください。

サーバ側では常に90日という判定を使っています。3カ月だと合計が90日なのか91日なのか…合わなくなってしまいます。

項目を入力したら「料金プランの追加」ボタンをクリックします。

これで料金プラン付きの商品が追加できました。

名称をクリックして詳細を表示します。

料金プランをクリックします。

この画面に表示されているIDをメモします。

商品名 プラン ID
[自サイト名]有料コンテンツ(自動更新) 90日1回課金 ▲▲▲※①

StripeのWebhook登録

WebhookとはStripe側の処理結果を自サーバで受け取るための仕組みです。

テストモードになっている事を確認して「開発者」→「Webhook」をクリックします。

【補足】今はテストモードですが、後で本番モードにして全く同じ作業を行います。

「エンドポイントを追加」をクリックします。(図は作業後の状態なので、既に設定が表示されています)

以下の設定を入れて「Add endpoint」をクリックします。

  • Endpoint URL・・・https://■■■■■/wp-admin/admin-ajax.php?action=stripeHook
  • (■は自サイトのドメイン名です)
  • Version・・・Your Current versionを選択

Event to Sendは5つ選択します。

  • charge.succeeded
  • customer.created
  • customer.subscription.created
  • invoice.payment_succeeded
  • customer.subscription.deleted

Stripe認証キーの取得

各キーの値をメモしておきます。

まずは、Webhook設定画面の下に表示されている「署名シークレット」です。

次に「開発者」→「APIキー」とクリックした画面に表示されている「公開可能キー」と「シークレットキー」です。

Stripeキー
公開可能キー ▲▲▲※②
シークレットキー ▲▲▲※③
Webhook署名シークレット ▲▲▲※④

【補足】今はテストモードですが、後で本番モードにして全く同じ作業を行います。

Stripeライブラリのアップロード

以下のリンクにアクセスします。

PHP library for the Stripe API. . Contribute to stripe/stripe-php development by creating an account on GitHub.

画面右の「Clone or download」ボタンをクリックし、「Download ZIP」をクリックします。

ダウンロードしたファイルを解凍し、サーバーのCocoon子テーマのトップディレクトリにフォルダごとアップロードします。

X Serverの場合は、

/■ドメイン名■/public_html/wp-content/themes/cocoon-child-master

です。

Stripe関係の準備はここまでです。

固定ページの追加

以下の固定ページを追加します。

固定ページ名 スラッグ 記述内容
有料会員 register (後述)
会員情報 memberinfo [show_member_info99]
支払いエラー payment-error この画面が表示された場合は、お手数ですがサイト管理者までご連絡ください。
自動更新キャンセル stripe-subscription-cancel [show_cancel_subscription99]

「記述内容」欄に書かれている内容をそのまま※コピペしてください。有料会員ページは後で設定します。

※ショートコードをここに書くと反映されてしまうので99を追加していまます。コピペは以下のように読み替えてください。

  • show_member_info99 ⇒ show_member_info
  • show_cancel_subscription99 ⇒ show_cancel_subscription

Direct Stripeプラグインのインストールと設定

プラグインをインストールして有効にします。

プラグインをインストールすると左側のメニューにSirect Stripeの項目が表示されます。セッティングをクリックします。

「GLOBAL SETTINGS」タブが表示されています。

以下の設定を入れます。

  • Use test keys/mode・・・ONにする
  • Test Publishable API key・・・先にメモしたStripe公開可能キー※②
  • Test Secret API key・・・先にメモしたStripeシークレットキー※③
  • Currency・・・JPY

「BUTTONS SETTINGS」タブをクリックします。これから支払いボタンを作成します。

  1. 30日1000円プラン
  2. 90日2400円(自動更新)プラン

まずは前者のボタンです。

「st30day1time」と入力して「CREATE BUTTON」をクリックします。

以下の設定を入れます。

  • Name・・・30日1000円プラン
  • Type・・・Payment
  • Amount・・・10
  • Add a CSS ID to the button・・・st30day1time
  • Label・・・30日1000円プラン
  • Panel Label・・・支払う
  • Description・・・[自サイト名]有料会員
  • Currency・・・JPY
  • Success url・・・/login
  • Error url・・・/payment-error

続いて2個目のボタンです。

「st90day_auto」と入力して「CREATE BUTTON」をクリックします。

以下の設定を入れます。

  • Name・・・90日2400円プラン(自動更新)
  • Type・・・Subscription
  • Plan ID・・・先にメモした商品ID※①
  • Add a CSS ID to the button・・・st90day-auto
  • Label・・・90日2400円プラン(自動更新)
  • Panel Label・・・支払う
  • Description・・・[自サイト名]有料会員
  • Currency・・・JPY
  • Success url・・・/login
  • Error url・・・/payment-error

Direct Stripeの設定は以上です。

Plugin Load Filterプラグインのインストールと設定

Direct Stripeプラグインをインストールすると、サイトが超絶重くなります。このプラグインの機能は支払いページでしか必要ないので、そこだけで使うように設定します。

プラグインをインストールして有効にします。プラグインをインストールすると左側のメニュー「プラグイン」の中に「Plugin Load Filter」の項目が表示されます。それをクリックして設定画面を表示します。

「フィルター登録」タブにDirect Stripeのエントリーがあるので、

図のようにコンセントのアイコンを「Page Type フィルタ」の一番右(Page Type)にします。

画面一番下の「フィルター登録」ボタンをクリックし、設定を保存します。

続いて「Post Type フィルタ有効プラグイン選択」タブをクリックして、

図のようにPageの下にあるコンセントのアイコンをクリックします。

画面一番下の「有効かプラグイン登録」ボタンをクリックし、設定を保存します。

支払いボタンの設置

固定ページ「有料会員」を編集します。

「有料会員になるにはどちらかのメニューを選択してください。」といった感じで一言記述し、「stripe Add button」ボタンをクリックします。

リストボックスの中に先にDirect Stripeで作成したボタン名称があります。いずれかを選択して「Insert Button」ボタンをクリックします。(Direct Stripeで2個ボタンを作成したので、リストボックスには2エントリーあるはず)

[xxxdirect-stripe value=”ds-1553497072072″]といった感じでショートコードが展開されます。もう一つのボタンも挿入し、ショートコードが二つ記述されている状態にします。

必要であれば、以降に続けて、本文に有料会員の説明を記載します。

ボタンレイアウトの変更

固定ページ「有料会員」のカスタムCSSの欄に以下のコードをコピペします。

.stripe-button-ds {
    display: inline-block;
    width: 200px;
    height: 70px;
    text-align: left;
    background-color: #000;
    font-size: 16px;
    color: #FFF;
    text-decoration: none;
    font-weight: bold;
    padding: 8px 16px 8px 32px;
    border-radius: 4px;
    position: relative;
}
.stripe-button-ds:before {
    font-family: "FontAwesome";
    content: "\f105";
    position: absolute;
    left: 16px;
    top: 50%;
    margin-top: -8px;
}
.stripe-button-ds:hover {
    opacity: 0.8;
}

Direct Stripeプラグイン読み込みの設定

右側に「Page Filter」プラグインの設定があります。

「使用する」を選択しDesctop/Mobileそれぞれにチェックします。

全て設定後「更新」ボタンをクリックし、固定ページ「有料会員」を保存します。

有料/無料カテゴリーの追加

今回の仕組みでは、有料/無料の判定をカテゴリーで行います。

  1. カテゴリー「有料」に属している投稿は有料コンテンツ。それ以外は全て無料
  2. カテゴリー「無料」に属している投稿は無料。それ以外は全て有料コンテンツ

「1.」「2.」どちらかのパターンしかできません。

「1.」の方法が良い人は、カテゴリー追加でスラッグ「limited」を追加します。

「2.」の方法が良い人は、カテゴリー追加でスラッグ「free」を追加します。

【補足】両方同時はできません。

【補足】この段階では、まだ記事に制限はかかりません。

【補足】全ての作業が終了するまで、ひとまず一つの記事だけに有料/無料設定を適用すると良いです。

有料/無料コンテンツの登録

先の選択で「1.」の人は、既存の記事、またはこれから作成する記事の中で、有料にしたいものをカテゴリー「limited」に含めます。カテゴリーは複数に所属しても問題ないので、既に別のカテゴリーが設定されている記事に関しては、複数のカテゴリーに含めるようにします。

同様に、「2.」の人は無料にしたい記事をカテゴリー「free」に含めます。

【補足】どちらの場合でも、この段階ではまだ記事に制限はかかりません。

会員制サイトの処理をfunctions.phpに記述

ここは後述のソースコードをコピペでOKです。

自サーバのCocoon子テーマのfunctions.phpに会員制サイトの処理を追加します。

  • これまでfunctions.phpを編集した事が無い人・・・自分のfunctions.phpを後述のソースコードで置き換えればOK
  • functions.phpに既に処理が書いてある人・・・自分のfunctions.phpの末尾に後述のソースコードを追記

functions.phpのソースコードは後述します。

後述のソースコードの一部を自分の環境に合わせます。編集内容は以下です。

  • ★★自分の名前★★となっている部分・・・自分の名前を記述
  • ★★Stripeシークレットキー※③★★・・・先にメモした※③Stripeシークレットキーを記述
  • ★★Webhook署名シークレット※④★★・・・先にメモした※④Webhook署名シークレットを記述
  • ★★自サイトのドメイン名(https://は含めない)★★・・・自サイトのドメイン名を記述

また、有料/無料設定の方式で、

  1. カテゴリー「有料」に属している投稿は有料コンテンツ。それ以外は全て無料
  2. カテゴリー「無料」に属している投稿は無料。それ以外は全て有料コンテンツ

「2.」の方が良い人は、

「★★カテゴリー「無料」以外なら制限をかける」となっている行のPHPコメント化を解除し、「//★★カテゴリー「有料」なら制限をかける」となっている行をPHPコメント化します。

「1.」で良い人はそのままです。

今動作している子テーマのfunctions.phpをバックアップする

さらにfunctions.phpをいつでも元の状態に戻せるようにしておきます。

ここまでで

準備は完了です

functions.phpの動作確認

先に編集したfunctions.phpをサーバーにアップロードし、自サイトのTOPページ、いずれかの固定ページ、いずれかの投稿ページがこれまで通り表示されることを確認します。

【補足】もし正しく表示されない場合は作業を中止して、バックアップしてあるfunctions.phpをリストアしてください。

テスト、会員制サイトの動作確認

まずはStripeの設定がテストモードの状態で会員制サイトの動作確認を行います。テストモードの時は実際の支払いは発生しません。

【補足】本番環境に移行した後に、まったく同じテストを行います。

有料コンテンツの表示確認

WordPressをログアウトし、有料設定されている投稿を表示します。(無料以外有料設定の人は、無料以外の投稿を表示します)

投稿が二つ目の大見出しより前(記事にh2タグが複数あるとして、2つめのh2タグ直前まで)まで表示されていて、それ以降は上記のように表示されていることを確認します。

テスト会員登録確認

先のリンクの「会員登録」をクリックし会員登録画面を表示します。支払いボタンをクリックし、クレジットカードの入力画面を表示させます。

以下の通りにテストデータを入力します。

  • メールアドレス・・・任意。使えるものなら何でもOK
  • カード番号・・・4242 4242 4242 4242(Stripeのテスト番号)
  • MM/YY・・・本日から1か月後
  • CVC・・・111

入力したメールアドレス宛にメールが届いています。そこに記載されている内容で自サイトにログインできることを確認します。

また、ログイン後に有料コンテンツにアクセスし、内容が全て表示されていることを確認します。

ログインメニューの設置

以下の二つのファイルの末尾に「show_login_menu();」と記述します。

  • 子テーマのルートディレクトリ/tmp-user/body-top-insert.php
  • 子テーマのルートディレクトリ/tmp-user/amp-body-top-insert.php

例えばX Serverの場合以下のファイルの事です。

/■■自ドメイン名■■/public_html/wp-content/themes/cocoon-child-master/tmp-user/body-top-insert.php

WordPressにログインしていない状態で自サイトを表示し、

画面上部にログインメニュー↑が表示されていることを確認します。

有効期限と自動更新の確認

登録したユーザーでログインして期限が正しく表示されていることを確認します。

他に以下のパターンを確認します。

  • 期限が過ぎた人が「期限切れ」になること
  • 自動更新の人は、期限が過ぎた後に自動で期限が延長(再課金)されること
  • 自動更新の人に「自動更新キャンセル」のリンクがあること
  • 自動更新をキャンセルした人は会員種別が「自動更新キャンセル」になって、それでも期限内は有料コンテンツが参照できること。また自動更新キャンセルのメールが送信されていること。
  • 期限を切れた人が再び課金を行って、再び有料会員になれること。その後、有料コンテンツが参照できること。

Stripeダッシュボードからの課金確認

「支払い」をクリックします。

課金した人のデータが表示されていることを確認します。

※テスト課金の場合は、ここには表示されるのみで、実際の振り込みは一切行われません。

本番環境へ変更(そして本番動作確認)

Stripe本番商品の登録

Stripeを本番環境にし、「準備作業-Stripeの商品登録」と全く同じ作業をします。

商品名(本番) プラン ID
[自サイト名]有料コンテンツ(自動更新) 90日1回課金 ▲▲▲※⑪

Stripe本番キーの取得

同じく、Stripeの本番環境で、「準備作業-StripeのWebhook登録」と全く同じ作業をします。その後「準備作業-Stripe認証キーの取得」と全く同じ作業をします。

Stripeキー(本番)
公開可能キー ▲▲▲※⑫
シークレットキー ▲▲▲※⑬
Webhook署名シークレット ▲▲▲※⑭

DirectStripe本番設定

DirectStripeの「GLOBAL SETTINGS」画面で「Use test keys / mode」のスイッチをOFFにします。

以下を入力します。

  • Live Publishable API key・・・先にメモしたStripe本番環境の公開可能キー※⑫
  • Live Secret API key・・・先にメモしたStripe本番環境のシークレットキー※⑬

DirectStripeの「BUTTON SETTINGS」画面で「st90day_auto」ボタン設定を表示します。以下の部分だけ設定変更します。

  • Plan ID・・・先にメモしたStripe本番環境の商品プランID※⑩
  • (上記以外は変更なし)

functions.phpに本番キーを記述&サーバー転送

以下の部分を本番環境用に合わせます。

  • ★★Stripeシークレットキー※③★★・・・先にメモしたStripe本番環境のシークレットキー※⑬
  • ★★Webhook署名シークレット※④★★・・・先にメモしたStripe本番環境のWebhook署名シークレット※⑬

修正したらサーバーにアップロードします。

本番課金テスト

実際に存在するクレジットカードで先に記述した「テスト、会員制サイトの動作確認」と全く同じ作業を行います。

ただし「ログインメニューの設置」だけは、テスト/本番は関係ないので、もう作業しなくてよいです。

作業は以上です。
お疲れさまでした。

ソースコード(コピペ用)

ダウンロードファイル

工事中です。