Stripeで支払い方法(カード情報)の変更 with Laravel

Stripe VueJS PHP

意図

顧客のクレジットカード情報を更新する機能を作りたい。

  • クレジットカードの有効期限切れ
  • 謝って入力したケース

また、バックエンドはLaravelだが、 サーバレス(node.js)で構築してみたいのでエッセンス的なところを身に付けておきたい。

環境

カードのテスト

テストできるカードは、Stripe テスト方法に記載されています。めちゃめちゃ親切なドキュメントですね。感動しました。

  • VISA: 4242424242424242
  • Master Card: 5555555555554444

を使いまわそうかなと。

エラーのテストや不正請求のテストも実施することができるので、便利です。

お支払い方法(カード情報)の変更

詳細は、Updating The Default Payment Methodに書いてあります。

Lereval側(StripeController)

user()はLaravelのAPIトークンを見て、Userを取得しています。

// 支払いの意図を作成し、支払いを捕捉できるようにします
public function getSetupIntent( Request $request )
{
    return $request->user()->createSetupIntent();
}
// 支払い方法の更新
public function updatePaymentMethod(Request $request) {
    $paymentMethod = $request->input('paymentMethod');
    $request->user()->updateDefaultPaymentMethod($paymentMethod); // ココで更新
    return $this->status(); // ステータスを返しています
}

Vue.js側

export default {
  data () {
    return {
      card: null,
      stripe: [],
      stripeAPIToken: YOUR_STRIPE_PUBLIC_KEY, // StripeのPublic Keyを入れる
      intentToken: ''
    }
  },

  mounted () {
    // eslint-disable-next-line no-undef
    this.stripe = Stripe(this.stripeAPIToken)
    const elements = this.stripe.elements()
    this.card = elements.create('card', { options }) // 任意のオプション
    this.card.mount('#card-element')
    this.loadIntent() // ここでgetSetupIntentを呼び出し
  },

  methods: {
    async submit () {
      // 決済情報の登録
      await this.stripe.confirmCardSetup(
        this.intentToken.client_secret, {
          payment_method: {
            card: this.card,
            billing_details: {}
          }
        }
      ).then(result => {
          this.updatePaymentMethod(result.setupIntent.payment_method)
          this.card.clear()
        }
      })
    },

    loadIntent () {
      this.axios.get('/get-setup-intent')
        .then(res => {
          this.intentToken = res.data
        })
    },

    /**
     * カード情報の更新
     * @param {object} paymentMethod 支払い情報
     * @return {void}
     */
    async updatePaymentMethod (paymentMethod) {
      const data = {
        paymentMethod: paymentMethod
      }
      await this.axios.post('/update-payment-method', data)
    }
  }
}

mountedgetSetupIntentを呼び出しているので、処理を実行したあとは、コンポーネントを破棄してあげる。

また、apiのエンドポイントは、スパイナルケース(ケバブケース)が良いとのこと。メソッド名もDBの更新であれば、 changeよりもupdateを使用したい。

  • 変更結果が永続化されるならupdate
  • 変更結果が一時的なものならchange

お支払い方法(カード情報)の作成

先ほどは更新だけでしたが、お支払い方法(カード情報)のみをユーザーに登録してもらいたいケースもあると思います。カード情報の登録は、顧客を作る必要があります。
stripe_idを確認し、ある場合は支払い方法の更新。ない場合は、顧客を作成した後に支払い方法を更新します。(stripe_idは、Userテーブルのカラムです。)

// お支払い情報(カード情報)の作成/更新
public function savePaymentMethod(Request $request) {
    $user = $request->user();
    $paymentMethod = $request->input('paymentMethod');
    if ($user->stripe_id) {
        $user->updateDefaultPaymentMethod($paymentMethod);
    } else {
        // カード情報作成の場合、顧客を作る
        $user->email = decrypt($user->email);
        $user->createAsStripeCustomer();
        $user->updateDefaultPaymentMethod($paymentMethod);
    }
    return $this->status(); // 独自で作った
}

また、サブスクリプションの作成の際に既に支払い情報がある場合は、add()を使用します。

$user->newSubscription('default', $planId)->add();

お支払い方法(カード情報)の削除

お支払い情報の削除は、Deleting Payment Methodsに書いてあります。

資料