我的公式中出现了 PHP Notice: Undefined index: stripeToken
。
它的关系$_POST['stripeToken']
if (!isset($stripe_payment_intent_id)) {
$description = 'Order date time : ' . date('Y-m-d H:i:s');
$token = $_POST['stripeToken'];
$params = [
'amount' => $total_amount,
'currency' => $currency,
'source' => $token,
'setup_future_usage' => 'off_session',
'description' => $description,
'capture_method' => $capture_method,
'metadata' => $metadata
];
$this->intent = PaymentIntent::create($params);
// $this->event_log($customer_id, "page create intent", json_encode($params), $this->intent);
$stripe_payment_intent_id = $this->intent->id;
unset($_SESSION['stripe_payment_intent_id']);
}
你知道如何解决这个问题吗?
也许必须在里面添加一些东西作为隐藏字段来考虑 $_POST
?
传统
这是我的 javascript
public function getSubmitCardDetailsJavascript($intent = null)
{
$stripe_publishable_key = $this->public_key;
// $intent_url = tep_href_link("ext/modules/payment/stripe_sca/payment_intent.php", '', 'SSL', false, false);
$intent_url = ''; // return url
$js = <<<EOD
<style>
#stripe_table_new_card #card-element {
background-color: #fff;
padding: 6px 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
</style>
<script src="https://js.stripe.com/v3/"></script>
<script>
$(function() {
$('[name=checkout_confirmation]').attr('id','payment-form');
var stripe = Stripe('{$stripe_publishable_key}');
var elements = stripe.elements();
// Create an instance of the card Element.
var card = elements.create('card', {hidePostalCode: true});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
$('#payment-form').submit(function(event) {
var \$form = $(this);
// Disable the submit button to prevent repeated clicks
\$form.find('button').prop('disabled', true);
var selected = $("input[name='stripe_card']:checked"). val();
var cc_save = $('[name=card-save]').prop('checked');
try {
if ((selected != null && selected != '0') || cc_save) {
// update intent to use saved card, then process payment if successful
updatePaymentIntent(cc_save,selected);
} else {
// using new card details without save
processNewCardPayment();
}
} catch ( error ) {
\$form.find('.payment-errors').text(error);
}
// Prevent the form from submitting with the default action
return false;
});
if ( $('#stripe_table').length > 0 ) {
if ( typeof($('#stripe_table').parent().closest('table').attr('width')) == 'undefined' ) {
$('#stripe_table').parent().closest('table').attr('width', '100%');
}
$('#stripe_table .moduleRowExtra').hide();
$('#stripe_table_new_card').hide();
$('#card-element').prop('id','new-card-element');
$('#save-card-element').prop('id','card-element');
$('form[name="checkout_confirmation"] input[name="stripe_card"]').change(function() {
if ( $(this).val() == '0' ) {
stripeShowNewCardFields();
} else {
if ($('#stripe_table_new_card').is(':visible')) {
$('#card-element').prop('id','new-card-element');
$('#save-card-element').prop('id','card-element');
}
$('#stripe_table_new_card').hide();
}
$('tr[id^="stripe_card_"]').removeClass('moduleRowSelected');
$('#stripe_card_' + $(this).val()).addClass('moduleRowSelected');
});
$('form[name="checkout_confirmation"] input[name="stripe_card"]:first').prop('checked', true).trigger('change');
$('#stripe_table .moduleRow').hover(function() {
$(this).addClass('moduleRowOver');
}, function() {
$(this).removeClass('moduleRowOver');
}).click(function(event) {
var target = $(event.target);
if ( !target.is('input:radio')) {
$(this).find('input:radio').each(function() {
if ( $(this).prop('checked') == false ) {
$(this).prop('checked', true).trigger('change');
}
});
}
});
} else {
if ( typeof($('#stripe_table_new_card').parent().closest('table').attr('width')) == 'undefined' ) {
$('#stripe_table_new_card').parent().closest('table').attr('width', '100%');
}
}
function stripeShowNewCardFields() {
$('#card-element').attr('id','save-card-element');
$('#new-card-element').attr('id','card-element');
$('#stripe_table_new_card').show();
}
function updatePaymentIntent(cc_save,token){
// add card save option to payment intent, so card can be saved in webhook
// or customer/payment method if using saved card
$.getJSON( "{$intent_url}",{"id":$('#intent_id').val(),
"token":token,
"customer_id": $('#customer_id').val(),
"cc_save": cc_save},
function( data ) {
if (data.status == 'ok') {
var selected = $("input[name='stripe_card']:checked"). val();
if (selected == null || selected == '0') {
processNewCardPayment();
} else {
processSavedCardPayment(data.payment_method);
}
} else {
var \$form = $('#payment-form');
\$form.find('button').prop('disabled', false);
$('#card-errors').text(data.error);
}
});
}
function processNewCardPayment() {
stripe.handleCardPayment(
$('#secret').val(), card, {
payment_method_data: {
billing_details: {
name: $('#cardholder-name').val(),
address: {
city: $('#city').val(),
line1: $('#line1').val(),
postal_code: $('#postal_code').val(),
state: $('#state').val(),
country: $('#country').val()
},
email: $('#email_address').val()
}
}
}
).then(function(result) {
stripeResponseHandler(result);
});
}
function processSavedCardPayment(payment_method_id) {
stripe.handleCardPayment(
$('#secret').val(),
{
payment_method: payment_method_id
}
).then(function(result) {
stripeResponseHandler(result);
});
}
function stripeResponseHandler(result) {
var \$form = $('#payment-form');
if (result.error) {
$('#card-errors').text(result.error.message);
\$form.find('button').prop('disabled', false);
} else {
$('#card-errors').text('Processing');
// Insert the token into the form so it gets submitted to the server
\$form.append($('<input type="hidden" name="stripeIntentId" />').val(result.paymentIntent.id));
// and submit
\$form.get(0).submit();
}
}
});
</script>
EOD;
return $js;
}
注意:
$_POST['stripeToken']
是必不可少的,否则会产生错误 $_POST['stripeToken'] ??'';
PHP Fatal error: Uncaught (Status 400) (Request req_IX420AP8Wy1zL4) No such source: ''
thrown in /var/www/cl....../vendor/stripe/stripe-php/lib/Exception/ApiErrorException.php on line 38
HTML 代码
<form name="checkout" action="https://www.xxxxxxxxxxxxxxxxxxxxx.com/Process" method="post" id="payment-form" class="form-inline" role="form" onsubmit="return checkCheckBox(this)">
<div class="col-md-12">
<div class="separator"></div>
<div class="card moduleCheckoutConfirmationPaymentInformationCard">
<div class="card-header moduleCheckoutConfirmationPaymentInformationCardHeader"><strong>Paiement destiné à :</strong></div>
<div class="card-block moduleCheckoutConfirmationPaymentInformationCardBlock">
<div class="separator"></div>
<div class="col-sm-12">
<div class="">
Stripe paiement : Veuillez remplir les champs
<div class="separator"></div>
<input type="hidden" id="intent_id" value="pi_1I5SZvKZUkuP7mZSeaBMX7uN" /><input type="hidden" id="secret" value="pi_1I5SZvKZUkuP7mZSeaBMX7uN_secret_jbzEVl5gvWLdp1oXjByDylWwH" />
<div id="stripe_table_new_card">
<div class="form-group">
<label for="cardholder-name" class="control-label">Nom du propriétaire</label>
<div><input type="text" id="cardholder-name" class="form-control" value="xxxxxxxxxxxx" required="" /></div>
</div>
<div class="separator"></div>
<div class="form-group">
<label for="card-element" class="control-label">Type de carte</label>
<div id="card-element" class="col-md-5 StripeElement StripeElement--empty">
<div
class="__PrivateStripeElement"
style="margin: 0px !important; padding: 0px !important; border: none !important; display: block !important; background: transparent !important; position: relative !important; opacity: 1 !important;"
>
<iframe
frameborder="0"
allowtransparency="true"
scrolling="no"
name="__privateStripeFrame1055"
allowpaymentrequest="true"
src="https://js.stripe.com/v3/elements-inner-card-bcxxxxxxxxxxxxxaxxxxxxxxxxx.html#wait=false&hidePostalCode=true&rtl=false&componentName=card&keyMode=live&apiKey=pk_live_qlbcxxxxxxxxxxxxxaxxxxxxxxxxxjUOs5yndgxxxxxxxxxxx&origin=https%3A%2F%2Fwww.xxxxxxxx.com&referrer=https%3A%2F%2Fwww.xxxxxxxxxxx.com%2Findex.php%2FCheckout%2FConfirmation&controllerId=__privateStripeController1051"
title="Cadre de saisie sécurisé pour le paiement par carte"
style="
border: none !important;
margin: 0px !important;
padding: 0px !important;
width: 1px !important;
min-width: 100% !important;
overflow: hidden !important;
display: block !important;
user-select: none !important;
transform: translateZ(0px) !important;
height: 16.8px;
"
></iframe>
<input
class="__PrivateStripeElement-input"
aria-hidden="true"
aria-label=" "
autocomplete="false"
maxlength="1"
style="
border: none !important;
display: block !important;
position: absolute !important;
height: 1px !important;
top: 0px !important;
left: 0px !important;
padding: 0px !important;
margin: 0px !important;
width: 100% !important;
opacity: 0 !important;
background: transparent !important;
pointer-events: none !important;
font-size: 16px !important;
"
/>
</div>
</div>
</div>
<div id="card-errors" role="alert" class="messageStackError payment-errors"></div>
</div>
<input type="hidden" id="city" value="Montreal" /><input type="hidden" id="line1" value="7043 a rue xxxxxxxx" /><input type="hidden" id="line2" value="apt 8" /><input type="hidden" id="postal_code" value="H2SXXX" />
<input type="hidden" id="state" value="Quebec" /><input type="hidden" id="country" value="CA" /><input type="hidden" id="email_address" value="xxxxxxxxx@gmail.com" /><input type="hidden" id="customer_id" value="1" />
<style>
#stripe_table_new_card #card-element {
background-color: #fff;
padding: 6px 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
</style>
<script src="https://js.stripe.com/v3/"></script>
<script>
$(function () {
$("[name=checkout_confirmation]").attr("id", "payment-form");
var stripe = Stripe("pk_live_qlL9JUxxxxxxxxxxxxxxxxxxxxxxo");
var elements = stripe.elements();
var card = elements.create("card", { hidePostalCode: true });
card.mount("#card-element");
$("#payment-form").submit(function (event) {
var $form = $(this);
$form.find("button").prop("disabled", true);
var selected = $("input[name='stripe_card']:checked").val();
var cc_save = $("[name=card-save]").prop("checked");
try {
if ((selected != null && selected != "0") || cc_save) {
updatePaymentIntent(cc_save, selected);
} else {
processNewCardPayment();
}
} catch (error) {
$form.find(".payment-errors").text(error);
}
return false;
});
if ($("#stripe_table").length > 0) {
if (typeof $("#stripe_table").parent().closest("table").attr("width") == "undefined") {
$("#stripe_table").parent().closest("table").attr("width", "100%");
}
$("#stripe_table .moduleRowExtra").hide();
$("#stripe_table_new_card").hide();
$("#card-element").prop("id", "new-card-element");
$("#save-card-element").prop("id", "card-element");
$('form[name="checkout_confirmation"] input[name="stripe_card"]').change(function () {
if ($(this).val() == "0") {
stripeShowNewCardFields();
} else {
if ($("#stripe_table_new_card").is(":visible")) {
$("#card-element").prop("id", "new-card-element");
$("#save-card-element").prop("id", "card-element");
}
$("#stripe_table_new_card").hide();
}
$('tr[id^="stripe_card_"]').removeClass("moduleRowSelected");
$("#stripe_card_" + $(this).val()).addClass("moduleRowSelected");
});
$('form[name="checkout_confirmation"] input[name="stripe_card"]:first').prop("checked", true).trigger("change");
$("#stripe_table .moduleRow")
.hover(
function () {
$(this).addClass("moduleRowOver");
},
function () {
$(this).removeClass("moduleRowOver");
}
)
.click(function (event) {
var target = $(event.target);
if (!target.is("input:radio")) {
$(this)
.find("input:radio")
.each(function () {
if ($(this).prop("checked") == false) {
$(this).prop("checked", true).trigger("change");
}
});
}
});
} else {
if (typeof $("#stripe_table_new_card").parent().closest("table").attr("width") == "undefined") {
$("#stripe_table_new_card").parent().closest("table").attr("width", "100%");
}
}
function stripeShowNewCardFields() {
$("#card-element").attr("id", "save-card-element");
$("#new-card-element").attr("id", "card-element");
$("#stripe_table_new_card").show();
}
function updatePaymentIntent(cc_save, token) {
$.getJSON("", { id: $("#intent_id").val(), token: token, customer_id: $("#customer_id").val(), cc_save: cc_save }, function (data) {
if (data.status == "ok") {
var selected = $("input[name='stripe_card']:checked").val();
if (selected == null || selected == "0") {
processNewCardPayment();
} else {
processSavedCardPayment(data.payment_method);
}
} else {
var $form = $("#payment-form");
$form.find("button").prop("disabled", false);
$("#card-errors").text(data.error);
}
});
}
function processNewCardPayment() {
stripe
.handleCardPayment($("#secret").val(), card, {
payment_method_data: {
billing_details: {
name: $("#cardholder-name").val(),
address: { city: $("#city").val(), line1: $("#line1").val(), postal_code: $("#postal_code").val(), state: $("#state").val(), country: $("#country").val() },
email: $("#email_address").val(),
},
},
})
.then(function (result) {
stripeResponseHandler(result);
});
}
function processSavedCardPayment(payment_method_id) {
stripe.handleCardPayment($("#secret").val(), { payment_method: payment_method_id }).then(function (result) {
stripeResponseHandler(result);
});
}
function stripeResponseHandler(result) {
var $form = $("#payment-form");
if (result.error) {
$("#card-errors").text(result.error.message);
$form.find("button").prop("disabled", false);
} else {
$("#card-errors").text("Processing");
$form.append($('<input type="hidden" name="stripeIntentId"/>').val(result.paymentIntent.id));
$form.get(0).submit();
}
}
});
</script>
</div>
</div>
<table class="table moduleCheckoutConfirmationPaymentInformationCardTable"></table>
</div>
</div>
</div>
</form>