diff --git a/REVOLUT_IMPLEMENTATION.md b/REVOLUT_IMPLEMENTATION.md new file mode 100644 index 0000000..d25547a --- /dev/null +++ b/REVOLUT_IMPLEMENTATION.md @@ -0,0 +1,338 @@ +# Revolut Payment Integration Guide + +This guide explains how to implement Revolut payments using the unusualify/payable package. + +## Prerequisites + +1. Revolut Merchant Account +2. API credentials from Revolut dashboard +3. `unusualify/payable` package installed +4. `@revolut/checkout` npm package for frontend + +## Installation + +1. Install the npm package: +```bash +npm install @revolut/checkout +``` + +## Backend Implementation + +### 1. Controller Method + +Create a controller method to handle the payment initialization: + +```php +public function testRevolut() +{ + $payable = new Payable('revolut'); + + $params = [ + 'amount' => 10.00, // Amount in major units (e.g., 10.00 EUR) + 'currency' => 'EUR', // Currency code (e.g., EUR, USD, GBP) + 'order_id' => 'ORDER-'.uniqid(), // Unique order ID + 'user_email' => 'customer@example.com', + 'user_id' => 1, + 'installment' => 1, // Number of installments (1 for one-time payment) + 'user_ip' => request()->ip(), + 'description' => 'Order description', + ]; + + $result = $payable->pay($params); + + if (($result['type'] ?? null) === 'widget') { + return view('checkout.revolut', [ + 'token' => $result['token'] ?? '', + 'env' => $result['env'] ?? 'sandbox', + ]); + } + + abort(400, $result['message'] ?? 'Unable to initialize Revolut order'); +} +``` + +## Frontend Implementation + +### 1. Vue Component Implementation + +Create a new Vue component at `resources/js/Components/RevolutCheckout.vue`: + +```vue + + + + + +``` + +#### Usage in your Vue application: + +1. First, import and register the component: + +```javascript +// In your app.js or main.js +import RevolutCheckout from './Components/RevolutCheckout.vue'; + +// If using Vue 3 +app.component('RevolutCheckout', RevolutCheckout); + +// If using Vue 2 +// Vue.component('RevolutCheckout', RevolutCheckout); +``` + +2. Use the component in your view: + +```vue + + + +``` + +### 2. Blade Template (Alternative to Vue) (`resources/views/checkout/revolut.blade.php`) + +```html + + + + + + Revolut Checkout + + + +
+

Revolut Checkout

