質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Stripe

Stripeとは、米国のオンライン決済システム提供企業、及び同社が提供する決裁システムを指します。Webサイトやモバイルアプリにコードを組み込むことでクレジットカードなどの決済サービスが簡潔に追加できます。

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

CORS

CORSとはCross-Origin Resource Sharingの頭文字をとったもので、ブラウザがオリジン以外のサーバからデータを取得するシステムのことです。

Q&A

解決済

1回答

2527閲覧

【Nuxt.js/Laravel】CORSエラーについて

RyoS_

総合スコア4

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Stripe

Stripeとは、米国のオンライン決済システム提供企業、及び同社が提供する決裁システムを指します。Webサイトやモバイルアプリにコードを組み込むことでクレジットカードなどの決済サービスが簡潔に追加できます。

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

CORS

CORSとはCross-Origin Resource Sharingの頭文字をとったもので、ブラウザがオリジン以外のサーバからデータを取得するシステムのことです。

0グッド

1クリップ

投稿2021/07/28 00:51

編集2021/07/28 01:36

前提・実現したいこと

フロントエンドとバックエンドでサーバーを分けて開発をしています
・フロントエンド: Nuxt.js, Netlify 
・バックエンド: Laravel, Heroku 

バックエンドでstripeのcheckoutページを作成して、決済画面にリダイレクトさせたいのですがCORSエラーが発生しました。

発生している問題・エラーメッセージ

CORSエラーが発生しています。

Access to XMLHttpRequest at 'https://checkout.stripe.com/pay/cs_test_XXXXX' (redirected from 'https://liff-nuxt-laravel-ec.herokuapp.com/api/stripe/store') from origin 'https://deploy-preview-4--liff-nuxt-laravel-ec.netlify.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

イメージ説明

イメージ説明

該当のソースコード

フロントエンド

vue:checkout.vue

1<template> 2 <div class="card"> 3 <img class="card-product-img" :src="this.$route.query.image" /> 4 <p class="card-product-name">{{ this.$route.query.name }}</p> 5 <p class="card-product-price">¥{{ this.$route.query.price }}</p> 6 <div class="button"> 7 <button type="submit" class="button-btn" @click="buyProducts">購入する</button> 8 </div> 9 </div> 10</template> 11 12<script> 13export default { 14 head: { 15 script: [ 16 { 17 src: 'https://js.stripe.com/v3/', 18 }, 19 ], 20 }, 21 methods: { 22 async buyProducts() { 23 const res = await this.$axios.$post('/stripe/store', { 24 productImage: this.$route.query.image, 25 productName: this.$route.query.name, 26 productPrice: this.$route.query.price, 27 productStripePriceApi: this.$route.query.stripePriceApi, 28 }); 29 console.log(res); 30 }, 31 }, 32}; 33</script>

バックエンド

php:

1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Http\Request; 6use Stripe\Stripe; 7use Stripe\Checkout\Session; 8 9class PayloadController extends Controller 10{ 11 public function store(Request $request) 12 { 13 // API 14 $stripeApiKey = config("env.stripe_api_key"); 15 Stripe::setApiKey($stripeApiKey); 16 17 // header 18 header('Content-Type: application/json'); 19 20 // domain(仮ドメイン) 21 $domain = "https://deploy-preview-4--liff-nuxt-laravel-ec.netlify.app"; 22 23 // product 24 $productImage = $request->input("productImage"); 25 $productName = $request->input("productName"); 26 $productPrice = $request->input("productPrice"); 27 $productStripePriceApi = $request->input("productStripePriceApi"); 28 29 // checkout 30 $checkout_session = Session::create([ 31 'payment_method_types' => ['card'], 32 'line_items' => [[ 33 'price' => $productStripePriceApi, 34 'quantity' => 1, 35 ]], 36 'mode' => 'payment', 37 'success_url' => $domain . '/success', 38 'cancel_url' => $domain . '/cancel', 39 ]); 40 41 return redirect($checkout_session->url, 303, [], true); 42 } 43}
CORS

php:Cors.php

1<?php 2 3namespace App\Http\Middleware; 4 5use Closure; 6 7class Cors 8{ 9 public function handle($request, Closure $next) 10 { 11 return $next($request) 12 ->header('Access-Control-Allow-Origin', '*') 13 ->header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') 14 ->header('Access-Control-Allow-Headers', 'Content-Type, X-XSRF-TOKEN'); 15 } 16}

考えたこと

Access-Control-Allow-Origin: *と指定しているので、どのドメインに対してもCORSはうまくいくと思っていました。

リダイレクトを行うときには別のheader情報を付与する必要があるのかと思い調べてみました。
https://rinoguchi.net/2019/05/302-redirect-cors.html

上記の記事内では302を使う場合、CORSエラーが発生し、対策としては302をやめるしかないとのことでした。

2点質問があります。
①私も同様に、303リダイレクトをやめるべきなのでしょうか?

②バックエンド側でリダイレクトが使えないのならば、「このURLをフロントエンド側に渡して、フロントエンド側でページ移動を行う」というものは考えついたのですが、そのような対応でいいのでしょうか?

ご確認よろしくお願いいたします。

追記

404エラーのRequest Headers情報です。

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

プリフライトリクエスト(OPTIONS、最初のキャプチャ画像)に対する応答が404になっているのが原因だと思います。あと、このキャプチャの下半分(HTTPリクエスト)にも必要な情報があるので、追記してください。


(追記)

HTTPリクエストヘッダの情報ありがとうございます。リダイレクトだとOrigin: nullとなるのですね。これは知りませんでした。
しかし、検証環境を作って調べてみたところ、Origin: nullでも、Access-Control-Allow-Origin: * レスポンスを返しておけば、CORSのエラーにはなりません。
なので、現状リダイレクト先で404となり、CORSのヘッダが返せていないことが原因だと思います。

投稿2021/07/28 01:32

編集2021/07/28 04:55
ockeghem

総合スコア11705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RyoS_

2021/07/28 01:37

ご回答ありがとうございます。 追記いたしました。
RyoS_

2021/07/28 09:14

ご回答ありがとうございます。 適切なヘッダーが転送されていないということですね。 これはどこに問題があると考えるべきなのでしょうか? また、1点アドバイスをいただきたいのですが、フロントエンド側のnuxt.jsにこちらのURLを渡して、 window.location.href = url;でページ移動をするのはどうなのでしょうか? 動作確認はでき正しく動くことがわかりました。
ockeghem

2021/07/28 09:22

それは私からは回答できないですし、別の質問とすべきだと思います。ただ、stripe固有の問題となると、回答は得られにくい気がします。
RyoS_

2021/07/28 09:42

承知しました。 ご親切にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問