会員グループ管理プラグインとStripeを利用して EC-CUBE4 で有料会員を管理する方法

会員グループ管理プラグインとStripeのを利用して EC-CUBE4 で有料会員を管理する方法です。

はじめに

Stripeで作成した「支払いのリンク」経由で支払いしたら、予め用意した会員グループ(今回はプレミアムプラン)が会員に付与されて継続して課金される仕組みを用意しています。ただしプレミアムプランを解約する処理は用意していません。

ご注意

「支払いのリンク」経由で支払いをするので、EC-CUBEにすでに登録されているメールアドレスかどうかのチェックをしていません。

同じ会員が何度もプレミアムプランに加入してしまう可能性がございます。

本番運用するときはStripe Elementsを利用してチェックアウトフローを構築することを強くおすすめします。

会員グループ管理プラグイン for EC-CUBE4をインストール

会員グループ管理プラグイン for EC-CUBE4をインストールして会員グループを作成してください。

会員グループ名はプレミアムプランとしてください。

Stripeエンドポイント for EC-CUBE4をインストール

Stripeエンドポイント for EC-CUBE4プラグインをREADMEに記載されている通りインストールしてください。

Stripeの「支払いのリンク」で継続支払い商品を作成

Stripeの「支払いのリンク」で継続支払いの商品を作成してください。

StripeのWebhookにエンドポイントを登録

Stripeの管理画面でWebhookに Stripeエンドポイント for EC-CUBE4 で構築されたエンドポイントを登録してください。

エンドポイントURLは以下を登録してください。

https://my-domain/stripe/webhook/endpoint

Webhookのイベントタイプは以下を登録してください。

invoice.payment_failed
invoice.paid
checkout.session.completed

Webhookの署名シークレットを.envに設定

以下のようにWebhookの署名シークレットを.envに設定してください。

STRIPE_SIGNING_SECRET=whsec_t6KFvU8...

支払いが成功した場合は会員グループを付与する

以下のように、支払いが成功した場合は会員グループを付与して、支払いに問題があった場合は会員グループを解除しています。

<?php

namespace Customize\EventListener;


use Doctrine\ORM\EntityManagerInterface;
use Eccube\Entity\Customer;
use Plugin\CustomerGroup\Entity\Group;
use Plugin\StripeEndpoint\Event\StripeEvent;
use Stripe\Checkout\Session;
use Stripe\Event;
use Stripe\Invoice;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class StripeEventListener implements EventSubscriberInterface
{
    /**
     * @var EntityManagerInterface
     */
    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public static function getSubscribedEvents()
    {
        return [
            Event::CHECKOUT_SESSION_COMPLETED => ['onCheckoutSessionCompleted'],
            Event::INVOICE_PAID => ['onInvoicePaid'],
            Event::INVOICE_PAYMENT_FAILED => ['onInvoicePaymentFailed']
        ];
    }

    /**
     * 顧客が「支払う」または「登録」ボタンをクリックしたとき
     *
     * @param StripeEvent $event
     */
    public function onCheckoutSessionCompleted(StripeEvent $event)
    {
        /** @var Session $session */
        $session = $event->getResource();

        /** @var Customer $customer */
        $customer = $this->entityManager->getRepository(Customer::class)->findOneBy([
            'email' => $session->customer_details->email
        ]);

        $customer->setStripeCustomerId($session->customer);
        $this->entityManager->persist($customer);
        $this->entityManager->flush();
    }

    /**
     * 支払いが成功した場合
     *
     * @param StripeEvent $event
     */
    public function onInvoicePaid(StripeEvent $event)
    {
        /** @var Invoice $invoice */
        $invoice = $event->getResource();

        /** @var Customer $customer */
        $customer = $this->entityManager->getRepository(Customer::class)->findOneBy([
            'stripe_customer_id' => $invoice->customer
        ]);

        if (false === $customer->hasGroups()) {
            // プレミアムプランを会員に付与
            $group = $this->entityManager->find(Group::class, 1);
            $customer->addGroup($group);
            $this->entityManager->persist($customer);
            $this->entityManager->flush();
        }
    }

    /**
     * 顧客の支払い方法に問題があった場合
     *
     * @param StripeEvent $event
     */
    public function onInvoicePaymentFailed(StripeEvent $event)
    {
        /** @var Invoice $invoice */
        $invoice = $event->getResource();

        /** @var Customer $customer */
        $customer = $this->entityManager->getRepository(Customer::class)->findOneBy([
            'stripe_customer_id' => $invoice->customer
        ]);

        $customer->getGroups()->clear();
        $customer->setStripeCustomerId(null);
        $this->entityManager->persist($customer);
        $this->entityManager->flush();
    }
}

マイページに「支払いのリンク」を設置

Stripeで作成した「支払いのリンク」をマイページのどこかに設置してください。有料会員になると解約リンクに切り替える処理は独自でご用意ください。

有料会員かどうかは会員テーブルにStripe会員IDが登録されているかどうかで判定できる思います。

お気軽にコメントをどうぞ