【发布时间】:2021-02-03 23:24:55
【问题描述】:
这是我第一次尝试使用node js,所以我按照教程开发了一个带条纹的node js购物车,但是我买了一些东西后出现了一些错误。我的 Stripe 账户也有支票,显然这些物品没有付款
终端中的错误信息:
C:\Users\lee hao zheng\Desktop\shopping cart(node js2)\server.js:42
req.body.items.forEach(function(item){
^
TypeError: Cannot read property 'forEach' of undefined
at C:\Users\lee hao zheng\Desktop\shopping cart(node js2)\server.js:42:28
at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3)
控制台错误提示
purchase:1 Failed to load resource: net::ERR_CONNECTION_RESET
store.js:67 TypeError: Failed to fetch
(anonymous) @ store.js:67
store.js 代码
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', ready)
} else {
ready()
}
function ready() {
var removeCartItemButtons = document.getElementsByClassName('btn-danger')
for (var i = 0; i < removeCartItemButtons.length; i++) {
var button = removeCartItemButtons[i]
button.addEventListener('click', removeCartItem)
}
var quantityInputs = document.getElementsByClassName('cart-quantity-input')
for (var i = 0; i < quantityInputs.length; i++) {
var input = quantityInputs[i]
input.addEventListener('change', quantityChanged)
}
var addToCartButtons = document.getElementsByClassName('shop-item-button')
for (var i = 0; i < addToCartButtons.length; i++) {
var button = addToCartButtons[i]
button.addEventListener('click', addToCartClicked)
}
document.getElementsByClassName('btn-purchase')[0].addEventListener('click', purchaseClicked)
}
var stripeHandler =StripeCheckout.configure({
key: stripePublicKey,
locale:'en',
token:function(token){
var items=[]
var cartItemContainer= document.getElementsByClassName('cart-items')[0]
var cartRows= cartItemContainer.getElementsByClassName('cart-row')
for (var i=0; i < cartRows.length; i++){
var cartRow = cartRows[i]
var quantityElement = cartRow.getElementsByClassName('cart-quantity-input')[0]
var quantity= quantityElement.value
var id= cartRow.dataset.itemId
items.push({
id:id,
quantity: quantity
})
}
fetch('/purchase', {
method:'POST',
header:{
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
stripeTokenId: token.id,
items: items
})
}).then(function(res){
return res.json()
}).then(function(data){
alert(data.message)
var cartItems = document.getElementsByClassName('cart-items')[0]
while (cartItems.hasChildNodes()) {
cartItems.removeChild(cartItems.firstChild)
}
updateCartTotal()
}).catch(function(error){
console.error(error)
})
}
})
function purchaseClicked() {
// alert('Thank you for your purchase')
var priceElement =document.getElementsByClassName('cart-total-price')[0]
var price= parseFloat(priceElement.innerText.replace('$', ''))*100
stripeHandler.open({
amount: price
})
}
function removeCartItem(event) {
var buttonClicked = event.target
buttonClicked.parentElement.parentElement.remove()
updateCartTotal()
}
function quantityChanged(event) {
var input = event.target
if (isNaN(input.value) || input.value <= 0) {
input.value = 1
}
updateCartTotal()
}
function addToCartClicked(event) {
var button = event.target
var shopItem = button.parentElement.parentElement
var title = shopItem.getElementsByClassName('shop-item-title')[0].innerText
var price = shopItem.getElementsByClassName('shop-item-price')[0].innerText
var imageSrc = shopItem.getElementsByClassName('shop-item-image')[0].src
var id = shopItem.dataset.itemId
addItemToCart(title, price, imageSrc, id)
updateCartTotal()
}
function addItemToCart(title, price, imageSrc,id) {
var cartRow = document.createElement('div')
cartRow.classList.add('cart-row')
cartRow.dataset.itemId = id
var cartItems = document.getElementsByClassName('cart-items')[0]
var cartItemNames = cartItems.getElementsByClassName('cart-item-title')
for (var i = 0; i < cartItemNames.length; i++) {
if (cartItemNames[i].innerText == title) {
alert('This item is already added to the cart')
return
}
}
var cartRowContents = `
<div class="cart-item cart-column">
<img class="cart-item-image" src="${imageSrc}" width="100" height="100">
<span class="cart-item-title">${title}</span>
</div>
<span class="cart-price cart-column">${price}</span>
<div class="cart-quantity cart-column">
<input class="cart-quantity-input" type="number" value="1">
<button class="btn btn-danger" type="button">REMOVE</button>
</div>`
cartRow.innerHTML = cartRowContents
cartItems.append(cartRow)
cartRow.getElementsByClassName('btn-danger')[0].addEventListener('click', removeCartItem)
cartRow.getElementsByClassName('cart-quantity-input')[0].addEventListener('change', quantityChanged)
}
function updateCartTotal() {
var cartItemContainer = document.getElementsByClassName('cart-items')[0]
var cartRows = cartItemContainer.getElementsByClassName('cart-row')
var total = 0
for (var i = 0; i < cartRows.length; i++) {
var cartRow = cartRows[i]
var priceElement = cartRow.getElementsByClassName('cart-price')[0]
var quantityElement = cartRow.getElementsByClassName('cart-quantity-input')[0]
var price = parseFloat(priceElement.innerText.replace('$', ''))
var quantity = quantityElement.value
total = total + (price * quantity)
}
total = Math.round(total * 100) / 100
document.getElementsByClassName('cart-total-price')[0].innerText = '$' + total
}
这是要运行的文件,server.js
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
// require('dotenv').load()
}
const stripeSecretKey = process.env.STRIPE_SECRET_KEY
const stripePublictKey = process.env.STRIPE_PUBLIC_KEY
console.log(stripeSecretKey,stripePublictKey)
const express= require('express')
const app =express()
const fs=require('fs')
const stripe = require('stripe')(stripeSecretKey)
app.set('view engine', 'ejs')
app.use(express.json())
app.use(express.static('public'))
app.get('/store.html',function(req, res){
fs.readFile('items.json', function(error,data){
if(error){
res.status(500).end()
}else{
res.render('store.ejs',{
stripePublicKey: stripePublictKey,
items: JSON.parse(data)
})
}
})
})
app.post('/purchase',function(req, res){
fs.readFile('items.json', function(error,data){
if(error){
res.status(500).end()
}else{
const itemsJson = JSON.parse(data)
const itemsArray = itemsJson.music.concat(itemsJson.merch)
let total = 0;
req.body.items.forEach(function(item){
const itemJson = itemsArray.find(function(i){
return i.id == item.id
})
total = total + itemJson.price* item.quantity
})
stripe.charges.create({
amount: total,
source: req.body.stripeTokenId,
currency:'usd'
}).then(function(){
console.log('Charge Successful')
res.json({message: 'Successfully purchased items'})
}).catch(function(){
console.log('Charge Fail')
res.status(500).end()
})
}
})
})
app.listen(3000)
store.ejs
<!DOCTYPE html>
<html>
<head>
<title>The Generics | Store</title>
<meta name="description" content="This is the description">
<link rel="stylesheet" href="styles.css" />
<script src="https://checkout.stripe.com/checkout.js" defer></script>
<script>
var stripePublicKey = '<%= stripePublicKey %>'
</script>
<script src="store.js" defer></script>
</head>
<body>
<header class="main-header">
<nav class="main-nav nav">
<ul>
<li><a href="index.html">HOME</a></li>
<li><a href="store.html">STORE</a></li>
<li><a href="about.html">ABOUT</a></li>
</ul>
</nav>
<h1 class="band-name band-name-large">The Generics</h1>
</header>
<section class="container content-section">
<h2 class="section-header">MUSIC</h2>
<div class="shop-items" >
<% items.music.forEach(function(item){%>
<div class="shop-item" data-item-id="<%= item.id%>">
<span class="shop-item-title"><%= item.name%></span>
<img class="shop-item-image" src="Images/<%= item.imgName%> ">
<div class="shop-item-details">
<span class="shop-item-price">$<%= item.price/100 %> </span>
<button class="btn btn-primary shop-item-button" type="button">ADD TO CART</button>
</div>
</div>
<% }) %>
</div>
</section>
<section class="container content-section">
<h2 class="section-header">MERCH</h2>
<div class="shop-items">
<% items.merch.forEach(function(item){%>
<div class="shop-item" data-item-id="<%= item.id%>">
<span class="shop-item-title"><%= item.name%></span>
<img class="shop-item-image" src="Images/<%= item.imgName%> ">
<div class="shop-item-details">
<span class="shop-item-price">$<%= item.price/100 %> </span>
<button class="btn btn-primary shop-item-button" type="button">ADD TO CART</button>
</div>
</div>
<% }) %>
</div>
</section>
<section class="container content-section">
<h2 class="section-header">CART</h2>
<div class="cart-row">
<span class="cart-item cart-header cart-column">ITEM</span>
<span class="cart-price cart-header cart-column">PRICE</span>
<span class="cart-quantity cart-header cart-column">QUANTITY</span>
</div>
<div class="cart-items">
</div>
<div class="cart-total">
<strong class="cart-total-title">Total</strong>
<span class="cart-total-price">$0</span>
</div>
<button class="btn btn-primary btn-purchase" type="button">PURCHASE</button>
</section>
<footer class="main-footer">
<div class="container main-footer-container">
<h3 class="band-name">The Generics</h3>
<ul class="nav footer-nav">
<li>
<a href="https://www.youtube.com" target="_blank">
<img src="Images/YouTube Logo.png">
</a>
</li>
<li>
<a href="https://www.spotify.com" target="_blank">
<img src="Images/Spotify Logo.png">
</a>
</li>
<li>
<a href="https://www.facebook.com" target="_blank">
<img src="Images/Facebook Logo.png">
</a>
</li>
</ul>
</div>
</footer>
</body>
</html>
【问题讨论】:
-
我建议你做
console.log(req.body)看看它到底是什么。显然req.body.items不是您认为的数组。
标签: javascript node.js express stripe-payments