Я пытаюсь сохранить данные из дополнительных входов в форме, а не только данные кредитной карты.
Вот как выглядит форма: изображение формы
Оплата работает, и бронирование сохраняется в базе данных. Я изо всех сил пытаюсь выяснить, как также получить дополнительные входные данные формы "ссылку на ваш проект" и "дополнительную информацию", которые также хранятся в БД.
Вот что код любит на сервере:
router.route('/pay')
.post(async (req, res, next) => {
let artist = req.session.artist;
let price = req.session.price;
let user = req.session.user;
let email = req.session.userEmail;
price *= 100;
const {
paymentMethodId,
paymentIntentId,
currency,
useStripeSdk
} = req.body;
try {
let intent;
if (paymentMethodId) {
// Create new PaymentIntent with a PaymentMethod ID from the client.
intent = await stripe.paymentIntents.create({
amount: price,
currency: currency,
receipt_email: email,
payment_method: paymentMethodId,
confirmation_method: 'manual',
confirm: true,
// If a mobile client passes `useStripeSdk`, set `use_stripe_sdk=true`
// to take advantage of new authentication features in mobile SDKs
use_stripe_sdk: useStripeSdk
});
// After create, if the PaymentIntent's status is succeeded, fulfill the order.
} else if (paymentIntentId) {
// Confirm the PaymentIntent to finalize payment after handling a required action
// on the client.
intent = await stripe.paymentIntents.confirm(paymentIntentId);
// After confirm, if the PaymentIntent's status is succeeded, fulfill the order.
}
let newBooking = await Booking.create({
artist,
user,
price,
projectLink: req.body.projectLink,
additionalInfo: req.body.additionalInfo
});
console.log(newBooking)
let data = {
intent: generateResponse(intent)
};
res.send(data);
} catch (e) {
// Handle "hard declines" e.g. insufficient funds, expired card, etc
// See https://stripe.com/docs/declines/codes for more
res.send({
error: e.message
});
}
});
А вот как это выглядит на клиенте:
var stripe = Stripe('pk_test_ycz...');
// A reference to Stripe.js
var stripe;
var orderData = {
items: [{
id: "photo-subscription"
}],
currency: "usd"
};
// Disable the button until we have Stripe set up on the page
document.querySelector(".disable").disabled = true;
fetch("/stripe-key")
.then(function (result) {
return result.json();
})
.then(function (data) {
return setupElements(data);
})
.then(function ({
stripe,
card,
clientSecret
}) {
document.querySelector(".disable").disabled = false;
var form = document.getElementById("payment-form");
form.addEventListener("submit", function (event) {
event.preventDefault();
const projectLink = document.getElementById('projectLink').value;
const additionalInfo = document.getElementById('additionalInfo').value;
pay(stripe, card, clientSecret, projectLink, additionalInfo);
console.log(projectLink, additionalInfo)
});
});
var setupElements = function (data) {
stripe = Stripe(data.publishableKey);
/* ------- Set up Stripe Elements to use in checkout form ------- */
var elements = stripe.elements();
var style = {
base: {
color: "#32325d",
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#aab7c4"
}
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a"
}
};
var card = elements.create("card", {
style: style
});
card.mount("#card-element");
return {
stripe: stripe,
card: card,
clientSecret: data.clientSecret
};
};
var handleAction = function (clientSecret, projectLink, additionalInfo) {
stripe.handleCardAction(clientSecret).then(function (data) {
if (data.error) {
showError("Your card was not authenticated, please try again");
} else if (data.paymentIntent.status === "requires_confirmation") {
fetch("/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
paymentIntentId: data.paymentIntent.id
})
})
.then(function (result) {
return result.json();
})
.then(function (json) {
if (json.error) {
showError(json.error);
} else {
orderComplete(clientSecret);
}
});
}
});
};
/*
* Collect card details and pay for the order
*/
var pay = function (stripe, card) {
changeLoadingState(true);
// Collects card details and creates a PaymentMethod
stripe
.createPaymentMethod("card", card)
.then(function (result) {
if (result.error) {
showError(result.error.message);
} else {
orderData.paymentMethodId = result.paymentMethod.id;
return fetch("/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(orderData)
});
}
})
.then(function (result) {
return result.json();
})
.then(function (response) {
if (response.intent.error) {
showError(response.intent.error);
} else if (response.intent.requiresAction) {
// Request authentication
handleAction(response.intent.clientSecret);
} else {
orderComplete(response.intent.clientSecret);
}
});
};
На стороне сервера я использовал req.body для обоих входов в Booking.create (... ) но я не уверен, как получить это от клиента, используя код Stripe. На стороне клиента я пытался добавить данные формы в вызов API fetch для / pay, но не мог понять, как заставить его работать. Если у кого-то есть идеи, это было бы здорово. Спасибо