Уведомить веб-интерфейс Vue SPA, если заряд Stripe (iDEAL) успешно завершен с помощью Webhooks и Jobs Laravel

Итак, я создаю веб-приложение, в котором есть магазин с Laravel API и Vue в качестве внешнего интерфейса SPA.

Я пытался использовать Strip для включения платежей. Пока что с помощью документации Stripe мне удалось создать исходный код во внешнем интерфейсе. для iDEAL Stripe настоятельно рекомендует нам использовать веб-перехватчики, чтобы подтвердить успешность платежа. (Я использую пакет Spatie / Laravel-Stripe-Webhook) Это текущий поток моего веб-приложения:

Checkout.vue:

    checkout() {

        const sourceData = {
            type: 'ideal',
            amount: this.cart.total,
            currency: 'eur',
            owner: {
                name: this.name + ' ' + this.last_name,
                email: this.email,
            },
            metadata: {
                order: JSON.stringify(order),
                total_quantity: this.cart.total_quantity,
            },
            redirect: {
                return_url: 'http://example.test/order-confirmation',
            },
        }

        this.stripe.createSource(this.ideal, sourceData).then(function(result) {
            if (result.error) {
                console.log(error.message)
                this.error = error.message
            } else {
                stripeSourceHandler(result.source)
            }
        })

        const stripeSourceHandler = source => {
            document.location.href = source.redirect.url
        }

    },
  1. После ввода платежного адреса, адреса электронной почты и т. Д. Пользователь начинает оплату.
  2. Пользователь перенаправляется на страницу оплаты iDEAL, где он может авторизовать платеж.
  3. Источник создан. Stripe отправляет source.chargeable webhook:

config / stripe-webhooks.php:

    'jobs' => [
        'source_chargeable' => \App\Jobs\StripeWebhooks\ProcessPaymentsJob::class,
        'charge_succeeded' => \App\Jobs\StripeWebhooks\ChargeSucceededJob::class,
    ],

ProcessPaymentsJob.php:

public function __construct(WebhookCall $webhookCall)
{
    $this->webhookCall = $webhookCall;
}

public function handle()
{
    $charge = $this->webhookCall->payload['data']['object'];

    \Stripe\Stripe::setApiKey(config('services.stripe.secret'));

    $user = '';

    if(User::find(Auth::id())) {
        $user = $user->name;
    } else {
        $user = 'a guest';
    }

    $payment = \Stripe\Charge::create([
        'amount' => $charge['amount'],
        'currency' => 'eur',
        'source' => $charge['id'],
        'description' => 'New payment from '. $user,
        'metadata' => [
            'order' => $charge['metadata']['order'],
            'total_quantity' => $charge['metadata']['total_quantity'],
        ]
    ]);

}
  1. Пользователь возвращается к redirect[return_url]
  2. Если все прошло хорошо, Stripe должен отправить charge.succeeded webhook:

ChargeSucceededJob.php:

public function __construct(WebhookCall $webhookCall)
{
    $this->webhookCall = $webhookCall;
}

public function handle()
{
$charge = $this->webhookCall->payload['data']['object'];

$order = Order::create([
    'user_id' => Auth::id() ?? null,
    'payment_id' => $charge['id'],
    'payment_method' => $charge['payment_method_details']['type'],
    'billing_email' => $charge['billing_details']['email'],
    'billing_name' => $charge['metadata']['name'],
    'billing_last_name' => $charge['metadata']['last_name'],
    'billing_address' => $charge['metadata']['address'],
    'billing_address_number' => $charge['metadata']['address_num'],
    'billing_postal_code' => $charge['metadata']['postal_code'],
    'billing_city' => $charge['metadata']['city'],
    'billing_phone' => strval($charge['billing_details']['phone']),
    'order' => json_decode($charge['metadata']['order']),
    'total_quantity' => (int) $charge['metadata']['total_quantity'],
    'billing_total' => $charge['amount'],
]);
}

Все идет хорошо. Однако я не знаю, как уведомить клиента (на веб-интерфейсе) о том, что заказ выполнен. В документации Stripe объясняется, как получить Источник на странице подтверждения заказа, но они не объясняют, как получить Charge, потому что это то, что определяет, был ли выполнен весь заказ или нет.

OrderConfirmation.vue:

    checkPaymentStatus() {
        this.stripe = Stripe(this.stripeKey)

        // After some amount of time, we should stop trying to resolve the order synchronously:
        const MAX_POLL_COUNT = 10;
        let pollCount = 0;

        let params = new URLSearchParams(location.search)

        const pollForSourceStatus = async () => {
            const { source } = await this.stripe.retrieveSource({id: params.get('source'), client_secret: params.get('client_secret')})
            if (source.status === 'chargeable') {
                // Make a request to your server to charge the Source.
                // Depending on the Charge status, show your customer the relevant message.
            } else if (source.status === 'pending' && pollCount < MAX_POLL_COUNT) {
                // Try again in a second, if the Source is still `pending`:
                pollCount += 1;
                setTimeout(pollForSourceStatus, 1000);
            } else {
                // Depending on the Source status, show your customer the relevant message.
            }
        };

        pollForSourceStatus();
    }

Как мне отсюда уйти? Я пытаюсь уведомить интерфейс, когда заряд был успешным. Мой первоначальный мыслительный процесс заключался в том, чтобы просто вернуть объект Order, как я бы сделал, если бы это был контроллер, но, если я правильно понимаю, задание выполняется асинхронно, поэтому я не могу вернуть данные. Я также новичок в Вакансиях, Очередях и тому подобном, я все еще пытаюсь осознать это.

Другой вариант, о котором я подумал, заключается в том, что я буду опрашивать запросы от внешнего интерфейса к бэкэнду, чтобы запросить последний заказ, но я понятия не имею, как это будет работать и / или является ли это хорошим решением.

Любая помощь / советы / полезные ресурсы будут очень благодарны!


person pu4cu    schedule 28.04.2020    source источник


Ответы (1)


Платежи iDEAL асинхронны, но, к счастью, они сразу же уведомляют вас, был ли платеж успешным или нет.

Когда процесс iDEAL будет завершен и ваш пользователь будет перенаправлен на ваш сайт, Stripe автоматически добавляет некоторые параметры запроса в URL. Это означает, что ваши пользователи будут перенаправлены на что-то вроде:

https://example.com/checkout/complete?payment_intent=pi_123&payment_intent_client_secret=pi_123_secret_456&source_type=ideal

Следующим шагом будет получение PaymentIntent и проверка его статуса. , что вы можете сделать:

  1. Получение PaymentIntent на клиенте с использованием stripe.js и секрета клиента PaymentIntent: https://stripe.com/docs/js/payment_intents/retrieve_payment_intent
  2. Получение PaymentIntent на сервере путем отправки запроса ajax на ваш сервер с идентификатором PaymentIntend: https://stripe.com/docs/api/payment_intents/retrieve

Если статус succeeded, значит, платеж был завершен, и вы можете продолжить.

person Paul Asjes    schedule 29.04.2020
comment
Хм, хорошо. Просто проверил документы еще раз, и, похоже, я следил за их API источников, а не за их API методов оплаты. Мне придется взглянуть на это еще раз. - person pu4cu; 29.04.2020