public function completeOffsitePurchase($input)
 {
     $this->input = $input;
     $ref = array_get($this->input, 'token') ?: $this->invitation->transaction_reference;
     if (method_exists($this->gateway(), 'completePurchase')) {
         $details = $this->paymentDetails();
         $response = $this->gateway()->completePurchase($details)->send();
         $ref = $response->getTransactionReference() ?: $ref;
         if ($response->isCancelled()) {
             return false;
         } elseif (!$response->isSuccessful()) {
             throw new Exception($response->getMessage());
         }
     }
     // check invoice still has balance
     if (!floatval($this->invoice()->balance)) {
         throw new Exception(trans('texts.payment_error_code', ['code' => 'NB']));
     }
     // check this isn't a duplicate transaction reference
     if (Payment::whereAccountId($this->invitation->account_id)->whereTransactionReference($ref)->first()) {
         throw new Exception(trans('texts.payment_error_code', ['code' => 'DT']));
     }
     return $this->createPayment($ref);
 }