KSA-ORACLE/app/Http/Controllers/WisePaymentController.php
2025-09-15 13:00:04 +03:00

249 lines
8.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Payment;
use Illuminate\Http\Request;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
class WisePaymentController extends Controller
{
private $wiseClient;
private $wiseApiKey;
private $profileId;
public function __construct()
{
$this->wiseApiKey = env('WISE_API_KEY');
$this->profileId = env('WISE_PROFILE_ID'); // Your Wise business/profile ID
$this->wiseClient = new Client([
'base_uri' => 'https://api.wise.com/v1/',
'headers' => [
'Authorization' => 'Bearer ' . $this->wiseApiKey,
'Content-Type' => 'application/json',
],
]);
}
public function createTransfer(Request $request)
{
// Validate the incoming request data
$validatedData = $request->validate([
'amount' => 'required|numeric|min:0.01',
'source_currency' => 'required|string|size:3',
'target_currency' => 'required|string|size:3',
'recipient_name' => 'required|string|max:255',
'recipient_email' => 'required|email',
'recipient_account_number' => 'required|string',
'recipient_bank_code' => 'sometimes|string', // Needed for some countries
'recipient_address' => 'sometimes|array',
'reason' => 'sometimes|string|max:255',
]);
try {
// Create a new Payment record
$payment = new Payment([
'amount' => $validatedData['amount'],
'currency' => $validatedData['source_currency'],
'target_currency' => $validatedData['target_currency'],
'recipient_name' => $validatedData['recipient_name'],
'recipient_email' => $validatedData['recipient_email'],
'status' => 'pending',
'client_session_id' => $request->client_session_id ?? uniqid('wise_', true)
]);
$payment->save();
// Create recipient account
$recipient = $this->createRecipient($validatedData);
// Create quote
$quote = $this->createQuote($validatedData);
// Create transfer
$transfer = $this->createTransferWise($quote, $recipient, $validatedData);
// Fund the transfer
$this->fundTransfer($transfer['id']);
// Update the Payment record
$payment->wise_transfer_id = $transfer['id'];
$payment->wise_recipient_id = $recipient['id'];
$payment->wise_quote_id = $quote['id'];
$payment->status = 'processing';
$payment->save();
return response()->json([
'success' => true,
'message' => 'Transfer initiated successfully.',
'transfer_id' => $transfer['id'],
'payment_id' => $payment->id
]);
} catch (ClientException $e) {
$response = $e->getResponse();
$body = json_decode($response->getBody()->getContents(), true);
Log::error('Wise Client Error:', [
'code' => $e->getCode(),
'message' => $e->getMessage(),
'details' => $body
]);
if (isset($payment)) {
$payment->status = 'failed';
$payment->error_message = $e->getMessage();
$payment->save();
}
return response()->json([
'success' => false,
'message' => 'Wise API failed to process the request.',
'error' => $body['errors'] ?? $e->getMessage()
], 400);
} catch (\Exception $e) {
Log::error('General Wise API Error:', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
if (isset($payment)) {
$payment->status = 'failed';
$payment->error_message = $e->getMessage();
$payment->save();
}
return response()->json([
'success' => false,
'message' => 'An unexpected error occurred.',
'error' => $e->getMessage()
], 500);
}
}
public function handleWebhook(Request $request)
{
// Verify the webhook signature if needed
$payload = $request->all();
Log::info('Wise Webhook Received:', $payload);
if (isset($payload['data']['resource']['id'])) {
$transferId = $payload['data']['resource']['id'];
// Find the payment by transfer ID
$payment = Payment::where('wise_transfer_id', $transferId)->first();
if ($payment) {
$payment->status = $payload['data']['current_state'] ?? 'unknown';
$payment->save();
// You might want to trigger other actions based on status change
}
}
return response()->json(['status' => 'ok']);
}
// Helper methods to interact with Wise API
private function createRecipient($data)
{
$response = $this->wiseClient->post('accounts', [
'json' => [
'profile' => $this->profileId,
'accountHolderName' => $data['recipient_name'],
'currency' => $data['target_currency'],
'type' => 'email', // or 'sort_code', 'aba', 'iban' etc. based on country
'details' => [
'email' => $data['recipient_email'],
// Add more details based on account type and country
'legalType' => 'PRIVATE',
// 'accountNumber' => $data['recipient_account_number'],
// 'bankCode' => $data['recipient_bank_code'] ?? null,
]
],
]);
return json_decode($response->getBody(), true);
}
private function createQuote($data)
{
$response = $this->wiseClient->post('quotes', [
'json' => [
'profile' => $this->profileId,
'source' => $data['source_currency'],
'target' => $data['target_currency'],
'rateType' => 'FIXED', // or 'FLOAT'
'sourceAmount' => $data['amount'],
'type' => 'BALANCE_PAYOUT' // or 'BALANCE_CONVERSION'
],
]);
return json_decode($response->getBody(), true);
}
private function createTransferWise($quote, $recipient, $data)
{
$response = $this->wiseClient->post('transfers', [
'json' => [
'targetAccount' => $recipient['id'],
'quote' => $quote['id'],
'customerTransactionId' => uniqid('cti_', true),
'details' => [
'reference' => $data['reason'] ?? 'Payment for services',
'transferPurpose' => $data['reason'] ?? 'Payment for services',
]
],
]);
return json_decode($response->getBody(), true);
}
private function fundTransfer($transferId)
{
// Check if the transfer requires funding
$transfer = $this->wiseClient->get("transfers/{$transferId}");
$transferData = json_decode($transfer->getBody(), true);
if ($transferData['status'] === 'pending') {
// Fund the transfer from your balance
$this->wiseClient->post("transfers/{$transferId}/payments", [
'json' => [
'type' => 'BALANCE',
'profile' => $this->profileId
]
]);
}
}
// Additional helper method to check transfer status
public function checkTransferStatus($paymentId)
{
$payment = Payment::findOrFail($paymentId);
try {
$response = $this->wiseClient->get("transfers/{$payment->wise_transfer_id}");
$transferData = json_decode($response->getBody(), true);
$payment->status = $transferData['status'];
$payment->save();
return response()->json([
'success' => true,
'status' => $transferData['status']
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Failed to check transfer status'
], 500);
}
}
}