@@ -19,7 +19,6 @@ class BillingController extends Controller | |||||
//Should validate that all amounts are positive integers in a reasonable range | //Should validate that all amounts are positive integers in a reasonable range | ||||
public function secret(Request $request) { | public function secret(Request $request) { | ||||
Stripe::setApiKey(env('STRIPE_SECRET')); | Stripe::setApiKey(env('STRIPE_SECRET')); | ||||
Log::debug($request->packs); | |||||
$amount = $request->packs[ 'credits10' ]*1099 + | $amount = $request->packs[ 'credits10' ]*1099 + | ||||
$request->packs[ 'credits50' ]*5499 + $request->packs[ 'credits100' ]*10999 | $request->packs[ 'credits50' ]*5499 + $request->packs[ 'credits100' ]*10999 | ||||
@@ -28,18 +27,17 @@ class BillingController extends Controller | |||||
$transaction = new Transaction; | $transaction = new Transaction; | ||||
$transaction->credits = $request->packs['credits10']*10 + | $transaction->credits = $request->packs['credits10']*10 + | ||||
$request->packs['credits50']*50 + | $request->packs['credits50']*50 + | ||||
$request->packs['credits[100]']*100 + | $request->packs['credits100']*100 + | ||||
$request->packs['credits[1000]']*1000; | $request->packs['credits1000']*1000; | ||||
$transaction->credits_extra = | $transaction->credits_extra = | ||||
$request->packs['credits50']*5 + | $request->packs['credits50']*5 + | ||||
$request->packs['credits[100]']*10 + | $request->packs['credits100']*10 + | ||||
$request->packs['credits[1000]']*150; | $request->packs['credits1000']*150; | ||||
$transaction->user_id = Auth::user()->id; | $transaction->user_id = Auth::user()->id; | ||||
$transaction->charge = $amount; | $transaction->charge = $amount; | ||||
$transaction->status = 'processing'; | $transaction->status = 'processing'; | ||||
$transaction->completed = false; | $transaction->completed = false; | ||||
$transaction->save(); | |||||
$intent = PaymentIntent::create([ | $intent = PaymentIntent::create([ | ||||
'amount' => $amount, | 'amount' => $amount, | ||||
@@ -47,15 +45,39 @@ class BillingController extends Controller | |||||
'customer' => Auth::user()->customer_id, | 'customer' => Auth::user()->customer_id, | ||||
'metadata' => ['transaction_id' => $transaction->id] | 'metadata' => ['transaction_id' => $transaction->id] | ||||
]); | ]); | ||||
$transaction->intent_id = $intent->id; | |||||
$transaction->save(); | |||||
return $intent->client_secret; | return $intent->client_secret; | ||||
} | } | ||||
public function getCards() { | public function getCards() { | ||||
Stripe::setApiKey(env('STRIPE_SECRET')); | Stripe::setApiKey(env('STRIPE_SECRET')); | ||||
return PaymentMethod::all([ | return PaymentMethod::all([ | ||||
'customer' => Auth::user()->customer_id, | 'customer' => Auth::user()->customer_id, | ||||
'type' => 'card' | '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(); | |||||
} | |||||
} | |||||
} | } |
@@ -8,7 +8,7 @@ use App\Models\Service; | |||||
use Illuminate\Support\Facades\Auth; | use Illuminate\Support\Facades\Auth; | ||||
use Illuminate\Support\Facades\Log; | use Illuminate\Support\Facades\Log; | ||||
class TransactionController extends Controller | class OrderController extends Controller | ||||
{ | { | ||||
//THis should also reduce user's available credits | //THis should also reduce user's available credits | ||||
public function newOrder(Request $request) { | public function newOrder(Request $request) { |
@@ -12,6 +12,6 @@ class VerifyCsrfToken extends Middleware | |||||
* @var array | * @var array | ||||
*/ | */ | ||||
protected $except = [ | protected $except = [ | ||||
// | 'hooks/*' | ||||
]; | ]; | ||||
} | } |
@@ -20,6 +20,7 @@ class CreateTransactionsTable extends Migration | |||||
$table->integer('credits')->unsigned(); | $table->integer('credits')->unsigned(); | ||||
$table->integer('credits_extra')->unsigned()->default(0); | $table->integer('credits_extra')->unsigned()->default(0); | ||||
$table->string('status'); | $table->string('status'); | ||||
$table->string('intent_id')->unique(); | |||||
$table->boolean('completed'); | $table->boolean('completed'); | ||||
$table->string('note')->nullable(); | $table->string('note')->nullable(); | ||||
$table->timestamps(); | $table->timestamps(); | ||||
@@ -81,7 +81,6 @@ function getSecret() { | |||||
//Gets key from the server then sends it with stripe | //Gets key from the server then sends it with stripe | ||||
//Maybe it should asl attach the user's receipt email | //Maybe it should asl attach the user's receipt email | ||||
function pay() { | function pay() { | ||||
console.log('paying') | |||||
this.getSecret().then(secret => { | this.getSecret().then(secret => { | ||||
if (!secret) {return} | if (!secret) {return} | ||||
this.loading = true | this.loading = true | ||||
@@ -105,8 +104,7 @@ function pay() { | |||||
document.getElementById('payment-error').textContent = | document.getElementById('payment-error').textContent = | ||||
result.error.message | result.error.message | ||||
} else if (result.paymentIntent.status === 'succeeded') { | } else if (result.paymentIntent.status === 'succeeded') { | ||||
document.getElementById('payment-error').textContent = | this.complete() | ||||
'Purchase completed' | |||||
} else { | } else { | ||||
document.getElementById('payment-error').textContent = | document.getElementById('payment-error').textContent = | ||||
'An unknown error occured' | 'An unknown error occured' | ||||
@@ -123,11 +121,12 @@ function getCards() { | |||||
'X-XSRF-TOKEN': this.token} | 'X-XSRF-TOKEN': this.token} | ||||
}).then((response) => {response.json().then(data => { | }).then((response) => {response.json().then(data => { | ||||
this.cards = data.data | this.cards = data.data | ||||
if (this.cards) { | if (this.cards && this.cards.length > 0) { | ||||
this.picked = this.cards[0].id | this.picked = this.cards[0].id | ||||
} | } | ||||
})}) | })}) | ||||
} | } | ||||
function ready() { | function ready() { | ||||
return this.total != 0 && !this.loading && ((this.cardValid && | return this.total != 0 && !this.loading && ((this.cardValid && | ||||
this.billingName) || this.picked) | this.billingName) || this.picked) | ||||
@@ -1,6 +1,6 @@ | |||||
<template> | <template> | ||||
<template v-if="!loading"> | <template v-if="!loading"> | ||||
<sidebar :active="active"></sidebar> | <sidebar :role="user.role" :active="active"></sidebar> | ||||
<transition name="fade" mode="out-in"> | <transition name="fade" mode="out-in"> | ||||
<div v-if="active === ''" id="main"> | <div v-if="active === ''" id="main"> | ||||
<section class="welcome-pane"><h3>Welcome, {{user.name}}!</h3></section> | <section class="welcome-pane"><h3>Welcome, {{user.name}}!</h3></section> | ||||
@@ -15,7 +15,7 @@ | |||||
return {} | return {} | ||||
}, | }, | ||||
mounted() { | mounted() { | ||||
if (this.cards) { | if (this.cards && this.cards.length > 0) { | ||||
this.$emit('update:pickedCard', this.cards[0].id) | this.$emit('update:pickedCard', this.cards[0].id) | ||||
} | } | ||||
}, | }, | ||||
@@ -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"/> | <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> | </svg> | ||||
</a> | </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"> | <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"/> | <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> | </svg> | ||||
@@ -31,7 +31,7 @@ | |||||
<script> | <script> | ||||
export default { | export default { | ||||
props: ['active'] | props: ['active', 'role'] | ||||
} | } | ||||
</script> | </script> | ||||
@@ -3,7 +3,7 @@ | |||||
use Illuminate\Support\Facades\Route; | use Illuminate\Support\Facades\Route; | ||||
use App\Http\Controllers\UserController; | use App\Http\Controllers\UserController; | ||||
use App\Http\Controllers\ServiceController; | use App\Http\Controllers\ServiceController; | ||||
use App\Http\Controllers\TransactionController; | use App\Http\Controllers\OrderController; | ||||
use App\Http\Controllers\BillingController; | use App\Http\Controllers\BillingController; | ||||
use Illuminate\Foundation\Auth\EmailVerificationRequest; | use Illuminate\Foundation\Auth\EmailVerificationRequest; | ||||
use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||
@@ -84,7 +84,7 @@ Route::post('/panel/change-password', [UserController::class, | |||||
Route::get('/reset-email', [UserController::class, | Route::get('/reset-email', [UserController::class, | ||||
'resetEmail'])->name('reset-email'); | 'resetEmail'])->name('reset-email'); | ||||
Route::post('/panel/orders', [TransactionController::class, | Route::post('/panel/orders', [OrderController::class, | ||||
'newOrder'])->middleware([ 'auth', 'verified' ]); | 'newOrder'])->middleware([ 'auth', 'verified' ]); | ||||
Route::post('/panel/secret', [BillingController::class, | Route::post('/panel/secret', [BillingController::class, | ||||
@@ -92,3 +92,7 @@ Route::post('/panel/secret', [BillingController::class, | |||||
Route::get('/panel/cards', [BillingController::class, | Route::get('/panel/cards', [BillingController::class, | ||||
'getCards'])->middleware([ 'auth', 'verified' ]); | 'getCards'])->middleware([ 'auth', 'verified' ]); | ||||
// Maybe this should have middlewares? | |||||
Route::post('/hooks/charge', | |||||
[BillingController::class, 'chargeEvent']); |