2026年8月29日

2026年8月29日

MemberPressのエラーを解決する方法

はじめに

MemberPressで会員登録フォームを送信しても「Registration failed」エラーが出てアカウントが作成されない・有料会員向けに設定したコンテンツ保護ルールが機能せず非会員でも閲覧できてしまう・Stripeで決済すると「Card declined」エラーが出るが管理画面では決済完了と表示される・無料トライアル期間終了後に自動課金されないといった問題は、決済設定・アクセスルール・メール設定が原因です。

症状・原因

  • 会員登録時に「There was an error processing your payment」と表示される
  • 有料会員限定ページに設定したのに非ログインユーザーがコンテンツを閲覧できる
  • Stripeの決済画面でエラーなく進んでもWordPress側のトランザクションが「Pending」のまま
  • 無料トライアル期間が終わっても会員のステータスが「Active」のまま

解決手順

ステップ1:MemberPressの状態を確認する

# MemberPressの設定確認
wp eval "
if (defined('MEMBERPRESS_VERSION')) {
    echo 'MemberPress version: ' . MEMBERPRESS_VERSION . PHP_EOL;
}

// メンバーシップ一覧を確認
\$memberships = MeprProduct::get_all();
echo 'Total memberships: ' . count(\$memberships) . PHP_EOL;

foreach (\$memberships as \$membership) {
    printf('  #%d: %s | Price: %s | Period: %s %s | Trial: %s' . PHP_EOL,
        \$membership->ID,
        \$membership->post_title,
        \$membership->price,
        \$membership->period,
        \$membership->period_type,
        \$membership->trial ? 'yes (' . \$membership->trial_days . ' days)' : 'no'
    );
}

// アクティブなトランザクションを確認
global \$wpdb;
\$transactions = \$wpdb->get_results(
    \"SELECT t.id, t.status, t.amount, t.created_at, u.user_email
     FROM {\$wpdb->prefix}mepr_transactions t
     JOIN {\$wpdb->users} u ON t.user_id = u.ID
     WHERE t.status IN ('complete', 'pending')
     ORDER BY t.created_at DESC LIMIT 10\",
    ARRAY_A
);
echo 'Recent transactions: ' . count(\$transactions) . PHP_EOL;
foreach (\$transactions as \$tx) {
    printf('  #%d: %s | %s | %s | %s' . PHP_EOL,
        \$tx['id'], \$tx['status'], \$tx['amount'], \$tx['user_email'], \$tx['created_at']
    );
}
"

ステップ2:トランザクション処理をカスタマイズする

// functions.php: MemberPressトランザクション処理

// ① 決済完了時にカスタム処理を実行
add_action('mepr_event_transaction_completed', function(MeprEvent $event): void {
    $transaction = $event->get_data();
    $user        = $transaction->user();
    $membership  = $transaction->product();

    // 決済完了時にユーザーメタを更新
    update_user_meta($user->ID, '_mepr_joined_at', current_time('mysql'));
    update_user_meta($user->ID, '_mepr_membership', $membership->post_title);

    // カスタムウェルカムメールを送信
    wp_mail(
        $user->user_email,
        sprintf('[%s] 会員登録が完了しました', get_bloginfo('name')),
        sprintf("こんにちは %s さん、\n\n「%s」プランへのご登録ありがとうございます。\n\nマイページ: %s",
            $user->display_name,
            $membership->post_title,
            mepr_account_url()
        )
    );

    error_log(sprintf('[MeprP] Transaction #%d completed for user #%d (%s)',
        $transaction->id, $user->ID, $user->user_email));
});

// ② サブスクリプション更新成功時の処理
add_action('mepr_event_subscription_resumed', function(MeprEvent $event): void {
    $subscription = $event->get_data();
    $user         = $subscription->user();
    update_user_meta($user->ID, '_mepr_last_renewal', current_time('mysql'));
});

// ③ 決済失敗時の処理
add_action('mepr_event_transaction_failed', function(MeprEvent $event): void {
    $transaction = $event->get_data();
    $user        = $transaction->user();

    error_log(sprintf('[MeprP] Transaction failed for user #%d: %s',
        $user->ID, $user->user_email));

    // 管理者に通知
    wp_mail(
        get_option('admin_email'),
        '[MemberPress] 決済失敗の通知',
        sprintf('ユーザー: %s (%s) の決済が失敗しました。', $user->display_name, $user->user_email)
    );
});

ステップ3:コンテンツ保護ルールを確認する

// functions.php: アクセスルール管理

// ① 現在のユーザーがコンテンツにアクセスできるか確認
function check_memberpress_access(int $post_id, int $user_id = 0): bool {
    if (!function_exists('mepr_post_rules_to_string')) return true;

    $user_id = $user_id ?: get_current_user_id();
    if (!$user_id) return false;

    $mepr_user = new MeprUser($user_id);
    return $mepr_user->can_access_post($post_id);
}

