diff --git a/composer.json b/composer.json index d19331c14..9a4529108 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ "phpmailer/phpmailer": "~6.0", "minishlink/web-push": "^5.2", "stripe/stripe-php": "^7.40", - "geoip2/geoip2": "~2.0" + "geoip2/geoip2": "~2.0", + "paypal/paypal-checkout-sdk": "^1.0" }, "require-dev": { "kint-php/kint": "^1.1", diff --git a/composer.lock b/composer.lock index 12251f820..54c328891 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f48f2e76d23925213a1c248388654ed4", - "content-hash": "4faadcc7d5b72636e2d9ac9a18b062a2", + "hash": "c9fc655cdb58743c38114c03e68c1cc7", + "content-hash": "a150435d7f20bef4fdda8cb6c59eb1a6", "packages": [ { "name": "composer/ca-bundle", @@ -663,6 +663,95 @@ ], "time": "2020-03-20 21:48:09" }, + { + "name": "paypal/paypal-checkout-sdk", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/paypal/Checkout-PHP-SDK.git", + "reference": "ed6a55075448308b87a8b59dcb7fedf04a048cb1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paypal/Checkout-PHP-SDK/zipball/ed6a55075448308b87a8b59dcb7fedf04a048cb1", + "reference": "ed6a55075448308b87a8b59dcb7fedf04a048cb1", + "shasum": "" + }, + "require": { + "paypal/paypalhttp": "1.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "PayPalCheckoutSdk\\": "lib/PayPalCheckoutSdk", + "Sample\\": "samples/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "https://github.com/paypal/Checkout-PHP-SDK/blob/master/LICENSE" + ], + "authors": [ + { + "name": "PayPal", + "homepage": "https://github.com/paypal/Checkout-PHP-SDK/contributors" + } + ], + "description": "PayPal's PHP SDK for Checkout REST APIs", + "homepage": "http://github.com/paypal/Checkout-PHP-SDK/", + "keywords": [ + "checkout", + "orders", + "payments", + "paypal", + "rest", + "sdk" + ], + "time": "2019-11-07 23:16:44" + }, + { + "name": "paypal/paypalhttp", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/paypal/paypalhttp_php.git", + "reference": "1ad9b846a046f09d6135cbf2cbaa7701bbc630a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paypal/paypalhttp_php/zipball/1ad9b846a046f09d6135cbf2cbaa7701bbc630a3", + "reference": "1ad9b846a046f09d6135cbf2cbaa7701bbc630a3", + "shasum": "" + }, + "require": { + "ext-curl": "*" + }, + "require-dev": { + "phpunit/phpunit": "^5.7", + "wiremock-php/wiremock-php": "1.43.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PayPalHttp\\": "lib/PayPalHttp" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PayPal", + "homepage": "https://github.com/paypal/paypalhttp_php/contributors" + } + ], + "abandoned": true, + "time": "2019-11-06 21:27:12" + }, { "name": "phpmailer/phpmailer", "version": "v6.1.7", @@ -874,16 +963,16 @@ }, { "name": "spomky-labs/base64url", - "version": "v2.0.2", + "version": "v2.0.3", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/base64url.git", - "reference": "69e77e7d7c5407a253dacdd7bfe6b8978b7a4fb2" + "reference": "48ea8ff600cefe56b82d3d5b768b6f4f3bfe05a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/base64url/zipball/69e77e7d7c5407a253dacdd7bfe6b8978b7a4fb2", - "reference": "69e77e7d7c5407a253dacdd7bfe6b8978b7a4fb2", + "url": "https://api.github.com/repos/Spomky-Labs/base64url/zipball/48ea8ff600cefe56b82d3d5b768b6f4f3bfe05a1", + "reference": "48ea8ff600cefe56b82d3d5b768b6f4f3bfe05a1", "shasum": "" }, "require": { @@ -922,20 +1011,20 @@ "safe", "url" ], - "time": "2020-08-01 14:15:43" + "time": "2020-08-30 13:35:33" }, { "name": "stripe/stripe-php", - "version": "v7.49.0", + "version": "v7.52.0", "source": { "type": "git", "url": "https://github.com/stripe/stripe-php.git", - "reference": "db6229bff448f7f3bf7f6aee112d5d9ba34ca4ba" + "reference": "51e95c514aff45616dff09791ca5b2f10cf5c4e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stripe/stripe-php/zipball/db6229bff448f7f3bf7f6aee112d5d9ba34ca4ba", - "reference": "db6229bff448f7f3bf7f6aee112d5d9ba34ca4ba", + "url": "https://api.github.com/repos/stripe/stripe-php/zipball/51e95c514aff45616dff09791ca5b2f10cf5c4e8", + "reference": "51e95c514aff45616dff09791ca5b2f10cf5c4e8", "shasum": "" }, "require": { @@ -979,7 +1068,7 @@ "payment processing", "stripe" ], - "time": "2020-08-19 22:48:20" + "time": "2020-09-08 19:29:20" }, { "name": "symfony/polyfill-intl-idn", @@ -2230,16 +2319,16 @@ }, { "name": "symfony/var-dumper", - "version": "v4.4.11", + "version": "v4.4.13", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2125805a1a4e57f2340bc566c3013ca94d2722dc" + "reference": "1bef32329f3166486ab7cb88599cae4875632b99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2125805a1a4e57f2340bc566c3013ca94d2722dc", - "reference": "2125805a1a4e57f2340bc566c3013ca94d2722dc", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1bef32329f3166486ab7cb88599cae4875632b99", + "reference": "1bef32329f3166486ab7cb88599cae4875632b99", "shasum": "" }, "require": { @@ -2303,7 +2392,7 @@ "debug", "dump" ], - "time": "2020-06-24 13:34:53" + "time": "2020-08-17 07:31:35" } ], "aliases": [], diff --git a/frontend/payments/classes/class.ApiNarocilaController.php b/frontend/payments/classes/class.ApiNarocilaController.php index 2051b6107..9ff60a0bf 100644 --- a/frontend/payments/classes/class.ApiNarocilaController.php +++ b/frontend/payments/classes/class.ApiNarocilaController.php @@ -76,6 +76,7 @@ class ApiNarocilaController{ return true; else{ $this->response['error'] = 'Napaka! Napačen token.'; + $this->response['success'] = false; return false; } @@ -88,6 +89,7 @@ class ApiNarocilaController{ if (!isset($this->params['action'])) { $this->response['error'] = 'Napaka! Manjkajo parametri!'; + $this->response['success'] = false; } else { @@ -122,6 +124,7 @@ class ApiNarocilaController{ } else{ $this->response['error'] = 'Napaka! Manjka ID narocila!'; + $this->response['success'] = false; } break; @@ -135,6 +138,7 @@ class ApiNarocilaController{ } else{ $this->response['error'] = 'Napaka! Manjka ID narocila!'; + $this->response['success'] = false; } break; @@ -208,6 +212,8 @@ class ApiNarocilaController{ if($usr_id == '' || $usr_id == 0){ $this->response['error'] = 'ERROR! Missing user ID.'; + $this->response['success'] = false; + break; } @@ -223,6 +229,20 @@ class ApiNarocilaController{ $this->response = $price; break; + + // Preveri, ce je narocilo placano preko paypala + case 'check_narocilo_paypal': + + if(isset($this->data['narocilo_id'])){ + $paypal = new UserNarocilaPaypal($this->data['narocilo_id']); + $this->response = $narocilo->paypalCaptureOrder(); + } + else{ + $this->response['error'] = 'Napaka! Manjka ID narocila!'; + $this->response['success'] = false; + } + + break; } } } diff --git a/frontend/payments/classes/class.UserNarocila.php b/frontend/payments/classes/class.UserNarocila.php index 58b8c6a57..f8655a72c 100644 --- a/frontend/payments/classes/class.UserNarocila.php +++ b/frontend/payments/classes/class.UserNarocila.php @@ -647,6 +647,8 @@ class UserNarocila{ if($usr_id <= 0){ $response['error'] = 'ERROR! Missing user ID.'; + $response['success'] = false; + return $response; } @@ -684,6 +686,8 @@ class UserNarocila{ "); if (!$sqlNarocilo){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } @@ -713,7 +717,6 @@ class UserNarocila{ } - return $response; } @@ -753,6 +756,8 @@ class UserNarocila{ } catch (Exception $e){ $response['error'] = 'ERROR! Sending email with invoice failed.'; + $response['success'] = false; + return $response; } @@ -768,6 +773,8 @@ class UserNarocila{ $token = isset($narocilo_data['stripe_id']) ? $narocilo_data['stripe_id'] : ''; if($token == ''){ $response['error'] = 'ERROR! Missing token.'; + $response['success'] = false; + return $response; } @@ -789,10 +796,12 @@ class UserNarocila{ } else{ $response['error'] = $payment_response['error']; + $response['success'] = false; } } else{ $response['error'] = $stripe_response['error']; + $response['success'] = false; } $response['narocilo_id'] = $narocilo_id; @@ -814,11 +823,12 @@ class UserNarocila{ // Ce je bilo placilo preko stripa uspesno zgeneriramo racun in uporabniku aktiviramo paket if($paypal_response['success'] == true){ - $response['paypal_url'] = $paypal_response['paypal_url']; + $response['paypal_link'] = $paypal_response['paypal_link']; $response['success'] = true; } else{ $response['error'] = $paypal_response['error']; + $response['success'] = false; } return $response; @@ -826,7 +836,7 @@ class UserNarocila{ - // Posodobi obstojece narocilo za uporabnika - ZA TESTIRATI + // Posodobi obstojece narocilo za uporabnika public function updateNarocilo($narocilo_data){ global $global_user_id; @@ -835,6 +845,7 @@ class UserNarocila{ // ce nimamo id-ja narocila vrnemo error if(!isset($narocilo_data['narocilo_id']) || $narocilo_data['narocilo_id'] == '0'){ $response['error'] = 'Napaka! Manjka ID narocila!'; + $response['success'] = false; return $response; } @@ -864,6 +875,8 @@ class UserNarocila{ $sqlNarocilo = sisplet_query("UPDATE user_access_narocilo SET ".$update.", cebelica_id_racun='0', cebelica_id_predracun='0' WHERE id='".$narocilo_data['narocilo_id']."'"); if (!$sqlNarocilo){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } @@ -882,6 +895,7 @@ class UserNarocila{ // Ce nimamo id-ja narocila vrnemo error if($narocilo_id == 0){ $response['error'] = 'Napaka! Manjka ID narocila!'; + $response['success'] = false; return $response; } @@ -894,6 +908,7 @@ class UserNarocila{ // Ce je bil racun ze placan ne naredimo nicesar if($rowNarocilo['status'] == 1){ $response['error'] = 'Napaka! Račun je že plačan!'; + $response['success'] = false; return $response; } @@ -924,6 +939,8 @@ class UserNarocila{ "); if (!$sqlAccess){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } } @@ -932,6 +949,8 @@ class UserNarocila{ $sqlAccess = sisplet_query("UPDATE user_access SET time_expire = time_expire + INTERVAL '".$rowNarocilo['trajanje']."' MONTH WHERE usr_id='".$rowNarocilo['usr_id']."'"); if (!$sqlAccess){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } } @@ -948,6 +967,8 @@ class UserNarocila{ "); if (!$sqlAccess){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } } @@ -957,6 +978,8 @@ class UserNarocila{ $sqlNarociloStatus = sisplet_query("UPDATE user_access_narocilo SET status='1' WHERE id='".$narocilo_id."'"); if (!$sqlNarociloStatus){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } diff --git a/frontend/payments/classes/class.UserNarocilaPaypal.php b/frontend/payments/classes/class.UserNarocilaPaypal.php index 503313c5f..e90c64406 100644 --- a/frontend/payments/classes/class.UserNarocilaPaypal.php +++ b/frontend/payments/classes/class.UserNarocilaPaypal.php @@ -7,14 +7,23 @@ */ +use PayPalCheckoutSdk\Core\PayPalHttpClient; +use PayPalCheckoutSdk\Core\SandboxEnvironment; +use PayPalCheckoutSdk\Orders\OrdersCreateRequest; +use PayPalCheckoutSdk\Orders\OrdersCaptureRequest; + + class UserNarocilaPaypal{ private $narocilo; + private $paypal_client; public function __construct($narocilo_id){ - global $app_settings; + global $app_settings; + global $paypal_client_id; + global $paypal_secret; if($narocilo_id > 0){ @@ -28,6 +37,10 @@ class UserNarocilaPaypal{ else{ die("Napaka pri komunikaciji s paypal! Narocilo ne obstaja."); } + + // Ustvarimo okolje za paypal + $environment = new SandboxEnvironment($paypal_client_id, $paypal_secret); + $this->paypal_client = new PayPalHttpClient($environment); } else { die("Napaka pri komunikaciji s paypal! Manjka ID naročila."); @@ -37,11 +50,10 @@ class UserNarocilaPaypal{ // Placamo narocilo s paypal public function paypalCreatePayment(){ - global $paypal_account; - global $paypal_client_id; - global $paypal_secret; global $site_url; + $response = array(); + $UA = new UserNarocila(); $cena = $UA->getPrice($this->narocilo['package_name'], $this->narocilo['trajanje'], $this->narocilo['discount']); @@ -67,60 +79,161 @@ class UserNarocilaPaypal{ } - // Podatki za paypal potrebni za placilo + // Podatki narocila $orderDetails = array( - 'business' => $paypal_client_id, - - 'item_name' => '1KA naročnina (paket '.strtoupper($this->narocilo['package_name']). ' - '.$this->narocilo['trajanje'].' '.$months_string.')', - 'item_number' => $this->narocilo['id'], - 'amount' => $cena_za_placilo * 100, - 'currency_code' => 'EUR', - - 'return' => $site_url.'frontend/payments/paypal-pay.php', - 'cancel_return' => $site_url.'frontend/payments/paypal-cancel.php', - - 'cmd' => '_xclick' + 'ime' => '1KA naročnina (paket '.strtoupper($this->narocilo['package_name']). ' - '.$this->narocilo['trajanje'].' '.$months_string.')', + 'narocilo_id' => $this->narocilo['id'], + 'cena' => $cena_za_placilo, ); - // Posljemo placilo na paypal, da se lahko potem user prijavi in ga placa - $paypalResponse = $this->paypalCreatePaymentSend($orderDetails); + // Ustvarimo order na paypal, da se lahko potem user prijavi in ga placa + $paypal_response = $this->paypalCreateOrder($orderDetails); + + if(!isset($paypal_response['success']) || $paypal_response['success'] == false){ + return $paypal_response; + } // Vstavimo plačilo v bazo $sqlNarocilo = sisplet_query("INSERT INTO user_access_paypal_transaction (transaction_id, narocilo_id, price, currency_type, time) VALUES - ('".$paypalResponse['transaction_id']."', '".$paypalResponse['narocilo_id']."', '".$paypalResponse['price']."', '".$paypalResponse['currency_type']."',NOW()) + ('".$paypal_response['transaction_id']."', '".$this->narocilo['id']."', '".$cena_za_placilo."', 'EUR', NOW()) "); if (!$sqlNarocilo){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } - $response = array(); + $response['paypal_link'] = $paypal_response['paypal_link']; + + $response['success'] = true; return $response; } - - // Posljemo podatke za placilo paypalu - TODO - private function paypalCreatePaymentSend(){ - global $paypal_account; - global $paypal_client_id; - global $paypal_secret; + // Posljemo podatke za placilo paypalu + private function paypalCreateOrder($orderDetails){ + global $site_url; $response = array(); - $paypal_url = 'https://www.paypal.com/cgi-bin/webscr'; + $request = new OrdersCreateRequest(); - /* - $response['transaction_id'] = $_GET['tx']; - $response['narocilo_id'] = $_GET['item_number']; - $response['price'] = $_GET['amt']; - $response['currency_type'] = $_GET['cc']; - */ + $request->prefer('return=representation'); + //$request->headers["prefer"] = "return=representation"; + + $request->body = [ + "intent" => "CAPTURE", + "purchase_units" => [[ + "reference_id" => $orderDetails['narocilo_id'], + "amount" => [ + "value" => $orderDetails['cena'], + "currency_code" => "EUR" + ] + ]], + "application_context" => [ + "cancel_url" => $site_url . '/d/narocilo/paypal-cancel', + "return_url" => $site_url . '/d/narocilo/paypal' + ] + ]; + + try { + // Poklicemo paypal api za ustvarjanje narocila + $paypal_response = $client->execute($request); + + if($paypal_response->result->status != 'CREATED'){ + $response['error'] = 'ERROR! Order was not created.'; + $response['success'] = false; + + return $response; + } + + // Dobimo id paypal narocila + $response['transaction_id'] = $paypal_response->result->id; + + // Dobimo link za preusmeritev stranke, da potrdi narocilo in potem lahko izvedemo "capture" + foreach($paypal_response->result->links as $link){ + + if($link->rel == 'capture') + $response['paypal_link'] = $link->href; + } + } + catch (HttpException $e) { + $response['error'] = $e->getMessage(); + return $response; + } + + $response['success'] = true; + + return $response; + } + + + // Zakljucimo placilo, ce je bilo placilo ok odobreno preko paypala s strani stranke + public function paypalCaptureOrder(){ + + $response = array(); + + // Preverimo plačilo v bazo + $sqlNarociloPaypal = sisplet_query("SELECT transaction_id + FROM user_access_paypal_transaction + WHERE narocilo_id='".$this->narocilo['id']."' + "); + if (!$sqlNarociloPaypal){ + $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + + return $response; + } + + // Narocilo ne obstaja (ni v bazi paypal narocil) + if (mysqli_num_rows($sqlNarociloPaypal) == 0){ + $response['error'] = 'ERROR! Paypal order does not exist.'; + $response['success'] = false; + + return $response; + } + + $rowNarociloPaypal = mysqli_fetch_array($sqlNarociloPaypal); + + // Preverimo, ce je bilo vse ok placano - POST request to /v2/checkout/orders + $request = new OrdersCaptureRequest($rowNarociloPaypal['transaction_id']); + //$request->prefer('return=representation'); + + try { + // Poklicemo paypal api kjer preverimo placilo narocila + $paypal_response = $client->execute($request); + } + catch (HttpException $e) { + $response['error'] = $e->getMessage(); + $response['success'] = false; + + return $response; + } + + + // Posodobimo status narocila + $sqlNarocilo = sisplet_query("UPDATE user_access_paypal_transaction + SET status='".$paypal_response->result->status."' + WHERE transaction_id='".$paypal_response->result->id."' + "); + if (!$sqlNarocilo){ + $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + + return $response; + } + + + $response['status'] = $paypal_response->result->status; + + $response['success'] = true; + return $response; } } \ No newline at end of file diff --git a/frontend/payments/classes/class.UserNarocilaStripe.php b/frontend/payments/classes/class.UserNarocilaStripe.php index 8ca6af29e..a9148cde2 100644 --- a/frontend/payments/classes/class.UserNarocilaStripe.php +++ b/frontend/payments/classes/class.UserNarocilaStripe.php @@ -100,6 +100,8 @@ class UserNarocilaStripe{ "); if (!$sqlNarocilo){ $response['error'] = 'ERROR! '.mysqli_error($GLOBALS['connect_db']); + $response['success'] = false; + return $response; } $response = array(); @@ -118,6 +120,7 @@ class UserNarocilaStripe{ // Placilo ni uspelo else{ $response['error'] = 'ERROR! Stripe payment failed. Failure code '.$stripeResponse['failure_code']; + $response['success'] = false; } return $response; diff --git a/sql/update2.sql b/sql/update2.sql index c7c94ed29..4b4f57512 100644 --- a/sql/update2.sql +++ b/sql/update2.sql @@ -9291,6 +9291,7 @@ CREATE TABLE user_access_paypal_transaction( price DECIMAL(7,2) NOT NULL DEFAULT '0', currency_type VARCHAR(100) NOT NULL DEFAULT '', time DATETIME(3) NOT NULL, + status VARCHAR(30) NOT NULL DEFAULT '', PRIMARY KEY (id), UNIQUE KEY (transaction_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;