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

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

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

Оформление заказа. 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. После заполнение платежного адреса, электронных писем и пр. c. пользователь начинает платеж.
  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'],
        ]
    ]);

}
Пользователь возвращается к redirect[return_url] Если все прошло хорошо, Stripe должен отправить обвинение .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 они объясняют, как получить Источник на странице подтверждения заказа, но не объясняют, как получить Сбор, потому что именно это определяет, был ли весь заказ выполнен или нет.

Подтверждение заказа. 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();
    }

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

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

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

1 Ответ

0 голосов
/ 29 апреля 2020

Платежи 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 на клиенте с использованием полосы. js и секретного ключа PaymentIntent клиента: https://stripe.com/docs/js/payment_intents/retrieve_payment_intent
  2. Получение PaymentIntent на сервер, отправив запрос ajax на ваш бэкэнд с ID PaymentIntend: https://stripe.com/docs/api/payment_intents/retrieve

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

...