条纹:必须提供来源或客户 [英] Stripe: Must provide source or customer
问题描述
我正在尝试将Stripe集成到我的购物车项目中。我无法提交结帐表单。我不断收到此错误消息:必须提供来源或客户。要么我没有正确设置我的Stripe帐户,要么我在我的javascript中缺少一些参数。我花了好几个小时才解决这个问题,但仍然无法理解。
I'm trying to integrate Stripe for my shopping cart project. I can't get my checkout form to submit. I keep getting this error message: "Must provide source or customer." Either I didn't set up my Stripe account correctly or I'm missing some parameters in my javascript. I've spent hours on this problem and still can't figure it out.
这是来自Stripe的日志:
Parsed Request POST Body
This is from Stripe's log:
Parsed Request POST Body
{
"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="https://js.stripe.com/v2/"></script>
<script type="text/javascript" src="javascripts/checkout.js"></script>
推荐答案
使用Stripe的付款流程分为两个步骤:
A payment flow with Stripe is divided in two steps:
Client-side, in your frontend code, you collect and tokenize the customer's payment information using Checkout or Elements, then send the resulting token to your backend server.
服务器端,在后端代码中,您在API请求中使用令牌,例如创建费用或客户。
Server-side, in your backend code, you use the token in an API request, e.g. to create a charge or a customer.
您分享的代码是第一步。但是,您提到的错误消息:
The code you shared is for the first step. However, the error message you mentioned:
必须提供来源或客户。
Must provide source or customer.
在第二步中发生。当您在没有费用创建请求时,Stripe的API会返回此错误https://stripe.com/docs/api#create_charge-source\"rel =noreferrer> 来源
或 customer
参数。
occurs in the second step. This error is returned by Stripe's API when you send a charge creation request without a source
or customer
parameter.
您需要检查服务器端代码以确定问题的确切原因。您还可以在信息中心中查看集成发送的所有请求的日志: https:// dashboard.stripe.com/test/logs?method=not_get 。
You need to check your server-side code to figure out what the problem is exactly. You can also check the logs of all requests sent by your integration in your dashboard: https://dashboard.stripe.com/test/logs?method=not_get.
这篇关于条纹:必须提供来源或客户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!