Example #1
0
 public function complete(Request $r)
 {
     if (!($tok = $r->input('token'))) {
         return new Response('no tok', 400);
     }
     if (!($src = $r->input('source'))) {
         return new Response('no src', 400);
     }
     try {
         $token = new BookingToken();
         $token->token = $tok;
         $token->disposition = BookingToken::FRESH;
         $token->source = BookingToken::classify($src);
         $token->validateToken();
         $token->save();
     } catch (\Illuminate\Database\QueryException $e) {
         // Integrity violation -> dupe token?
         if ($e->getCode() == 23000) {
             return new Response('duplicate token', 410);
         }
         throw $e;
     } catch (\Demeter\BookingTokenException $e) {
         return new Response('Bad token', 400);
     }
     $comp = $src == BookingToken::TYPE_COMP;
     $doStripe = $src == BookingToken::TYPE_STRIPE;
     $invalid = FALSE;
     DB::beginTransaction();
     $seatSet = app(SeatsetController::class)->getSS(FALSE);
     if (!$seatSet) {
         $token->disposition = BookingToken::NO_SS;
         $token->save();
         DB::commit();
         return new Response('No SS', 404);
     }
     try {
         DB::table('seat_sets')->where('id', $seatSet->id)->sharedLock()->get();
         // May have changed pending the lock, so let's refresh
         $seatSet->fresh();
     } catch (\Illuminate\Database\QueryException $e) {
         DB::commit();
         return new Response('no lock', 503);
     }
     if (!$seatSet->ephemeral || $seatSet->annulled) {
         $token->disposition = BookingToken::SS_INVALID;
         $token->save();
         DB::commit();
         return new Response('SS Invalid', 409);
     }
     try {
         $cust = new Customer();
         foreach (['email' => 'email', 'pymtAddrLine1' => 'addrLine', 'pymtAddrCity' => 'addrCity', 'pymtAddrZip' => 'addrPostcode', 'pymtAddrCountry' => 'addrCountry'] as $input => $field) {
             $cust->{$field} = $r->input($input);
         }
         $cust->save();
         $booking = new Booking();
         $booking->name = $r->input('name');
         $booking->state = BookingState::BOOKED;
         $booking->token()->associate($token);
         $booking->customer()->associate($cust);
         $booking->seatSet()->associate($seatSet);
         $totals = $this->determineCurrentTotals($seatSet, $comp, $doStripe);
         $booking->net = $totals['net'];
         $booking->gross = $totals['gross'];
         $booking->fees = $totals['fee'];
         $booking->save();
         $seatSet->ephemeral = FALSE;
         $seatSet->freezePrices($comp);
         $seatSet->save();
         $token->disposition = BookingToken::READY;
         $token->save();
         DB::commit();
     } catch (\Illuminate\Database\QueryException $e) {
         // If something went wrong here, we probably had
         // bad/missing data.
         DB::rollback();
         $token->disposition = BookingToken::BOOK_FAIL;
         $token->save();
         error_log($e);
         return new Response('sql bounce', 400);
     }
     $bookData = ['booking' => $booking->id];
     if (!$doStripe || $this->takePayment($booking, $token, $declined, $e)) {
         DB::transaction(function () use($booking, $token) {
             $booking->state = BookingState::CONFIRMED;
             $token->disposition = BookingToken::CHARGED_OK;
             $booking->save();
             $token->save();
         });
         return $bookData;
     } else {
         DB::transaction(function () use($booking, $token, $seatSet, $declined, $e) {
             $booking->state = BookingState::ABORTED;
             $token->disposition = $declined ? BookingToken::CHARGED_DECLINED : BookingToken::CHARGED_FAIL;
             $seatSet->ephemeral = TRUE;
             error_log($e);
             // TODO: Store charge exception
             $booking->save();
             $token->save();
             $seatSet->save();
         });
         return new Response($bookData, 402);
     }
 }