我终于通过支付意图API在Laravel中实现了新的Stripe支付元素。但是,我现在需要捕获有关支付的信息,并将它们存储在我的数据库中--具体来说,我需要以下数据:
所有这些信息似乎都可以在支付意向对象中获得,但是几个Stripe指南中没有一个指定如何在服务器上捕获它们。我想避免使用web挂钩,因为它们似乎对我已经检索的数据的抓取和持久化来说太过分了。
由于Stripe文档的AJAX/PHP解决方案是如何设置的,它也没有帮助这一点,因为它试图转储和销毁服务器端的任何变量,导致整个客户端流中断,停止支付表单的呈现并阻止任何调试信息。本质上,这使得支付意图API的整个实现无法在服务器上进行调试。
以前来过这里的人知道我会如何捕捉这些信息吗?
JavaScript/AJAX的相关部分:
const stripe = Stripe(<TEST_PUBLISHABLE_KEY>);
const fonts = [
{
cssSrc:
"https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap",
},
];
const appearance = {
theme: "stripe",
labels: "floating",
variables: {
colorText: "#2c2c2c",
fontFamily: "Open Sans, Segoe UI, sans-serif",
borderRadius: "4px",
},
};
let elements;
initialize();
checkStatus();
document
.querySelector("#payment-form")
.addEventListener("submit", handleSubmit);
// Fetches a payment intent and captures the client secret
async function initialize() {
const { clientSecret } = await fetch("/payment/stripe", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": document.querySelector('input[name="_token"]').value,
},
}).then((r) => r.json());
elements = stripe.elements({ fonts, appearance, clientSecret });
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
}
async function handleSubmit(e) {
e.preventDefault();
setLoading(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
// Make sure to change this to your payment completion page
return_url: "http://localhost.rc/success"
},
});
if (error.type === "card_error" || error.type === "validation_error") {
showMessage(error.message);
} else {
showMessage("An unexpected error occured.");
}
setLoading(false);
}
// Fetches the payment intent status after payment submission
async function checkStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);
if (!clientSecret) {
return;
}
const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);
switch (paymentIntent.status) {
case "succeeded":
showMessage("Payment succeeded!");
break;
case "processing":
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
showMessage("Your payment was not successful, please try again.");
break;
default:
showMessage("Something went wrong.");
break;
}
}路由文件:
Route::post('/payment/stripe', [TransactionController::class, "stripe"]);TransactionController:
public function stripe(Request $request) {
Stripe\Stripe::setApiKey(env(<TEST_SECRET_KEY>));
header('Content-Type: application/json');
try {
$paymentIntent = Stripe\PaymentIntent::create([
'amount' => 2.99,
'currency' => 'gbp',
'automatic_payment_methods' => [
'enabled' => true,
],
]);
$output = [
'clientSecret' => $paymentIntent->client_secret,
];
$this->storeStripe($paymentIntent, $output);
echo json_encode($output);
} catch (Stripe\Exception\CardException $e) {
echo 'Error code is:' . $e->getError()->code;
$paymentIntentId = $e->getError()->payment_intent->id;
$paymentIntent = Stripe\PaymentIntent::retrieve($paymentIntentId);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
}如何从我的数据库中存储的支付意图中获取上述信息?
发布于 2022-02-24 17:25:34
我知道你不会喜欢这个的,但我还是会说的。老实说,我认为实现webhook端点、侦听器和接收功能是最好的选择,原因如下:
Stripe支付意图捕获了支付的生命周期,因为它通过多个状态。因为Stripe之外的各种支付网络不能保证特定的响应时间,所以这些转换可以是异步的。
因此,除非您正在侦听payment_intent.succeeded事件,否则您无法确定何时是查询API是否已完成支付意图的适当时间。此外,在某些情况下,付款方法在初步处理后可能会被很好地拒绝(例如可疑的假卡等)。使用webhooks方法可以使您随时了解这些更改。
最后,虽然您可能只想将这些数据存储在DB now中,但范围确实会增加,并且尽早实现web钩子侦听器意味着,如果您需要采取其他的操作,那么您就可以准备好解决方案了。
发布于 2022-03-01 17:54:30
在RyanM的推荐下,我选择了web钩子解决方案,这比我预期的使用斯帕特氏条纹韦氏钩子包要容易得多(尽管它似乎是由一个更关心关闭问题而不是修复潜在bug的人运行的,所以选择Stripe收银员可能会更容易,也可能是一个更愉快的开发体验)。
注意,默认情况下,Stripe webhooks返回一个事件对象,该对象本身包含与事件相关的其他对象,例如,用于payment_intent.succeeded的payment_intent.succeeded和任何相关的计费对象。因此,有必要向下钻一点,以获取所需的所有信息。
$paymentIntent = $this->webhookCall->payload["data"]["object"];
$paymentID = $this->webhookCall->payload["data"]["object"]["id"]; // Transaction ID
$charge = $this->webhookCall->payload["data"]["object"]["charges"]["data"][0];
$transaction = Transaction::where("gateway_payment_id", $paymentID)->first();
$transaction->payment_status = strtoupper($paymentIntent["status"]); // Payment status
$transaction->payment_method = $charge["payment_method_details"]["type"]; // Payment method
$transaction->amount = ($paymentIntent["amount_received"]/100); // Amount charged, in pounds
$transaction->currency = strtoupper($paymentIntent["currency"]); // Currency charged in
$transaction->postcode = $charge["billing_details"]["address"]["postal_code"] ?? "N/A"; // Postcode if entered by the user - otherwise default to N/Ahttps://stackoverflow.com/questions/71255423
复制相似问题