首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从Stripe支付元素中获取支付数据

如何从Stripe支付元素中获取支付数据
EN

Stack Overflow用户
提问于 2022-02-24 16:46:33
回答 2查看 633关注 0票数 0

我终于通过支付意图API在Laravel中实现了新的Stripe支付元素。但是,我现在需要捕获有关支付的信息,并将它们存储在我的数据库中--具体来说,我需要以下数据:

  • 交易ID
  • 付款状态(失败/待决/成功等)
  • 支付方式类型(卡片/Google Pay/Apple Pay/等)
  • 实际向客户收取的金额
  • 客户实际支付的货币
  • 用户在付款表格中输入的邮政编码。

所有这些信息似乎都可以在支付意向对象中获得,但是几个Stripe指南中没有一个指定如何在服务器上捕获它们。我想避免使用web挂钩,因为它们似乎对我已经检索的数据的抓取和持久化来说太过分了。

由于Stripe文档的AJAX/PHP解决方案是如何设置的,它也没有帮助这一点,因为它试图转储和销毁服务器端的任何变量,导致整个客户端流中断,停止支付表单的呈现并阻止任何调试信息。本质上,这使得支付意图API的整个实现无法在服务器上进行调试。

以前来过这里的人知道我会如何捕捉这些信息吗?

JavaScript/AJAX的相关部分:

代码语言:javascript
复制
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;
    }
}

路由文件:

代码语言:javascript
复制
Route::post('/payment/stripe', [TransactionController::class, "stripe"]);

TransactionController:

代码语言:javascript
复制
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()]);

    }
}

如何从我的数据库中存储的支付意图中获取上述信息?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-02-24 17:25:34

我知道你不会喜欢这个的,但我还是会说的。老实说,我认为实现webhook端点、侦听器和接收功能是最好的选择,原因如下:

Stripe支付意图捕获了支付的生命周期,因为它通过多个状态。因为Stripe之外的各种支付网络不能保证特定的响应时间,所以这些转换可以是异步的。

因此,除非您正在侦听payment_intent.succeeded事件,否则您无法确定何时是查询API是否已完成支付意图的适当时间。此外,在某些情况下,付款方法在初步处理后可能会被很好地拒绝(例如可疑的假卡等)。使用webhooks方法可以使您随时了解这些更改。

最后,虽然您可能只想将这些数据存储在DB now中,但范围确实会增加,并且尽早实现web钩子侦听器意味着,如果您需要采取其他的操作,那么您就可以准备好解决方案了。

  • 向客户发送电子邮件通知
  • 调整收入调节
  • 处理履行动作
  • 其他东西.
票数 3
EN

Stack Overflow用户

发布于 2022-03-01 17:54:30

在RyanM的推荐下,我选择了web钩子解决方案,这比我预期的使用斯帕特氏条纹韦氏钩子包要容易得多(尽管它似乎是由一个更关心关闭问题而不是修复潜在bug的人运行的,所以选择Stripe收银员可能会更容易,也可能是一个更愉快的开发体验)。

注意,默认情况下,Stripe webhooks返回一个事件对象,该对象本身包含与事件相关的其他对象,例如,用于payment_intent.succeeded的payment_intent.succeeded和任何相关的计费对象。因此,有必要向下钻一点,以获取所需的所有信息。

代码语言:javascript
复制
$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/A
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71255423

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档