Итак, я создаю веб-приложение, в котором есть магазин с 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
}
},
- После ввода платежного адреса, адреса электронной почты и т. Д. Пользователь начинает оплату.
- Пользователь перенаправляется на страницу оплаты iDEAL, где он может авторизовать платеж.
- Источник создан. 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 должен отправить 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, как я бы сделал, если бы это был контроллер, но, если я правильно понимаю, задание выполняется асинхронно, поэтому я не могу вернуть данные. Я также новичок в Вакансиях, Очередях и тому подобном, я все еще пытаюсь осознать это.
Другой вариант, о котором я подумал, заключается в том, что я буду опрашивать запросы от внешнего интерфейса к бэкэнду, чтобы запросить последний заказ, но я понятия не имею, как это будет работать и / или является ли это хорошим решением.
Любая помощь / советы / полезные ресурсы будут очень благодарны!