我正在尝试将Stripe实现到我的MVC Core项目中,并收到此错误:“无此付款方式:pm_xxx”。我想接受同步付款。我在这里做错什么了吗?我已经能够将错误跟踪到paymentIntentService Create函数,并且该错误显示在局部视图中。
HTML:
<link rel="stylesheet" href="~/css/payment_client_global.css" />
<section>
<form id="payment-form" class="sr-payment-form">
<div class="sr-combo-inputs-row">
<div class="sr-input sr-card-element" id="card-element"></div>
</div>
<div class="sr-field-error" id="card-errors" role="alert"></div>
<button id="submit">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay</span><span id="order-amount"></span>
</button>
</form>
<div class="sr-result hidden">
<p>Payment completed<br /></p>
<pre>
<code></code>
</pre>
</div>
</section>
<script>
// A reference to Stripe.js
var stripe;
var orderData = {
items: [{ id: "prod_IFwyjFBhip0bTF" }],
currency: "usd"
};
// Disable the button until we have Stripe set up on the page
document.querySelector("button").disabled = true;
fetch("/stripe-key")
.then(function (result) {
return result.json();
})
.then(function (data) {
return setupElements(data);
})
.then(function ({ stripe, card, clientSecret }) {
document.querySelector("button").disabled = false;
var form = document.getElementById("payment-form");
form.addEventListener("submit", function (event) {
event.preventDefault();
pay(stripe, card, clientSecret);
});
});
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");
alert(data.clientSecret); //TEST
return {
stripe: stripe,
card: card,
clientSecret: data.clientSecret
};
};
var handleAction = function (clientSecret) {
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.error) {
showError(response.error);
} else if (response.requiresAction) {
// Request authentication
handleAction(response.clientSecret);
} else {
orderComplete(response.clientSecret);
}
});
};
/* ------- Post-payment helpers ------- */
/* Shows a success / error message when the payment is complete */
var orderComplete = function (clientSecret) {
stripe.retrievePaymentIntent(clientSecret).then(function (result) {
var paymentIntent = result.paymentIntent;
var paymentIntentJson = JSON.stringify(paymentIntent, null, 2);
document.querySelector(".sr-payment-form").classList.add("hidden");
document.querySelector("pre").textContent = paymentIntentJson;
document.querySelector(".sr-result").classList.remove("hidden");
setTimeout(function () {
document.querySelector(".sr-result").classList.add("expand");
}, 200);
changeLoadingState(false);
});
};
var showError = function (errorMsgText) {
changeLoadingState(false);
var errorMsg = document.querySelector(".sr-field-error");
errorMsg.textContent = errorMsgText;
setTimeout(function () {
errorMsg.textContent = "";
}, 4000);
};
// Show a spinner on payment submission
var changeLoadingState = function (isLoading) {
if (isLoading) {
document.querySelector("button").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.querySelector("button").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
};
</script>
控制器:
[Route("/pay")]
public class ConfirmPaymentController : Controller
{
public IActionResult Index([FromBody] ConfirmPaymentRequest request)
{
var paymentIntentService = new PaymentIntentService();
PaymentIntent paymentIntent = null;
try
{
if (request.PaymentMethodId != null)
{
// Create the PaymentIntent
var createOptions = new PaymentIntentCreateOptions
{
Amount = 1099,
Currency = "cad",
ConfirmationMethod = "manual",
PaymentMethodTypes = new List<string> { "card" },
PaymentMethod = request.PaymentMethodId,
Confirm = true,
};
paymentIntent = paymentIntentService.Create(createOptions);
}
else if (request.PaymentIntentId != null)
{
var confirmOptions = new PaymentIntentConfirmOptions { };
paymentIntent = paymentIntentService.Confirm(
request.PaymentIntentId,
confirmOptions
);
}
}
catch (StripeException e)
{
return Json(new { error = e.StripeError.Message });
}
return generatePaymentResponse(paymentIntent);
}
[HttpGet]
[Route("/stripe-key")]
public JsonResult StripeKey()
{
return new JsonResult(new StripeKeyResponse("[my pk_test here]"));
}
private IActionResult generatePaymentResponse(PaymentIntent intent)
{
// Note that if your API version is before 2019-02-11, 'requires_action'
// appears as 'requires_source_action'.
if (intent.Status == "requires_action" &&
intent.NextAction.Type == "use_stripe_sdk")
{
// Tell the client to handle the action
return Json(new
{
requires_action = true,
payment_intent_client_secret = intent.ClientSecret
});
}
else if (intent.Status == "succeeded")
{
// The payment didn’t need any additional actions and completed!
// Handle post-payment fulfillment
return Json(new { success = true });
}
else
{
// Invalid status
return StatusCode(500, new { error = "Invalid PaymentIntent status" });
}
}
}