/**
* Validates the incoming POST/GET response from the gateway to ensure it is
* legitimate and can be trusted.
*
* @param array $get The GET data for this request
* @param array $post The POST data for this request
* @return array An array of transaction data, sets any errors using Input if the data fails to validate
* - client_id The ID of the client that attempted the payment
* - amount The amount of the payment
* - currency The currency of the payment
* - invoices An array of invoices and the amount the payment should be applied to (if any) including:
* - id The ID of the invoice to apply to
* - amount The amount to apply to the invoice
* - status The status of the transaction (approved, declined, void, pending, reconciled, refunded, returned)
* - reference_id The reference ID for gateway-only use with this transaction (optional)
* - transaction_id The ID returned by the gateway to identify this transaction
* - parent_transaction_id The ID returned by the gateway to identify this
* transaction's original transaction (in the case of refunds)
*/
public function validate(array $get, array $post)
{
$api = $this->getApi($this->meta['client_id'], $this->meta['client_secret'], $this->meta['sandbox']);
$payments = new PaypalCheckoutPayments($api);
$payload = file_get_contents('php: $webhook = json_decode($payload);
$events = ['CHECKOUT.ORDER.APPROVED', 'PAYMENT.CAPTURE.COMPLETED'];
if (!in_array($webhook->event_type ?? '', $events)) {
$this->Input->setErrors(['unsupported_event' => ['unsupported_event' => 'Unsupported event type.']]);
return;
}
$this->log('validate', json_encode($webhook), 'input', !empty($webhook));
if ($webhook->event_type == 'CHECKOUT.ORDER.APPROVED') {
$orders = new PaypalCheckoutOrders($api);
$response = $orders->capture(['id' => $webhook->resource->id]);
$this->log('capture', json_encode($response->response()), 'output', empty($response->errors()));
if (($errors = $response->errors())) {
$this->Input->setErrors($errors);
return;
}
return [
'client_id' => $webhook->resource->purchase_units[0]->custom_id ?? null,
'amount' => $webhook->resource->purchase_units[0]->amount->value ?? null,
'currency' => $webhook->resource->purchase_units[0]->amount->currency_code ?? null,
'invoices' => $this->unserializeInvoices($webhook->resource->purchase_units[0]->reference_id ?? ''),
'status' => 'pending',
'reference_id' => null,
'transaction_id' => $webhook->resource->id ?? null,
'parent_transaction_id' => null
];
}
$payment = $webhook->resource ?? (object) [];
$order_response = (object) [];
$order = (object) [];
$transaction = (object) [];
if (isset($payment->supplementary_data->related_ids->order_id)) {
$orders = new PaypalCheckoutOrders($api);
$order_response = $orders->get(['id' => $payment->supplementary_data->related_ids->order_id]) ?? (object) [];
$order = $order_response->response();
$transaction = $order->purchase_units[0] ?? (object) [];
}
$this->log('validate', json_encode($transaction), 'output', !empty($transaction));
if (empty($transaction)) {
$this->Input->setErrors(['missing_transaction' => ['missing_transaction' => 'No transaction found.']]);
return;
}
$status = 'error';
$success = false;
switch ($payment->status ?? 'ERROR') {
case 'COMPLETED':
$status = 'approved';
$success = true;
break;
case 'APPROVED':
$status = 'pending';
$success = true;
break;
case 'VOIDED':
$status = 'void';
$success = true;
break;
}
if (!$success) {
return;
}
if (($errors = $order_response->errors())) {
$this->Input->setErrors($errors);
return;
}
return [
'client_id' => $transaction->custom_id ?? null,
'amount' => $payment->amount->value ?? null,
'currency' => $payment->amount->currency_code ?? null,
'invoices' => $this->unserializeInvoices($transaction->reference_id ?? ''),
'status' => $status,
'reference_id' => $payment->id ?? null,
'transaction_id' => $order->id ?? null,
'parent_transaction_id' => null
];
}