From 18dadd28c15ce7a3316f055652fbcfebcd1ee63a Mon Sep 17 00:00:00 2001
From: Immanuel Onyeka <immanuel@onyeka.ca>
Date: Wed, 9 Jun 2021 15:59:32 -0400
Subject: [PATCH] Update user credits after a charge

---
 app/Http/Controllers/BillingController.php    | 34 +++++++++++++++----
 ...tionController.php => OrderController.php} |  2 +-
 app/Http/Middleware/VerifyCsrfToken.php       |  2 +-
 ...06_08_224029_create_transactions_table.php |  1 +
 resources/js/panel/credits.vue                |  7 ++--
 resources/js/panel/panel.vue                  |  2 +-
 resources/js/panel/saved-cards.vue            |  2 +-
 resources/js/panel/sidebar.vue                |  4 +--
 routes/web.php                                |  8 +++--
 9 files changed, 44 insertions(+), 18 deletions(-)
 rename app/Http/Controllers/{TransactionController.php => OrderController.php} (94%)

diff --git a/app/Http/Controllers/BillingController.php b/app/Http/Controllers/BillingController.php
index cae4dfd..29d2d68 100644
--- a/app/Http/Controllers/BillingController.php
+++ b/app/Http/Controllers/BillingController.php
@@ -19,7 +19,6 @@ class BillingController extends Controller
 	//Should validate that all amounts are positive integers in a reasonable range
 	public function secret(Request $request) {
 		Stripe::setApiKey(env('STRIPE_SECRET'));
-		Log::debug($request->packs);
 
 		$amount = $request->packs[ 'credits10' ]*1099 +
 			$request->packs[ 'credits50' ]*5499 + $request->packs[ 'credits100' ]*10999
@@ -28,18 +27,17 @@ class BillingController extends Controller
 		$transaction = new Transaction;
 		$transaction->credits = $request->packs['credits10']*10 +
 			$request->packs['credits50']*50 +
-			$request->packs['credits[100]']*100 +
-			$request->packs['credits[1000]']*1000;
+			$request->packs['credits100']*100 +
+			$request->packs['credits1000']*1000;
 		$transaction->credits_extra =
 			$request->packs['credits50']*5 +
-			$request->packs['credits[100]']*10 +
-			$request->packs['credits[1000]']*150;
+			$request->packs['credits100']*10 +
+			$request->packs['credits1000']*150;
 
 		$transaction->user_id = Auth::user()->id;
 		$transaction->charge = $amount;
 		$transaction->status = 'processing';
 		$transaction->completed = false;
-		$transaction->save();
 
 		$intent = PaymentIntent::create([
 			'amount' => $amount,
@@ -47,15 +45,39 @@ class BillingController extends Controller
 			'customer' => Auth::user()->customer_id,
 			'metadata' => ['transaction_id' => $transaction->id]
 		]);
+		$transaction->intent_id = $intent->id;
 
+		$transaction->save();
 		return $intent->client_secret;
 	}
 
 	public function getCards() {
 		Stripe::setApiKey(env('STRIPE_SECRET'));
+
 		return PaymentMethod::all([
 			'customer' => Auth::user()->customer_id,
 			'type' => 'card'
 		]);
 	}
+
+	public function chargeEvent(Request $request) {
+		Stripe::setApiKey(env('STRIPE_SECRET'));
+		$event = \Stripe\Event::constructFrom($request->all());
+		$charge = $event->data->object;
+		$transaction = Transaction::where('intent_id', $charge->payment_intent);
+		$user = $transaction->user;
+
+		if ($event->type == 'charge.succeeded') {
+			Log::debug($charge->metadata['transaction_id']);
+			$user->credits = $user->credits + $transaction->credits + $transaction->credits_extra;
+			$transaction->status = 'completed';
+			$transaction->completed = true;
+			$user->save();
+			$transaction->save();
+
+		} else {
+			$transaction->status = $charge->status;
+			$transaction->save();
+		}
+	}
 }
diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/OrderController.php
similarity index 94%
rename from app/Http/Controllers/TransactionController.php
rename to app/Http/Controllers/OrderController.php
index c66f950..4057906 100644
--- a/app/Http/Controllers/TransactionController.php
+++ b/app/Http/Controllers/OrderController.php
@@ -8,7 +8,7 @@ use App\Models\Service;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Log;
 
