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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Stripe

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

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

0回答

656閲覧

【React】Stripe Elementsのチュートリアルが進まない

joenobuo

総合スコア11

Stripe

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

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2022/06/24 15:40

編集2022/06/25 09:46

やりたいこと

ReactのプロジェクトにStripe Elementsを組み込もうとしています。

分からないこと・躓いている点

チュートリアルを見ながら進めていたのですが、
サーバー側の処理で止まってしまい、Checkout Form画面が表示されません。
どうすれば先の処理に進み、フォームを表示出来るか教えて頂けませんでしょうか。

本来であれば、以下のようなフォームが表示されるようです。
成功例

言語等

OS:Windows10
フロント側:React
サーバー側:node.js

コード

上記のリンク先にも同様のコードがありますが、こちらにも貼ります。
npm startでアプリを起動しても、server.jsのapp.listenの部分から進んでいないようです。

javascript

1//server.js(サーバー側の処理を記述) 2 3const express = require("express"); 4const app = express(); 5// This is your test secret API key. 6const stripe = require("stripe")("ここにAPIキーを記述"); 7 8app.use(express.static("public")); 9app.use(express.json()); 10 11const calculateOrderAmount = (items) => { 12 // Replace this constant with a calculation of the order's amount 13 // Calculate the order total on the server to prevent 14 // people from directly manipulating the amount on the client 15 return 1400; 16}; 17 18app.post("/create-payment-intent", async (req, res) => { 19 const { items } = req.body; 20 21 // Create a PaymentIntent with the order amount and currency 22 const paymentIntent = await stripe.paymentIntents.create({ 23 amount: calculateOrderAmount(items), 24 currency: "eur", 25 automatic_payment_methods: { 26 enabled: true, 27 }, 28 }); 29 30 res.send({ 31 clientSecret: paymentIntent.client_secret, 32 }); 33}); 34 35//ここで止まる… 36app.listen(4242, () => console.log("Node server listening on port 4242!"));

jsx

1 2//App.jsx(最上位コンポーネント) 3import React, { useState, useEffect } from "react"; 4import { loadStripe } from "@stripe/stripe-js"; 5import { Elements } from "@stripe/react-stripe-js"; 6 7import CheckoutForm from "./CheckoutForm"; 8import "./App.css"; 9 10// Make sure to call loadStripe outside of a component’s render to avoid 11// recreating the Stripe object on every render. 12// This is your test publishable API key. 13const stripePromise = loadStripe("ここにAPIキーを記述"); 14 15export default function App() { 16 const [clientSecret, setClientSecret] = useState(""); 17 18 useEffect(() => { 19 // Create PaymentIntent as soon as the page loads 20 fetch("/create-payment-intent", { 21 method: "POST", 22 headers: { "Content-Type": "application/json" }, 23 body: JSON.stringify({ items: [{ id: "xl-tshirt" }] }), 24 }) 25 .then((res) => res.json()) 26 .then((data) => setClientSecret(data.clientSecret)); 27 }, []); 28 29 const appearance = { 30 theme: 'stripe', 31 }; 32 const options = { 33 clientSecret, 34 appearance, 35 }; 36 37 return ( 38 <div className="App"> 39 {clientSecret && ( 40 <Elements options={options} stripe={stripePromise}> 41 <CheckoutForm /> 42 </Elements> 43 )} 44 </div> 45 ); 46} 47

jsx

1 2//CheckoutForm.jsx(決済フォームを表示するコンポーネント) 3import React, { useEffect, useState } from "react"; 4import { 5 PaymentElement, 6 useStripe, 7 useElements 8} from "@stripe/react-stripe-js"; 9 10export default function CheckoutForm() { 11 const stripe = useStripe(); 12 const elements = useElements(); 13 14 const [message, setMessage] = useState(null); 15 const [isLoading, setIsLoading] = useState(false); 16 17 useEffect(() => { 18 if (!stripe) { 19 return; 20 } 21 22 const clientSecret = new URLSearchParams(window.location.search).get( 23 "payment_intent_client_secret" 24 ); 25 26 if (!clientSecret) { 27 return; 28 } 29 30 stripe.retrievePaymentIntent(clientSecret).then(({ paymentIntent }) => { 31 switch (paymentIntent.status) { 32 case "succeeded": 33 setMessage("Payment succeeded!"); 34 break; 35 case "processing": 36 setMessage("Your payment is processing."); 37 break; 38 case "requires_payment_method": 39 setMessage("Your payment was not successful, please try again."); 40 break; 41 default: 42 setMessage("Something went wrong."); 43 break; 44 } 45 }); 46 }, [stripe]); 47 48 const handleSubmit = async (e) => { 49 e.preventDefault(); 50 51 if (!stripe || !elements) { 52 // Stripe.js has not yet loaded. 53 // Make sure to disable form submission until Stripe.js has loaded. 54 return; 55 } 56 57 setIsLoading(true); 58 59 const { error } = await stripe.confirmPayment({ 60 elements, 61 confirmParams: { 62 // Make sure to change this to your payment completion page 63 return_url: "http://localhost:3000", 64 }, 65 }); 66 67 // This point will only be reached if there is an immediate error when 68 // confirming the payment. Otherwise, your customer will be redirected to 69 // your `return_url`. For some payment methods like iDEAL, your customer will 70 // be redirected to an intermediate site first to authorize the payment, then 71 // redirected to the `return_url`. 72 if (error.type === "card_error" || error.type === "validation_error") { 73 setMessage(error.message); 74 } else { 75 setMessage("An unexpected error occurred."); 76 } 77 78 setIsLoading(false); 79 }; 80 81 return ( 82 <form id="payment-form" onSubmit={handleSubmit}> 83 <PaymentElement id="payment-element" /> 84 <button disabled={isLoading || !stripe || !elements} id="submit"> 85 <span id="button-text"> 86 {isLoading ? <div className="spinner" id="spinner"></div> : "Pay now"} 87 </span> 88 </button> 89 {/* Show any error or success messages */} 90 {message && <div id="payment-message">{message}</div>} 91 </form> 92 ); 93} 94

json

1//package.json 2{ 3 "name": "stripe-sample", 4 "version": "0.1.0", 5 "dependencies": { 6 "@stripe/react-stripe-js": "^1.0.0", 7 "@stripe/stripe-js": "^1.0.0", 8 "express": "^4.18.1", 9 "react": "^16.9.0", 10 "react-dom": "^16.9.0", 11 "react-scripts": "^3.4.0", 12 "stripe": "^8.202.0" 13 }, 14 "devDependencies": { 15 "concurrently": "4.1.2" 16 }, 17 "homepage": "http://localhost:3000/checkout", 18 "proxy": "http://localhost:4242", 19 "scripts": { 20 "start-client": "react-scripts start", 21 "start-server": "node server.js", 22 "build": "react-scripts build", 23 "test": "react-scripts test", 24 "eject": "react-scripts eject" 25 }, 26 "eslintConfig": { 27 "extends": "react-app" 28 }, 29 "browserslist": { 30 "production": [ 31 ">0.2%", 32 "not dead", 33 "not op_mini all" 34 ], 35 "development": [ 36 "last 1 chrome version", 37 "last 1 firefox version", 38 "last 1 safari version" 39 ] 40 } 41}

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

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

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

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問