Chapter 08

決済システムの比較と導入

株式会社var(ヴァー)
株式会社var(ヴァー)
2021.09.12に更新

こちらのチャプターでは、決済システムの導入に関する背景を解説します。

学生起業家や個人起業家が自らのサービスをリリースする際に通る部分だと思いますのでご参考になることがあれば幸いです。

決済システムといば、PayPal or Stripe ということになるかと思います。
他にも色々あるとは思いますが、決済関係にそんなに詳しくない人がほとんどだと思うので我々はこの2択で最初から考えておりました。

結論としては、圧倒的に Stripe の勝ちでした。
理由は、美しさすら感じるオブジェクトの構成と素晴らしく読みやすいドキュメントを備えているためです。
その他、スマホ閲覧用のアプリ等もStripeの方が充実しており、非常に利用しやすいと判断しました。

ただ、Stripeは返金時にも手数料が引かれてしまうので注意が必要です。
Envaderは、利用規約等にも明記していますが、返金を受け付けておりません。そのため、今回は特に問題はなかったのですが、大きな金額を決済したり、返金保証があるサービス等では返金の規約等をしっかり盛り込む必要があると感じました。

Stripeの実装に関しては、比較的簡単でした。
公式ドキュメントにご丁寧に書いてありますし、Go言語用のライブラリも豊富にあったため、1日程度で実装は完了します。

以下に実装例を示しますが、ドキュメントのほぼコピペです。

params := &stripe.CheckoutSessionParams{
	SuccessURL: &successURL,
	CancelURL:  &cancelURL,
	PaymentMethodTypes: stripe.StringSlice([]string{
		"card",
	}),
	Mode: stripe.String(string(stripe.CheckoutSessionModeSubscription)),
	LineItems: []*stripe.CheckoutSessionLineItemParams{
		&stripe.CheckoutSessionLineItemParams{
			Price: stripe.String(priceID),
			Quantity: stripe.Int64(1),
		},
	},
}

s, _ := session.New(params)

Stripeを利用する時に困ったことは、概念が多すぎて自分たちが欲しいStripeが所有するデータ(price_id, cusotemer_idなど)になかなかありつけないということでした。

その都度、複数のAPIを数珠綱ぎにして情報をとってくるのは非効率だと判断し、Stripe側のデータも自分たちのデータベースで保持することを考えました。

Envaderでは、Stripeにおけるcustomer_idやprice_id等は、自前のデータベースにも保存しています。どのデータを自前のデータベースにも保存するかというのは一考の価値があるかと思います。

ちょっとしたTipsとして、よく利用したのは、stripe apiに組み込まれているmeta変数という領域です。自分たちの好きなデータをmetaに保存できるため、StripeからのAPIレスポンスをカスタマイズすることができました。

例えば、checkout session作成のAPIのレスポンスにprice_idが欲しいと言った場合は、リクエストの際にmetaに仕込んであげるとレスポンスにもprice_idが入っているという感じになります。

実装例はこちらです。

params := &stripe.CheckoutSessionParams{
	SuccessURL: &successURL,
	CancelURL:  &cancelURL,
	PaymentMethodTypes: stripe.StringSlice([]string{
		"card",
	}),
	CustomerEmail: &user.Email,
	Mode:        stripe.String(string(stripe.CheckoutSessionModePayment)),
	LineItems: []*stripe.CheckoutSessionLineItemParams{
		&stripe.CheckoutSessionLineItemParams{
			Price:    stripe.String(priceID),
			Quantity: stripe.Int64(1),
		},
	},
}
// ここに1行足すだけ
params.AddMetadata("price_id", priceID)

s, _ := session.New(params)

今回は、Checkout機能(以下のようなやつ)を利用しました。

ここで問題が生じました。

  • Stripeからのcallbackは、セッションIDを持たせた上でのリダイレクトである。
    • つまり、GraphQLに対して直接クエリを出せない
    • 別のエンドポイント(/queryでなく/callback)を作ったとしてもSPAが反応できない。

よって、ややこしい処理をすることになりました。
簡単に図に示して終わります。