-class TransactionController extends Controller
+class OrderController extends Controller
 {
 	//THis should also reduce user's available credits
 	public function newOrder(Request $request) {
diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php
index 0c13b85..44944fc 100644
--- a/app/Http/Middleware/VerifyCsrfToken.php
+++ b/app/Http/Middleware/VerifyCsrfToken.php
@@ -12,6 +12,6 @@ class VerifyCsrfToken extends Middleware
      * @var array
      */
     protected $except = [
-        //
+        'hooks/*'
     ];
 }
diff --git a/database/migrations/2021_06_08_224029_create_transactions_table.php b/database/migrations/2021_06_08_224029_create_transactions_table.php
index 647e4d4..1240a26 100644
--- a/database/migrations/2021_06_08_224029_create_transactions_table.php
+++ b/database/migrations/2021_06_08_224029_create_transactions_table.php
@@ -20,6 +20,7 @@ class CreateTransactionsTable extends Migration
 			$table->integer('credits')->unsigned();
 			$table->integer('credits_extra')->unsigned()->default(0);
             $table->string('status');
+            $table->string('intent_id')->unique();
             $table->boolean('completed');
             $table->string('note')->nullable();
             $table->timestamps();
diff --git a/resources/js/panel/credits.vue b/resources/js/panel/credits.vue
index 55e8700..9b6bfa7 100644
--- a/resources/js/panel/credits.vue
+++ b/resources/js/panel/credits.vue
@@ -81,7 +81,6 @@ function getSecret() {
 //Gets key from the server then sends it with stripe
 //Maybe it should asl attach the user's receipt email
 function pay() {
-	console.log('paying')
 	this.getSecret().then(secret => {
 		if (!secret) {return}
 		this.loading = true
@@ -105,8 +104,7 @@ function pay() {
 			document.getElementById('payment-error').textContent =
 			result.error.message
 		} else if (result.paymentIntent.status === 'succeeded') {
-			document.getElementById('payment-error').textContent =
-			'Purchase completed'
+			this.complete()
 		} else {
 			document.getElementById('payment-error').textContent =
 			'An unknown error occured'
@@ -123,11 +121,12 @@ function getCards() {
 		'X-XSRF-TOKEN': this.token}
 	}).then((response) => {response.json().then(data => {
 		this.cards = data.data
-		if (this.cards) {
+		if (this.cards && this.cards.length > 0) {
 			this.picked = this.cards[0].id
 		}
 	})})
 }
+
 function ready() {
 	return this.total != 0 && !this.loading && ((this.cardValid &&
 	this.billingName) || this.picked)
diff --git a/resources/js/panel/panel.vue b/resources/js/panel/panel.vue
index f03db76..f828601 100644
--- a/resources/js/panel/panel.vue
+++ b/resources/js/panel/panel.vue
@@ -1,6 +1,6 @@
 <template>
 <template v-if="!loading">
-<sidebar :active="active"></sidebar>
+<sidebar :role="user.role" :active="active"></sidebar>
 <transition name="fade" mode="out-in">
 <div v-if="active === ''" id="main">
 	<section class="welcome-pane"><h3>Welcome, {{user.name}}!</h3></section>
diff --git a/resources/js/panel/saved-cards.vue b/resources/js/panel/saved-cards.vue
index 3a98a90..7e95620 100644
--- a/resources/js/panel/saved-cards.vue
+++ b/resources/js/panel/saved-cards.vue
@@ -15,7 +15,7 @@
 			return {}
 		},
 		mounted() {
-			if (this.cards) {
+			if (this.cards && this.cards.length > 0) {
 				this.$emit('update:pickedCard', this.cards[0].id)
 			}
 		},
diff --git a/resources/js/panel/sidebar.vue b/resources/js/panel/sidebar.vue
index 850537f..2fefc1e 100644
--- a/resources/js/panel/sidebar.vue
+++ b/resources/js/panel/sidebar.vue
@@ -16,7 +16,7 @@
   <path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/>
 </svg>
 </a>
-<a :class="{selected: active == '#admin'}" href="/panel#admin">
+<a v-if="role == 'admin'" :class="{selected: active == '#admin'}" href="/telescope">
 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-key-fill" viewBox="0 0 16 16">
   <path d="M3.5 11.5a3.5 3.5 0 1 1 3.163-5H14L15.5 8 14 9.5l-1-1-1 1-1-1-1 1-1-1-1 1H6.663a3.5 3.5 0 0 1-3.163 2zM2.5 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
 </svg>
@@ -31,7 +31,7 @@
 
 <script>
 export default {
-	props: ['active']
+	props: ['active', 'role']
 }
 </script>
 
diff --git a/routes/web.php b/routes/web.php
index 1f1bb4a..78004aa 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -3,7 +3,7 @@
 use Illuminate\Support\Facades\Route;
 use App\Http\Controllers\UserController;
 use App\Http\Controllers\ServiceController;
-use App\Http\Controllers\TransactionController;
+use App\Http\Controllers\OrderController;
 use App\Http\Controllers\BillingController;
 use Illuminate\Foundation\Auth\EmailVerificationRequest;
 use Illuminate\Http\Request;
@@ -84,7 +84,7 @@ Route::post('/panel/change-password', [UserController::class,
 Route::get('/reset-email', [UserController::class,
 	'resetEmail'])->name('reset-email');
 
-Route::post('/panel/orders', [TransactionController::class,
+Route::post('/panel/orders', [OrderController::class,
 	'newOrder'])->middleware([ 'auth', 'verified' ]);
 
 Route::post('/panel/secret', [BillingController::class,
@@ -92,3 +92,7 @@ Route::post('/panel/secret', [BillingController::class,
 
 Route::get('/panel/cards', [BillingController::class,
 	'getCards'])->middleware([ 'auth', 'verified' ]);
+
+// Maybe this should have middlewares?
+Route::post('/hooks/charge',
+	[BillingController::class, 'chargeEvent']);