| Current Path : /home/users/unlimited/www/whatsapp-crm/app/Services/ |
| Current File : /home/users/unlimited/www/whatsapp-crm/app/Services/PayPalService.php |
<?php
namespace App\Services;
use App\Events\NewPaymentEvent;
use App\Models\BillingPayment;
use App\Models\BillingTransaction;
use App\Models\PaymentGateway;
use App\Models\Setting;
use App\Models\User;
use App\Services\SubscriptionService;
use App\Traits\ConsumesExternalServices;
use Carbon\Carbon;
use CurrencyHelper;
use Illuminate\Support\Facades\DB;
use Helper;
use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
class PayPalService
{
protected $config;
protected $subscriptionService;
protected $baseUri;
protected $clientId;
protected $clientSecret;
public function __construct()
{
$this->subscriptionService = new SubscriptionService();
$paypalInfo = PaymentGateway::where('name', 'Paypal')->first();
$this->config = json_decode($paypalInfo->metadata);
$this->baseUri = $this->config->mode == 'sandbox' ? 'https://api-m.sandbox.paypal.com/' : 'https://api-m.paypal.com/';
$this->clientId = $this->config->client_id;
$this->clientSecret = $this->config->secret;
Config::set('broadcasting.connections.pusher', [
'driver' => 'pusher',
'key' => Setting::where('key', 'pusher_app_key')->value('value'),
'secret' => Setting::where('key', 'pusher_app_secret')->value('value'),
'app_id' => Setting::where('key', 'pusher_app_id')->value('value'),
'options' => [
'cluster' => Setting::where('key', 'pusher_app_cluster')->value('value'),
],
]);
}
public function resolveAccessToken()
{
$httpClient = new HttpClient();
// Attempt to retrieve the auth token
try {
$payPalAuthRequest = $httpClient->request('POST', $this->baseUri . 'v1/oauth2/token', [
'auth' => [$this->clientId, $this->clientSecret],
'form_params' => [
'grant_type' => 'client_credentials'
]
]
);
return json_decode($payPalAuthRequest->getBody()->getContents())->access_token;
} catch (RequestException $e) {
Log::info($e->getResponse()->getBody()->getContents());
return response()->json([
'status' => 400,
'error' => $e->getResponse()->getBody()->getContents()
], 400);
}
}
public function makeRequest($method, $url, $body)
{
$httpClient = new HttpClient();
try {
$request = $httpClient->request($method, $this->baseUri . $url, [
'headers' => [
'Authorization' => 'Bearer ' . $this->resolveAccessToken(),
'Content-Type' => 'application/json'
],
'body' => json_encode($body)
]
);
return (object) array('success' => true, 'data' => json_decode($request->getBody()->getContents()));
} catch (RequestException $e) {
return (object) array('success' => false, 'error' => json_decode($e->getResponse()->getBody()->getContents()));
}
}
public function handlePayment($amount, $planId = NULL)
{
$currency = Setting::where('key', 'currency')->first()->value;
$returnUrl = url('billing');
$cancelUrl = url('billing');
try {
$pay = $this->makeRequest(
'POST',
'v1/payments/payment',
[
'intent' => 'sale',
'payer' => [
'payment_method' => 'paypal',
],
'redirect_urls' => [
'return_url' => $returnUrl,
'cancel_url' => $cancelUrl,
],
'transactions' => [
[
'amount' => [
'total' => $amount,
'currency' => $currency,
],
'description' => 'Subscription Payment',
'custom' => session()->get('current_organization') . '_' . auth()->user()->id . '_' . $planId,
],
],
'application_context' => [
'brand_name' => Setting::where('key', 'company_name')->first()->value,
'shipping_preference' => 'NO_SHIPPING',
],
]
);
return (object) array('success' => true, 'data' => $pay->data->links[1]->href);
} catch (\Exception $e) {
return (object) array('success' => false, 'error' => $e->getMessage());
}
}
protected function isValidWebhook()
{
// get request headers
$headers = apache_request_headers();
$headers = array_change_key_case($headers, CASE_UPPER);
// get http payload
$body = file_get_contents('php://input');
$data =
$headers['PAYPAL-TRANSMISSION-ID'] . '|' .
$headers['PAYPAL-TRANSMISSION-TIME'] . '|' .
$this->config->webhook_id . '|' . crc32($body);
// load certificate and extract public key
$pubKey = openssl_pkey_get_public(file_get_contents($headers['PAYPAL-CERT-URL']));
$key = openssl_pkey_get_details($pubKey)['key'];
// verify data against provided signature
$result = openssl_verify(
$data,
base64_decode($headers['PAYPAL-TRANSMISSION-SIG']),
$key,
'sha256WithRSAEncryption'
);
if ($result == 1) {
// webhook notification is verified
Log::info('webhook verified');
return true;
} elseif ($result == 0) {
// webhook notification is NOT verified
Log::info('webhook not verified');
return false;
} else {
// there was an error verifying this
Log::info('webhook verification error');
return false;
}
}
public function handleWebhook(Request $request)
{
if (!$this->isValidWebhook($request)) {
//Log::error('Received invalid webhook');
return response('Invalid webhook', 400);
exit();
}
if ($request->event_type == "PAYMENTS.PAYMENT.CREATED") {
$transaction = DB::transaction(function () use ($request) {
$transactionData = $request->resource['transactions'][0];
$metadata = $transactionData['custom'] ?? null;
if($metadata){
$metadata = explode('_', $metadata);
$organizationId = $metadata[0] ?? null;
$userId = $metadata[1] ?? null;
$planId = ($metadata[2] !== '') ? $metadata[2] : null;
$amount = $transactionData['amount']['total'];
$payment = BillingPayment::create([
'organization_id' => $organizationId,
'processor' => 'paypal',
'details' => $request->resource['id'],
'amount' => $amount
]);
$transaction = BillingTransaction::create([
'organization_id' => $organizationId,
'entity_type' => 'payment',
'entity_id' => $payment->id,
'description' => 'PayPal Payment',
'amount' => $amount,
'created_by' => $userId,
]);
if($planId == null){
$this->subscriptionService->activateSubscriptionIfInactiveAndExpiredWithCredits($organizationId, $userId);
} else {
$this->subscriptionService->updateSubscriptionPlan($organizationId, $planId, $userId);
}
//Log::debug($transaction);
event(new NewPaymentEvent($transaction, $organizationId));
return $transaction;
}
});
}
}
}