// ② コンテンツ保護ルールのデバッグ
add_action('mepr_unauthorized_content', function(WP_Post $post, int $user_id): void {
    error_log(sprintf('[MeprP] Access denied: post #%d for user #%d', $post->ID, $user_id));

    // アクセスルールを確認
    $rules = MeprRule::get_rules_for_post($post->ID);
    foreach ($rules as $rule) {
        error_log(sprintf('[MeprP] Rule #%d: %s requires membership #%d',
            $rule->ID, $rule->mepr_type, $rule->mepr_authorized_types_association ?? 0));
    }
}, 10, 2);

// ③ 特定の投稿タイプをMeprアクセスチェックから除外
add_filter('mepr_pre_run_rule_content', function(bool $run, WP_Post $post): bool {
    // カスタム投稿タイプ「announcement」は常に表示
    if ($post->post_type === 'announcement') {
        return false;
    }
    return $run;
}, 10, 2);

ステップ4:Webhook設定を確認する

# StripeのWebhook設定確認
wp eval "
// MeprPの決済ゲートウェイ設定を確認
\$gateways = MeprOptions::fetch()->gateways;
echo 'Payment gateways: ' . count(\$gateways) . PHP_EOL;

foreach (\$gateways as \$gateway) {
    printf('  %s: %s | Test mode: %s' . PHP_EOL,
        \$gateway->name,
        get_class(\$gateway),
        (\$gateway->test_mode ?? false) ? 'yes' : 'no'
    );
}

// 保留中のトランザクションを確認
global \$wpdb;
\$pending = \$wpdb->get_results(
    \"SELECT id, user_id, amount, gateway, created_at
     FROM {\$wpdb->prefix}mepr_transactions
     WHERE status = 'pending'
     AND created_at < DATE_SUB(NOW(), INTERVAL 24 HOUR)
     ORDER BY created_at DESC LIMIT 10\"
);
echo 'Stuck pending transactions (>24h): ' . count(\$pending) . PHP_EOL;
foreach (\$pending as \$tx) {
    printf('  #%d: user=%d, amount=%s, gw=%s, at=%s' . PHP_EOL,
        \$tx->id, \$tx->user_id, \$tx->amount, \$tx->gateway, \$tx->created_at
    );
}
"

ステップ5:サブスクリプションの有効期限を管理する

// functions.php: サブスクリプション管理

// ① 期限切れ会員のアクセスを即座に取り消し
add_action('mepr_event_subscription_expired', function(MeprEvent $event): void {
    $subscription = $event->get_data();
    $user         = $subscription->user();

    // 会員ロールを削除してSubscriberに戻す
    $wp_user = new WP_User($user->ID);
    $wp_user->set_role('subscriber');

    // アクセス期限メタを更新
    update_user_meta($user->ID, '_mepr_expired_at', current_time('mysql'));

    error_log(sprintf('[MeprP] Subscription expired for user #%d', $user->ID));
});

// ② 期限切れ前7日に更新リマインダーを送信
add_action('mepr_event_subscription_reminder', function(MeprEvent $event): void {
    $subscription = $event->get_data();
    $user         = $subscription->user();
    $membership   = $subscription->product();

    $expiry = new DateTime($subscription->expires_at);
    $now    = new DateTime();
    $days   = $now->diff($expiry)->days;

    wp_mail(
        $user->user_email,
        sprintf('[%s] 会員期限まで%d日です', get_bloginfo('name'), $days),
        sprintf("こんにちは %s さん、\n\n「%s」プランの有効期限まで残り%d日です。\n\n更新はこちら: %s",
            $user->display_name,
            $membership->post_title,
            $days,
            mepr_account_url()
        )
    );
});

// ③ トライアル期間終了時の処理
add_action('mepr_event_transaction_expired', function(MeprEvent $event): void {
    $transaction = $event->get_data();
    if (!$transaction->is_trial_txn()) return;

    $user = $transaction->user();
    error_log(sprintf('[MeprP] Trial expired for user #%d', $user->ID));
});

注意事項

  • MemberPressのStripe連携でWebhookが機能しない場合は、StripeダッシュボードのWebhookエンドポイントURLがhttps://example.com/?mepr-listener=stripeの形式で正しく設定されているか確認してください。SSL証明書のエラーがあるとWebhookが届きません
  • コンテンツ保護ルールが機能しない場合は「MemberPress → 設定 → 詳細」の「Force SSL」オプションを確認してください。HTTPとHTTPSが混在している場合にルールが正しく適用されないことがあります
  • テストモードと本番モードでAPIキーが混在しないよう注意してください。Stripeのテストキー(sk_test_)で本番決済しようとするとエラーになります

まとめ

MemberPress修復は①mepr_transactionsテーブルでトランザクション状態・MeprProduct::get_all()でメンバーシップ設定を確認、②mepr_event_transaction_completedフックで決済完了時のメタ更新・ウェルカムメール送信・mepr_event_transaction_failedで管理者通知、③MeprRule::get_rules_for_post()でアクセスルール確認・mepr_unauthorized_contentフックでデバッグログ・mepr_pre_run_rule_contentで特定投稿タイプを除外、④ゲートウェイ設定確認・24時間以上Pendingのトランザクション特定、⑤mepr_event_subscription_expiredで期限切れ時にロール変更・mepr_event_subscription_reminderで更新リマインダーメールを送信する手順で解決します。

お気軽にご相談ください

お見積りへ お問い合わせへ