条纹:必须提供源或客户
我试图条纹整合了我的购物车项目。我不能让我结账的形式提交。我不断收到此错误信息:“必须提供源或客户。”要么我没有设置我的条纹帐户正确或我丢失在我的JavaScript的一些参数。我已经在这个问题上花了几个小时,但还是无法弄明白。
这是条纹的日志: 解析的请求POST主体
{
"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;
这是我的index.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;
这是我的checkout.js:
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();
}
};
这是我结账的形式(.hbs):
<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="/"></script>
<script type="text/javascript" src="javascripts/checkout.js"></script>
回答如下:
有条纹的支付流在两个步骤分为:
- 客户端,在您的前端代码,您收集和使用Checkout或Elements记号化客户的付款信息,然后将生成的令牌到你的后台服务器。
- 服务器端,在后端代码,您使用的令牌API请求,例如到create a charge或a customer。
您共享的代码是第一步。不过,你提到的错误信息:
必须提供源或客户。
发生在第二步骤。由条纹的API,当你没有charge creation request或source
参数发送customer
返回此错误。
你需要检查你的服务器端代码,以找出问题到底是什么。您还可以检查您的整合在信息中心发送的所有请求的日志:https://dashboard.stripe/test/logs?method=not_get。
条纹:必须提供源或客户
我试图条纹整合了我的购物车项目。我不能让我结账的形式提交。我不断收到此错误信息:“必须提供源或客户。”要么我没有设置我的条纹帐户正确或我丢失在我的JavaScript的一些参数。我已经在这个问题上花了几个小时,但还是无法弄明白。
这是条纹的日志: 解析的请求POST主体
{
"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;
这是我的index.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;
这是我的checkout.js:
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();
}
};
这是我结账的形式(.hbs):
<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="/"></script>
<script type="text/javascript" src="javascripts/checkout.js"></script>
回答如下:
有条纹的支付流在两个步骤分为:
- 客户端,在您的前端代码,您收集和使用Checkout或Elements记号化客户的付款信息,然后将生成的令牌到你的后台服务器。
- 服务器端,在后端代码,您使用的令牌API请求,例如到create a charge或a customer。
您共享的代码是第一步。不过,你提到的错误信息:
必须提供源或客户。
发生在第二步骤。由条纹的API,当你没有charge creation request或source
参数发送customer
返回此错误。
你需要检查你的服务器端代码,以找出问题到底是什么。您还可以检查您的整合在信息中心发送的所有请求的日志:https://dashboard.stripe/test/logs?method=not_get。