Javascript 条带:必须提供来源或客户
我正在尝试为我的购物车项目集成Stripe。我无法提交我的结账表。我一直收到这样的错误消息:“必须提供源代码或客户。”要么我没有正确设置条带帐户,要么我的javascript中缺少一些参数。我在这个问题上花了好几个小时,还是没能解决 这来自Stripe的日志:Javascript 条带:必须提供来源或客户,javascript,node.js,mongodb,stripe-payments,Javascript,Node.js,Mongodb,Stripe Payments,我正在尝试为我的购物车项目集成Stripe。我无法提交我的结账表。我一直收到这样的错误消息:“必须提供源代码或客户。”要么我没有正确设置条带帐户,要么我的javascript中缺少一些参数。我在这个问题上花了好几个小时,还是没能解决 这来自Stripe的日志: 解析的请求帖子正文 { "amount": "21000", "currency": "usd", "description": "Test Charge" } { "error": { "type": "inv
解析的请求帖子正文
{
"amount": "21000",
"currency": "usd",
"description": "Test Charge"
}
{
"error": {
"type": "invalid_request_error",
"message": "Must provide source or customer."
}
}
响应主体
{
"amount": "21000",
"currency": "usd",
"description": "Test Charge"
}
{
"error": {
"type": "invalid_request_error",
"message": "Must provide source or customer."
}
}
这是我的app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var expressHbs = require('express-handlebars');
var mongoose = require('mongoose');
var session = require('express-session');
var passport = require('passport');
var flash = require('connect-flash');
var validator = require('express-validator');
var MongoStore = require('connect-mongo')(session);
var routes = require('./routes/index');
var userRoutes = require('./routes/user');
var app = express();
mongoose.connect('localhost:27017/shopping');
require('./config/passport');
// view engine setup
app.engine('.hbs', expressHbs({defaultLayout: 'layout', extname: '.hbs'}));
app.set('view engine', '.hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(validator());
app.use(cookieParser());
app.use(session({
secret: 'mysupersecret',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection }),
cookie: { maxAge: 180 * 60 * 1000 }
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next){
res.locals.login = req.isAuthenticated();
res.locals.session = req.session;
next();
});
app.use('/user', userRoutes);
app.use('/', routes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
这是我的索引。js:
var express = require('express');
var router = express.Router();
var Cart = require('../models/cart');
var Product = require('../models/product');
/* GET home page. */
router.get('/', function(req, res, next) {
var successMsg = req.flash('success')[0];
Product.find(function(err, docs) {
var productChunks = [];
var chunkSize = 3;
for (var i = 0; i < docs.length; i += chunkSize) {
productChunks.push(docs.slice(i, i + chunkSize));
}
res.render('shop/index', { title: 'Shopping Cart', products: productChunks, successMsg: successMsg, noMessages: !successMsg});
});
});
router.get('/add-to-cart/:id', function(req, res, next) {
var productId = req.params.id;
var cart = new Cart(req.session.cart ? req.session.cart : {});
Product.findById(productId, function(err, product){
if (err) {
return res.redirect('/');
}
cart.add(product, product.id);
req.session.cart = cart;
console.log(req.session.cart);
res.redirect('/');
});
});
router.get('/shopping-cart', function(req, res, next) {
if (!req.session.cart) {
return res.render('shop/shopping-cart', {products: null});
}
var cart = new Cart(req.session.cart);
res.render('shop/shopping-cart', {products: cart.generateArray(), totalPrice: cart.totalPrice});
});
router.get('/checkout', function(req, res, next) {
if (!req.session.cart) {
return res.redirect('/shopping-cart');
}
var cart = new Cart(req.session.cart);
var errMsg = req.flash('error')[0];
res.render('shop/checkout', {total: cart.totalPrice, errMsg: errMsg, noError: !errMsg});
});
router.post('/checkout', function(req, res, next) {
if (!req.session.cart) {
return res.redirect('/shopping-cart');
}
var cart = new Cart(req.session.cart);
var stripe = require("stripe")(
"**hidden**"
);
stripe.charges.create({
amount: cart.totalPrice * 100,
currency: "usd",
source: req.body.stripeToken,
description: "Test Charge"
}, function(err, charge) {
if (err) {
req.flash('error', err.message);
return res.redirect('/checkout');
}
req.flash('success', 'Successfully bought product!');
req.cart = null;
res.redirect('/');
});
});
module.exports = router;
Stripe.setPublishableKey('**hidden**');
var $form = $('checkout-form');
$form.submit(function(event) {
$('#charge-errors').addClass('hidden');
$form.find('button').prop('disabled', true);
Stripe.card.createToken({
number: $('#card-number').val(),
cvc: $('#card-cvc').val(),
exp_month: $('#card-expiry-month').val(),
exp_year: $('#card-expiry-year').val(),
name: $('#card-name').val()
}, stripeResponseHandler);
return false;
});
function stripeResponseHandler(status, response) {
if (response.error) { // Problem!
// Show the errors on the form
$('#charge-errors').text(response.error.message);
$('#charge-errors').removeClass('hidden');
$form.find('button').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
// Insert the token into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// Submit the form:
$form.get(0).submit();
}
};
<div class="row">
<div class="col-sm-6 col-md-6 col-md-offset-3 col-sm-offset-3">
<h1>Checkout</h1>
<h4>Your Total: ${{total}}</h4>
<div id="charge-error" class="alert alert-danger {{# if noError}}hidden{{/if}}">
{{errMsg}}
</div>
<form action="/checkout" method="post" id="checkout-form">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Address</label>
<input type="text" id="address" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Name on Card</label>
<input type="text" id="card-name" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Credit Card Number</label>
<input type="text" id="card-number" class="form-control" required>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="name">Expiration Month</label>
<input type="text" id="card-expiry-month" class="form-control" required>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="name">Expiration Year</label>
<input type="text" id="card-expiry-year" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">
CVC</label>
<input type="text" id="card-cvc" class="form-control" required>
</div>
</div>
</div>
<button type="submit" class="btn btn-success">Buy Now</button>
</form>
</div>
</div>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript" src="javascripts/checkout.js"></script>
var express=require('express');
var router=express.router();
var Cart=require('../models/Cart');
var Product=require(“../models/Product”);
/*获取主页*/
router.get('/',函数(req,res,next){
var successsg=req.flash('success')[0];
Product.find(函数(错误、文档){
var productChunks=[];
var-chunkSize=3;
对于(变量i=0;i
这是我的结帐。js:
var express = require('express');
var router = express.Router();
var Cart = require('../models/cart');
var Product = require('../models/product');
/* GET home page. */
router.get('/', function(req, res, next) {
var successMsg = req.flash('success')[0];
Product.find(function(err, docs) {
var productChunks = [];
var chunkSize = 3;
for (var i = 0; i < docs.length; i += chunkSize) {
productChunks.push(docs.slice(i, i + chunkSize));
}
res.render('shop/index', { title: 'Shopping Cart', products: productChunks, successMsg: successMsg, noMessages: !successMsg});
});
});
router.get('/add-to-cart/:id', function(req, res, next) {
var productId = req.params.id;
var cart = new Cart(req.session.cart ? req.session.cart : {});
Product.findById(productId, function(err, product){
if (err) {
return res.redirect('/');
}
cart.add(product, product.id);
req.session.cart = cart;
console.log(req.session.cart);
res.redirect('/');
});
});
router.get('/shopping-cart', function(req, res, next) {
if (!req.session.cart) {
return res.render('shop/shopping-cart', {products: null});
}
var cart = new Cart(req.session.cart);
res.render('shop/shopping-cart', {products: cart.generateArray(), totalPrice: cart.totalPrice});
});
router.get('/checkout', function(req, res, next) {
if (!req.session.cart) {
return res.redirect('/shopping-cart');
}
var cart = new Cart(req.session.cart);
var errMsg = req.flash('error')[0];
res.render('shop/checkout', {total: cart.totalPrice, errMsg: errMsg, noError: !errMsg});
});
router.post('/checkout', function(req, res, next) {
if (!req.session.cart) {
return res.redirect('/shopping-cart');
}
var cart = new Cart(req.session.cart);
var stripe = require("stripe")(
"**hidden**"
);
stripe.charges.create({
amount: cart.totalPrice * 100,
currency: "usd",
source: req.body.stripeToken,
description: "Test Charge"
}, function(err, charge) {
if (err) {
req.flash('error', err.message);
return res.redirect('/checkout');
}
req.flash('success', 'Successfully bought product!');
req.cart = null;
res.redirect('/');
});
});
module.exports = router;
Stripe.setPublishableKey('**hidden**');
var $form = $('checkout-form');
$form.submit(function(event) {
$('#charge-errors').addClass('hidden');
$form.find('button').prop('disabled', true);
Stripe.card.createToken({
number: $('#card-number').val(),
cvc: $('#card-cvc').val(),
exp_month: $('#card-expiry-month').val(),
exp_year: $('#card-expiry-year').val(),
name: $('#card-name').val()
}, stripeResponseHandler);
return false;
});
function stripeResponseHandler(status, response) {
if (response.error) { // Problem!
// Show the errors on the form
$('#charge-errors').text(response.error.message);
$('#charge-errors').removeClass('hidden');
$form.find('button').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
// Insert the token into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// Submit the form:
$form.get(0).submit();
}
};
<div class="row">
<div class="col-sm-6 col-md-6 col-md-offset-3 col-sm-offset-3">
<h1>Checkout</h1>
<h4>Your Total: ${{total}}</h4>
<div id="charge-error" class="alert alert-danger {{# if noError}}hidden{{/if}}">
{{errMsg}}
</div>
<form action="/checkout" method="post" id="checkout-form">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Address</label>
<input type="text" id="address" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Name on Card</label>
<input type="text" id="card-name" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Credit Card Number</label>
<input type="text" id="card-number" class="form-control" required>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="name">Expiration Month</label>
<input type="text" id="card-expiry-month" class="form-control" required>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="name">Expiration Year</label>
<input type="text" id="card-expiry-year" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">
CVC</label>
<input type="text" id="card-cvc" class="form-control" required>
</div>
</div>
</div>
<button type="submit" class="btn btn-success">Buy Now</button>
</form>
</div>
</div>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript" src="javascripts/checkout.js"></script>
Stripe.setPublishableKey('**隐藏**');
var$form=$('checkout-form');
$form.submit(函数(事件){
$(“#费用错误”).addClass(“隐藏”);
$form.find('button').prop('disabled',true);
Stripe.card.createToken({
编号:$(“#卡号”).val(),
cvc:$(“#卡cvc”).val(),
exp_month:$(“#卡到期月”).val(),
exp_year:$(“#卡到期年”).val(),
名称:$(“#卡名”).val()
},stripeResponseHandler);
返回false;
});
函数stripeResponseHandler(状态、响应){
if(response.error){//问题!
//在表单上显示错误
$(“#收费错误”).text(response.error.message);
$(“#费用错误”).removeClass('hidden');
$form.find('button').prop('disabled',false);//重新启用提交
}否则{//令牌已创建!
//获取令牌ID:
var token=response.id;
//将令牌插入表单,以便将其提交到服务器:
$form.append($('').val(标记));
//提交表格:
$form.get(0.submit();
}
};
这是我的结账表(.hbs):
var express = require('express');
var router = express.Router();
var Cart = require('../models/cart');
var Product = require('../models/product');
/* GET home page. */
router.get('/', function(req, res, next) {
var successMsg = req.flash('success')[0];
Product.find(function(err, docs) {
var productChunks = [];
var chunkSize = 3;
for (var i = 0; i < docs.length; i += chunkSize) {
productChunks.push(docs.slice(i, i + chunkSize));
}
res.render('shop/index', { title: 'Shopping Cart', products: productChunks, successMsg: successMsg, noMessages: !successMsg});
});
});
router.get('/add-to-cart/:id', function(req, res, next) {
var productId = req.params.id;
var cart = new Cart(req.session.cart ? req.session.cart : {});
Product.findById(productId, function(err, product){
if (err) {
return res.redirect('/');
}
cart.add(product, product.id);
req.session.cart = cart;
console.log(req.session.cart);
res.redirect('/');
});
});
router.get('/shopping-cart', function(req, res, next) {
if (!req.session.cart) {
return res.render('shop/shopping-cart', {products: null});
}
var cart = new Cart(req.session.cart);
res.render('shop/shopping-cart', {products: cart.generateArray(), totalPrice: cart.totalPrice});
});
router.get('/checkout', function(req, res, next) {
if (!req.session.cart) {
return res.redirect('/shopping-cart');
}
var cart = new Cart(req.session.cart);
var errMsg = req.flash('error')[0];
res.render('shop/checkout', {total: cart.totalPrice, errMsg: errMsg, noError: !errMsg});
});
router.post('/checkout', function(req, res, next) {
if (!req.session.cart) {
return res.redirect('/shopping-cart');
}
var cart = new Cart(req.session.cart);
var stripe = require("stripe")(
"**hidden**"
);
stripe.charges.create({
amount: cart.totalPrice * 100,
currency: "usd",
source: req.body.stripeToken,
description: "Test Charge"
}, function(err, charge) {
if (err) {
req.flash('error', err.message);
return res.redirect('/checkout');
}
req.flash('success', 'Successfully bought product!');
req.cart = null;
res.redirect('/');
});
});
module.exports = router;
Stripe.setPublishableKey('**hidden**');
var $form = $('checkout-form');
$form.submit(function(event) {
$('#charge-errors').addClass('hidden');
$form.find('button').prop('disabled', true);
Stripe.card.createToken({
number: $('#card-number').val(),
cvc: $('#card-cvc').val(),
exp_month: $('#card-expiry-month').val(),
exp_year: $('#card-expiry-year').val(),
name: $('#card-name').val()
}, stripeResponseHandler);
return false;
});
function stripeResponseHandler(status, response) {
if (response.error) { // Problem!
// Show the errors on the form
$('#charge-errors').text(response.error.message);
$('#charge-errors').removeClass('hidden');
$form.find('button').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
// Insert the token into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// Submit the form:
$form.get(0).submit();
}
};
<div class="row">
<div class="col-sm-6 col-md-6 col-md-offset-3 col-sm-offset-3">
<h1>Checkout</h1>
<h4>Your Total: ${{total}}</h4>
<div id="charge-error" class="alert alert-danger {{# if noError}}hidden{{/if}}">
{{errMsg}}
</div>
<form action="/checkout" method="post" id="checkout-form">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label for="name">Name</label>
<input type="text" id="name" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Address</label>
<input type="text" id="address" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Name on Card</label>
<input type="text" id="card-name" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">Credit Card Number</label>
<input type="text" id="card-number" class="form-control" required>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="name">Expiration Month</label>
<input type="text" id="card-expiry-month" class="form-control" required>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="name">Expiration Year</label>
<input type="text" id="card-expiry-year" class="form-control" required>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<label for="name">
CVC</label>
<input type="text" id="card-cvc" class="form-control" required>
</div>
</div>
</div>
<button type="submit" class="btn btn-success">Buy Now</button>
</form>
</div>
</div>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript" src="javascripts/checkout.js"></script>
结账
您的总数:${{Total}
{{errMsg}}
名称
地址
卡片上的名字
信用卡号码
到期月份
到期年
CVC
立即购买
带条带的支付流分为两个步骤:
您需要检查您的服务器端代码,以找出问题的确切原因。您还可以在仪表板中查看集成发送的所有请求的日志:。因此,几天前我通过电子邮件向Stripe支持团队寻求有关此问题的帮助,并最终获得了解决方案 错误实际上在前端。我没有在签出表单下引用jquery。我可以通过简单地添加 调用checkout.js文件之前执行
。我的结账