+ + + + + +
+
+ +
+
+ + + + + @vite(['resources/js/revolut.js']) + + +``` + +### 2. JavaScript (`resources/js/revolut.js`) + +```javascript +import RevolutCheckout from '@revolut/checkout'; + +document.addEventListener('DOMContentLoaded', async () => { + const token = document.querySelector('input[name="token"]').value; + const env = document.querySelector('input[name="env"]').value; + + if (!token) { + console.error('Revolut token missing.'); + return; + } + + const loader = document.getElementById('revolut-loader'); + const showLoader = () => { loader.style.display = 'flex'; }; + const hideLoader = () => { loader.style.display = 'none'; }; + + const setButtonBusy = (btn, busy) => { + if (!btn) return; + if (busy) { + btn.disabled = true; + if (!btn.dataset.originalText) btn.dataset.originalText = btn.textContent; + btn.textContent = 'Processing...'; + btn.setAttribute('aria-busy', 'true'); + } else { + btn.disabled = false; + btn.textContent = btn.dataset.originalText || 'Pay'; + btn.removeAttribute('aria-busy'); + } + }; + + try { + const instance = await RevolutCheckout(token, env); + const cardTarget = document.getElementById('card-field'); + + if (cardTarget) { + const submitBtn = document.getElementById('button-submit'); + + const cardField = instance.createCardField({ + target: cardTarget, + onSuccess() { + hideLoader(); + setButtonBusy(submitBtn, false); + // Handle successful payment (e.g., redirect to success page) + window.location.href = '/payment/success'; + }, + onError(error) { + hideLoader(); + setButtonBusy(submitBtn, false); + alert(`Payment failed: ${error.message || 'Unknown error'}`); + }, + }); + + if (submitBtn) { + submitBtn.addEventListener('click', () => { + const nameInput = document.querySelector('input[name="cardholder-name"]'); + const cardholderName = (nameInput && nameInput.value) ? nameInput.value : ''; + const meta = { name: cardholderName, cardholderName }; + + showLoader(); + setButtonBusy(submitBtn, true); + cardField.submit(meta); + }); + } + } + } catch (e) { + console.error('Failed to initialize Revolut', e); + alert('Failed to initialize payment: ' + (e?.message || e)); + } +}); +``` + +## Configuration + +Make sure to set up your Revolut API credentials in your `.env` file: + +```env +REVOLUT_ENV=sandbox # or 'production' for live +REVOLUT_PUBLIC_KEY=your_public_key +REVOLUT_SECRET_KEY=your_secret_key +``` diff --git a/config/payable.php b/config/payable.php index d6c67d0..4efeb34 100644 --- a/config/payable.php +++ b/config/payable.php @@ -132,5 +132,19 @@ 'secret_key' => env('BUCKAROO_LIVE_SECRET_KEY', ''), ], ], + 'revolut' => [ + 'mode' => env('REVOLUT_MODE', 'sandbox'), + 'api_version' => env('REVOLUT_API_VERSION', '2024-05-01'), + 'sandbox' => [ + 'api_url' => env('REVOLUT_SANDBOX_API_URL', ''), + 'public_key' => env('REVOLUT_SANDBOX_PUBLIC_KEY', ''), + 'secret_key' => env('REVOLUT_SANDBOX_SECRET_KEY', ''), + ], + 'live' => [ + 'api_url' => env('REVOLUT_LIVE_API_URL', ''), + 'public_key' => env('REVOLUT_LIVE_PUBLIC_KEY', ''), + 'secret_key' => env('REVOLUT_LIVE_SECRET_KEY', ''), + ], + ], ], ]; diff --git a/src/Contracts/ShouldEmbedForm.php b/src/Contracts/ShouldEmbedForm.php new file mode 100644 index 0000000..a535050 --- /dev/null +++ b/src/Contracts/ShouldEmbedForm.php @@ -0,0 +1,30 @@ + 1000, + 'amount' => 1, 'installment' => 1, 'currency' => 'TRY', 'locale' => 'tr', - 'order_id' => 'TEST-'.uniqid(), - 'card_name' => 'John Doe', + 'order_id' => 'TEST-' . uniqid(), + 'card_name' => 'Ramazan Ayyildiz', + 'card_no' => '4912055018403926', 'company_name' => 'B2Press', - 'card_no' => '9792290735587016', - 'card_month' => '02', - 'card_year' => '2026', - 'card_cvv' => '790', + 'card_month' => '03', + 'card_year' => '2029', + 'card_cvv' => '659', 'user_email' => 'test@example.com', 'user_ip' => request()->ip(), ]; - + return $payable->pay($params); } public function testTebCommon() { $payable = new Payable('teb-common-pos'); - + $params = [ 'paid_price' => 1, 'installment' => 1, 'currency' => 'TRY', 'locale' => 'tr', - 'order_id' => 'TEST-'.uniqid(), + 'order_id' => 'TEST-' . uniqid(), 'card_name' => 'Ramazan Ayyildiz', 'card_no' => '4912055018403926', 'company_name' => 'B2Press', @@ -49,39 +48,39 @@ public function testTebCommon() 'user_email' => 'test@example.com', 'user_ip' => request()->ip(), ]; - + return $payable->pay($params); } public function testPaypal() { $payable = new Payable('paypal'); - + $params = [ 'paid_price' => 100.10, 'installment' => 1, 'currency' => 'USD', - 'order_id' => 'TEST-'.uniqid(), + 'order_id' => 'TEST-' . uniqid(), 'user_email' => 'test@example.com', 'user_name' => 'John', 'user_surname' => 'Doe', 'user_ip' => request()->ip(), 'company_name' => 'B2Press', - 'locale' => 'tr-TR', + 'locale' => 'tr-TR' ]; - + return $payable->pay($params); } public function testPaypalRefund() { $payable = new Payable('paypal'); - + $params = [ /* 'capture_id' => '5JC53758C94870609', */ - 'payment_id' => 17, + 'payment_id' =>17, ]; - + $response = $payable->refund($params); dd($response); } @@ -89,12 +88,12 @@ public function testPaypalRefund() public function testPaypalCancel() { $payable = new Payable('paypal'); - + $params = [ 'authorization_id' => ' ', 'payment_id' => 7, ]; - + $response = $payable->cancel($params); dd($response); } @@ -102,57 +101,85 @@ public function testPaypalCancel() public function testIdeal() { $payable = new Payable('ideal'); - + $params = [ 'paid_price' => 100.10, 'installment' => 1, - 'currency' => 'USD', + 'currency' => 'EUR', 'issuer' => 'ABNANL2A', - 'order_id' => 'TEST-'.uniqid(), + 'order_id' => 'TEST-' . uniqid(), 'user_email' => 'test@example.com', 'user_ip' => request()->ip(), ]; - + return $payable->pay($params); } public function testIdealQr() { $payable = new Payable('ideal-qr'); - + $params = [ 'paid_price' => 100.10, 'installment' => 1, 'currency' => 'USD', 'issuer' => 'ABNANL2A', - 'order_id' => 'TEST'.uniqid(), + 'order_id' => 'TEST' . uniqid(), 'user_email' => 'test@example.com', - 'description' => 'Test purchase', + 'description' => 'Test Payment', 'user_ip' => request()->ip(), ]; - - $qrimageurl = $payable->pay($params); - + + $qrimageurl= $payable->pay($params); return ''; } public function testIdealRefund() { $payable = new Payable('ideal'); - + $params = [ /* 'order_id' => 'TEST-6814ef7229c4b', 'transaction_key' => '89819DD62261406A942D1FA029835852', 'paid_price' => 100.10, */ 'payment_id' => 16, ]; - + $response = $payable->refund($params); dd($response); } + public function handleResponse(Request $request) { dd($request->all()); } -} + + public function testRevolut() + { + $payable = new Payable('revolut'); + + $params = [ + // Use either 'paid_price' (major units) or 'amount' (minor units) + 'amount' => 10.00, + 'currency' => 'EUR', + 'order_id' => 'ORDER-'.uniqid(), + 'user_email' => 'john@example.com', + 'user_id' => 1, + 'installment' => 1, + 'user_ip' => request()->ip(), + 'description' => 'Test Revolut payment', + ]; + + $result = $payable->pay($params); + + if (($result['type'] ?? null) === 'widget') { + return view('checkout.revolut', [ + 'token' => $result['token'] ?? '', + 'env' => $result['env'] ?? 'sandbox', + ]); + } + + abort(400, $result['message'] ?? 'Unable to initialize Revolut order'); + } +} \ No newline at end of file diff --git a/src/Payable.php b/src/Payable.php index 7fb9af3..e7357f7 100644 --- a/src/Payable.php +++ b/src/Payable.php @@ -96,6 +96,21 @@ public function pay($payload, $paymentPayload = []) ->pay($payload, $paymentPayload); } + public function checkout($payload, $paymentPayload = []) + { + $validated = $this->validatePayload($payload); + + $payload = array_merge_recursive_preserve($this->getPayloadSchema(), $payload); + + $payload = $this->removeExceptional($payload); + + $payment = $this->createPaymentRecord($payload, $paymentPayload); + + return $this->service + ->setPayment($payment) + ->checkout($payload); + } + /** * Cancel Payment * @@ -236,7 +251,6 @@ public function createPaymentRecord($payload, $paymentAttributes = []) 'order_id' => $payload['order_id'], 'payment_gateway' => $this->slug, 'status' => $this->statusEnum::PENDING, - 'parameters' => Arr::except($payload, [ 'user_email', 'installment', diff --git a/src/Services/PaymentService.php b/src/Services/PaymentService.php index 67d9f0d..55d783d 100644 --- a/src/Services/PaymentService.php +++ b/src/Services/PaymentService.php @@ -3,6 +3,7 @@ namespace Unusualify\Payable\Services; use Illuminate\Support\Str; +use Unusualify\Payable\Contracts\ShouldEmbedForm; abstract class PaymentService extends URequest { @@ -104,6 +105,13 @@ abstract class PaymentService extends URequest */ public static $hasCancel = false; + /** + * Service + * + * @var string + */ + public static $hasBuiltInForm = false; + public const STATUS_PENDING = 'PENDING'; public const STATUS_COMPLETED = 'COMPLETED'; @@ -218,6 +226,19 @@ public function getStatusEnum() return $this->statusEnum; } + /** + * Check if the service has a built-in form and implements the ShouldEmbedForm contract + * + * @return bool + */ + public static function hasBuiltInForm() + { + $implements = class_implements(static::class); + + return (static::$hasBuiltInForm ?? false) + && in_array(ShouldEmbedForm::class, $implements); + } + public function addQueryParameters($url, $payload = []) { $url_parts = parse_url($url); @@ -359,6 +380,26 @@ public static function hasCancel($payload = null) return static::$hasCancel && (method_exists(static::class, 'isCancellable') ? (new static)->isCancellable($payload) : true); } + public function checkout(array $payload) + { + if($this->hasBuiltInForm()) { + $validated = $this->validateCheckoutPayload($payload); + + if($validated !== true) { + return response()->json([ + 'status' => 'error', + 'message' => $validated, + ], 403); + } + + $payload = $this->hydrateCheckoutPayload($payload); + + return $this->getBuiltInFormAttributes($payload); + } + + return []; + } + /** * Validate Refund * diff --git a/src/Services/RevolutService.php b/src/Services/RevolutService.php new file mode 100644 index 0000000..4dad4cf --- /dev/null +++ b/src/Services/RevolutService.php @@ -0,0 +1,409 @@ +setConfig(); + } + + /** + * Load config + * + */ + public function setConfig() + { + $this->config = config($this->getConfigName()); // e.g. 'payable.revolut' + $this->setMode($this->config['mode'] ?? 'sandbox'); + + $modeCfg = $this->config[$this->mode] ?? []; + $this->url = rtrim($modeCfg['api_url'] ?? '', '/'); + $this->secretKey = $modeCfg['secret_key'] ?? null; + $this->publicKey = $modeCfg['public_key'] ?? null; // not required for this flow + $this->apiVersion = $this->config['api_version'] ?? null; + + $this->headers = [ + 'Authorization' => 'Bearer '.$this->secretKey, + 'Revolut-Api-Version' => $this->apiVersion, + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]; + $this->setHeaders($this->headers); + + return $this; + } + + /** Minimal validation for widget flow */ + public function validateCheckoutPayload(array $payload) + { + $required = ['order_id', 'currency']; + $missing = array_diff($required, array_keys($payload)); + + if (!empty($missing)) { + return 'These keys are missing for Revolut: '.implode(', ', $missing); + } + + return true; + } + + public function hydrateCheckoutPayload(array $payload): array + { + $amountMinor = $this->normalizeAmountMinor($payload); + + return [ + 'amount' => $amountMinor, + 'currency' => $payload['currency'] ?? 'EUR', + 'merchant_order_ext_ref' => $payload['order_id'], + 'merchant_customer_ext_ref' => $payload['user_id'] ?? null, + 'description' => $payload['description'] ?? ('Payment for order '.$payload['order_id']), + 'customer' => [ + 'email' => $payload['user_email'] ?? null, + ], + 'metadata' => [ + 'order_id' => $payload['order_id'], + 'user_email' => $payload['user_email'] ?? null, + 'ip' => $payload['user_ip'] ?? null, + ], + // Optional: 'capture_mode' => 'automatic' | 'manual' + ]; + } + + /** Convert to minor units */ + protected function normalizeAmountMinor(array $params): int + { + if (isset($params['amount'])) return (int) $params['amount']; // minor + if (isset($params['price'])) return (int) $params['price']; // minor (your package) + if (isset($params['paid_price'])) return (int) round(((float) $params['paid_price']) * 100); // major→minor + return 0; + } + + /** Build Create Order payload */ + public function hydrateParams(array $params): array + { + return []; + } + + /** POST /orders */ + protected function createRevolutOrder(array $payload): array + { + $resp = $this->postReq( + $this->url, + '/orders', + $payload, + $this->headers, + 'json', + $this->mode + ); + + return is_string($resp) ? (array) json_decode($resp, true) : (array) $resp; + } + + /** GET /orders/{id} (optional UX or webhook confirm) */ + protected function retrieveRevolutOrder(string $orderId): array + { + $resp = $this->getReq( + $this->url, + '/orders/'.urlencode($orderId), + [], + $this->headers + ); + + return is_string($resp) ? (array) json_decode($resp, true) : (array) $resp; + } + + /** + * Main entry for Card Field / Card Pop-up. + * Creates the order and returns data your JS embed will use. + */ + public function createWidgetOrder_(array $params): array + { + $validated = $this->validateParams($params); + + if ($validated !== true) return ['error' => $validated]; + + $payload = $this->hydrateParams($params); + $revolutOrder = $this->createRevolutOrder($payload); + + // Persist PENDING with raw provider response + $this->payment?->update([ + 'status' => $this->getStatusEnum()::PENDING, + 'response' => $revolutOrder, + ]); + + dd($this->payment, $revolutOrder); + + return [ + 'token' => $revolutOrder['token'] ?? null, // REQUIRED by RevolutCheckout() + 'order_id' => $revolutOrder['id'] ?? null, + 'env' => $this->mode === 'live' ? 'prod' : 'sandbox', + 'amount' => $payload['amount'] ?? null, + 'currency' => $payload['currency'] ?? null, + 'email' => $payload['customer']['email'] ?? null, + ]; + } + + public function getBuiltInFormAttributes(array $payload): array + { + $revolutOrder = $this->createRevolutOrder($payload); + + $this->payment?->update([ + 'status' => $this->getStatusEnum()::PENDING, + 'response' => $revolutOrder, + ]); + + return [ + 'token' => $revolutOrder['token'] ?? null, // REQUIRED by RevolutCheckout() + 'paymentId' => $this->payment->id ?? null, + 'orderId' => $this->payment->order_id ?? null, + 'revolutOrderId' => $revolutOrder['id'] ?? null, + 'env' => $this->mode === 'live' ? 'prod' : 'sandbox', + 'amount' => $payload['amount'] ?? null, + 'currency' => $payload['currency'] ?? null, + 'email' => $payload['customer']['email'] ?? null, + ]; + } + /** + * Optional: keep pay() compatible — just return directive for widget flow. + * Your controller/UI should call createWidgetOrder() and then run the JS. + */ + public function pay(array $params) + { + $data = $this->createWidgetOrder($params); + + if (!empty($data['token'])) { + return response()->json([ + 'type' => 'widget', + 'order_id' => $data['order_id'], + 'token' => $data['token'], + 'env' => $data['env'], + 'message' => 'Use Card Field or Pop-up with RevolutCheckout(token, env).', + ]); + // return [ + // 'type' => 'widget', + // 'order_id' => $data['order_id'], + // 'token' => $data['token'], + // 'env' => $data['env'], + // 'message' => 'Use Card Field or Pop-up with RevolutCheckout(token, env).', + // ]; + } + + return ['type' => 'error', 'message' => $data['error'] ?? 'Unable to initialize Revolut order']; + } + + /** Return URL — UX only; don’t finalize here */ + public function handleResponse(HttpRequest $request) + { + $q = $request->query(); + + $this->payment?->update([ + 'status' => $this->getStatusEnum()::PENDING, + 'response' => $q, + ]); + + $orderId = $q['order_id'] ?? null; + $order = $orderId ? $this->retrieveOrder($orderId) : null; + + $payload = [ + 'id' => $q['payment_id'] ?? ($this->payment->id ?? null), + 'status' => self::RESPONSE_STATUS_SUCCESS, // means "return handled" + 'payment_service' => $q['payment_service'] ?? $this->service, + 'token' => $q['token'] ?? '', + 'order_id' => $order['id'] ?? $orderId, + 'order_data' => $order ?: $q, + ]; + + return $this->generatePostForm($payload, $this->payableReturnUrl); + } + + /** Webhook — source of truth (COMPLETED/FAILED/CANCELLED/AUTHORISED) */ + public function handleWebhook(HttpRequest $request) + { + $payload = $request->all(); + + $orderId = $payload['order']['id'] + ?? $payload['order_id'] + ?? $payload['merchant_order_ext_ref'] + ?? null; + + $rawState = $payload['order']['state'] + ?? $payload['state'] + ?? $payload['status'] + ?? null; + + if (!$orderId) { + return response()->json(['status' => 'ignored', 'reason' => 'missing order id'], 202); + } + + // Optional: re-fetch to confirm latest state + $order = $this->retrieveOrder($orderId); + $finalState = strtoupper($order['state'] ?? ($rawState ? strtoupper($rawState) : 'FAILED')); + + $payment = $this->payment ?: $this->findPaymentByOrderId($orderId); + if ($payment) { + $payment->update([ + 'status' => $this->mapRevolutStatus($finalState), + 'response' => $payload, + ]); + } + + return response()->json(['ok' => true]); + } + + /** POST /orders/{id}/cancel (void before capture) */ + public function cancel(array|object $params) + { + + $params = (array) $params; + + $orderId = $params['id'] ?? $this->payment->response->id ?? null; + + if (!$orderId) return ['status' => 'error', 'message' => 'Order ID is required']; + + $resp = $this->postReq($this->url, '/orders/'.urlencode($orderId).'/cancel', (object)[], $this->headers, 'json', $this->mode); + + $statusCode = 200; + $message = 'Cancel successful'; + if(is_array($resp) && isset($resp['status']) && $resp['status'] == 'error') { + $message = json_decode($resp['message'], true)['message']; + $statusCode = $resp['code'] ?? 500; + $data = $resp; + } else { + $data = is_string($resp) ? (array) json_decode($resp, true) : (array) $resp; + } + + $status = self::RESPONSE_STATUS_ERROR; + + if (!isset($data['status']) || $data['status'] !== 'error') { + $this->payment?->update([ + 'status' => $this->getStatusEnum()::CANCELLED, + 'response' => $data, + ]); + $status = self::RESPONSE_STATUS_SUCCESS; + } + + return [ + 'type' => 'cancel', + 'status' => $status, + 'code' => $statusCode, + 'message' => $message, + 'id' => $this->payment->id ?? ($params['payment_id'] ?? null), + 'payment_service' => $this->service, + 'order_data' => json_encode($data), + ]; + } + + /** POST /orders/{id}/refund (full/partial; amount in minor units) */ + public function refund(array|object $params) + { + $refundRequest = $this->validateRefundRequest($params); + + if (!$refundRequest['validated']) return $refundRequest; + + $params = (array) $params; + $payment = $refundRequest['payment'] ?? null; + $orderId = $params['id'] ?? ($payment->response->id ?? null); + $currency = $params['currency'] ?? ($payment->response->currency ?? null); + + if (!$orderId) { + return array_merge($refundRequest, ['message' => 'order_id is required for refund']); + } + + if (!$currency) { + return array_merge($refundRequest, ['message' => 'currency is required for refund']); + } + + $payload = []; + if (!empty($params['amount'])) $payload['amount'] = (int) $params['amount']; // minor + if (!empty($currency)) $payload['currency'] = $currency; + + $resp = $this->postReq($this->url, '/orders/'.urlencode($orderId).'/refund', $payload, $this->headers, 'json', $this->mode); + + $data = is_string($resp) ? (array) json_decode($resp, true) : (array) $resp; + + $status = self::RESPONSE_STATUS_SUCCESS; + $message = 'Refunded successfully'; + $revolutMessageObject = isset($data['message']) ? json_decode($data['message'], true) : []; + + $paymentPayload = []; + + + if(isset($data['code'])) { + $status = self::RESPONSE_STATUS_ERROR; + } else { + $payment->update([ + 'status' => $this->getStatusEnum()::REFUNDED, + 'response' => $data, + ]); + } + + if(isset($revolutMessageObject['message'])) { + $message = $revolutMessageObject['message']; + } + + return array_merge($refundRequest, [ + 'status' => $status, + 'order_data' => $data, + 'message' => $message, + ]); + } + + /** Map Revolut states to your enum */ + protected function mapRevolutStatus(string $revolutStatus): string + { + $statusMap = [ + 'PENDING' => $this->getStatusEnum()::PENDING, + 'AUTHORISED' => $this->getStatusEnum()::PENDING, // wait for capture + 'COMPLETED' => $this->getStatusEnum()::COMPLETED, + 'FAILED' => $this->getStatusEnum()::FAILED, + 'CANCELLED' => $this->getStatusEnum()::CANCELLED, + ]; + return $statusMap[$revolutStatus] ?? $this->getStatusEnum()::FAILED; + } + + /** Helper: find Payment by order id for this gateway */ + protected function findPaymentByOrderId($orderId) + { + if (!$orderId) return null; + $paymentModel = config('payable.model'); + if (!$paymentModel) return null; + + return $paymentModel::where('order_id', $orderId) + ->where('payment_gateway', $this->service) + ->latest('id') + ->first(); + } + + /** Keep parent implementation */ + public function generatePostForm($params, $actionUrl = null) + { + return parent::generatePostForm($params, $actionUrl); + } +} diff --git a/src/Services/URequest.php b/src/Services/URequest.php index 8b4d040..73938b3 100755 --- a/src/Services/URequest.php +++ b/src/Services/URequest.php @@ -91,6 +91,7 @@ public function postReq($url, $endPoint, $postFields, $headers, $type, $mode = n try { if ($type == 'json') { // dd($this->client); + if (count($headers) < 1) { $headers = [ 'Content-Type' => 'application/json', @@ -106,6 +107,7 @@ public function postReq($url, $endPoint, $postFields, $headers, $type, $mode = n // ); } // dd($postFields, "{$url}{$endPoint}", $this->headers); + $res = $this->client->post("{$url}{$endPoint}", [ 'headers' => $headers, 'json' => $postFields, @@ -170,7 +172,32 @@ public function postReq($url, $endPoint, $postFields, $headers, $type, $mode = n // dd($safeData); return $safeData; } catch (\Exception $e) { - return response()->json(['error' => $e->getMessage()], 500); + if($e instanceof \GuzzleHttp\Exception\ClientException) { + if($e->getResponse()->getStatusCode() == 422) { + return [ + 'status' => 'error', + 'code' => $e->getResponse()->getStatusCode(), + 'message' => $e->getResponse()->getBody()->getContents(), + ]; + } else if($e->getResponse()->getStatusCode() == 400) { + return [ + 'status' => 'error', + 'code' => $e->getResponse()->getStatusCode(), + 'message' => $e->getResponse()->getBody()->getContents(), + ]; + } else if($e->getResponse()->getStatusCode() == 404) { + return [ + 'status' => 'error', + 'code' => $e->getResponse()->getStatusCode(), + 'message' => $e->getResponse()->getBody()->getContents(), + ]; + } + } + return [ + 'status' => 'error', + 'code' => $e->getResponse()->getStatusCode(), + 'message' => $e->getMessage(), + ]; } }