diff --git a/src/app/Console/Commands/Data/Stats/CollectorCommand.php b/src/app/Console/Commands/Data/Stats/CollectorCommand.php --- a/src/app/Console/Commands/Data/Stats/CollectorCommand.php +++ b/src/app/Console/Commands/Data/Stats/CollectorCommand.php @@ -3,7 +3,7 @@ namespace App\Console\Commands\Data\Stats; use App\Http\Controllers\API\V4\Admin\StatsController; -use App\Providers\PaymentProvider; +use App\Payment; use App\User; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; @@ -44,7 +44,7 @@ // A subquery to get the all wallets with a successful payment $payments = DB::table('payments') ->selectRaw('distinct wallet_id') - ->where('status', PaymentProvider::STATUS_PAID); + ->where('status', Payment::STATUS_PAID); // A subquery to get users' wallets (by entitlement) - one record per user $wallets = DB::table('entitlements') diff --git a/src/app/Documents/Receipt.php b/src/app/Documents/Receipt.php --- a/src/app/Documents/Receipt.php +++ b/src/app/Documents/Receipt.php @@ -3,7 +3,6 @@ namespace App\Documents; use App\Payment; -use App\Providers\PaymentProvider; use App\User; use App\Wallet; use Barryvdh\DomPDF\Facade\Pdf; @@ -162,7 +161,7 @@ } else { $customer = $this->customerData(); $items = $this->wallet->payments() - ->where('status', PaymentProvider::STATUS_PAID) + ->where('status', Payment::STATUS_PAID) ->where('updated_at', '>=', $start) ->where('updated_at', '<', $end) ->where('amount', '<>', 0) @@ -188,9 +187,9 @@ $type = $item->type ?? null; - if ($type == PaymentProvider::TYPE_REFUND) { + if ($type == Payment::TYPE_REFUND) { $description = \trans('documents.receipt-refund'); - } elseif ($type == PaymentProvider::TYPE_CHARGEBACK) { + } elseif ($type == Payment::TYPE_CHARGEBACK) { $description = \trans('documents.receipt-chargeback'); } else { $description = \trans('documents.receipt-item-desc', ['site' => $appName]); diff --git a/src/app/Http/Controllers/API/V4/Admin/StatsController.php b/src/app/Http/Controllers/API/V4/Admin/StatsController.php --- a/src/app/Http/Controllers/API/V4/Admin/StatsController.php +++ b/src/app/Http/Controllers/API/V4/Admin/StatsController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers\API\V4\Admin; -use App\Providers\PaymentProvider; +use App\Payment; use App\User; use Carbon\Carbon; use Illuminate\Http\Request; @@ -114,8 +114,8 @@ ->selectRaw("date_format(updated_at, '%Y-%v') as period, sum(credit_amount) as amount, wallets.currency") ->join('wallets', 'wallets.id', '=', 'wallet_id') ->where('updated_at', '>=', $start->toDateString()) - ->where('status', PaymentProvider::STATUS_PAID) - ->whereIn('type', [PaymentProvider::TYPE_ONEOFF, PaymentProvider::TYPE_RECURRING]) + ->where('status', Payment::STATUS_PAID) + ->whereIn('type', [Payment::TYPE_ONEOFF, Payment::TYPE_RECURRING]) ->groupByRaw('period, wallets.currency'); $addTenantScope = function ($builder, $tenantId) { diff --git a/src/app/Http/Controllers/API/V4/PaymentsController.php b/src/app/Http/Controllers/API/V4/PaymentsController.php --- a/src/app/Http/Controllers/API/V4/PaymentsController.php +++ b/src/app/Http/Controllers/API/V4/PaymentsController.php @@ -3,10 +3,10 @@ namespace App\Http\Controllers\API\V4; use App\Http\Controllers\Controller; +use App\Payment; use App\Providers\PaymentProvider; use App\Tenant; use App\Wallet; -use App\Payment; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; @@ -169,14 +169,14 @@ // It has to be at least minimum payment amount and must cover current debt if ( $wallet->balance < 0 - && $wallet->balance <= PaymentProvider::MIN_AMOUNT * -1 + && $wallet->balance <= Payment::MIN_AMOUNT * -1 && $wallet->balance + $amount < 0 ) { return ['amount' => \trans('validation.minamountdebt')]; } - if ($amount < PaymentProvider::MIN_AMOUNT) { - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + if ($amount < Payment::MIN_AMOUNT) { + $min = $wallet->money(Payment::MIN_AMOUNT); return ['amount' => \trans('validation.minamount', ['amount' => $min])]; } @@ -213,8 +213,8 @@ $amount = (int) ($request->amount * 100); // Validate the minimum value - if ($amount < PaymentProvider::MIN_AMOUNT) { - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + if ($amount < Payment::MIN_AMOUNT) { + $min = $wallet->money(Payment::MIN_AMOUNT); $errors = ['amount' => \trans('validation.minamount', ['amount' => $min])]; return response()->json(['status' => 'error', 'errors' => $errors], 422); } @@ -222,7 +222,7 @@ $currency = $request->currency; $request = [ - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'currency' => $currency, 'amount' => $amount, 'methodId' => $request->methodId ?: PaymentProvider::METHOD_CREDITCARD, @@ -337,7 +337,7 @@ } $request = [ - 'type' => PaymentProvider::TYPE_RECURRING, + 'type' => Payment::TYPE_RECURRING, 'currency' => $wallet->currency, 'amount' => $amount, 'methodId' => PaymentProvider::METHOD_CREDITCARD, @@ -366,7 +366,7 @@ // Get the Mandate info $mandate = (array) $provider->getMandate($wallet); - $mandate['amount'] = (int) (PaymentProvider::MIN_AMOUNT / 100); + $mandate['amount'] = (int) (Payment::MIN_AMOUNT / 100); $mandate['balance'] = 0; $mandate['isDisabled'] = !empty($mandate['id']) && $settings['mandate_disabled']; @@ -415,11 +415,11 @@ $wallet = $user->wallets()->first(); $exists = Payment::where('wallet_id', $wallet->id) - ->where('type', PaymentProvider::TYPE_ONEOFF) + ->where('type', Payment::TYPE_ONEOFF) ->whereIn('status', [ - PaymentProvider::STATUS_OPEN, - PaymentProvider::STATUS_PENDING, - PaymentProvider::STATUS_AUTHORIZED + Payment::STATUS_OPEN, + Payment::STATUS_PENDING, + Payment::STATUS_AUTHORIZED ]) ->exists(); @@ -447,11 +447,11 @@ $page = intval(request()->input('page')) ?: 1; $hasMore = false; $result = Payment::where('wallet_id', $wallet->id) - ->where('type', PaymentProvider::TYPE_ONEOFF) + ->where('type', Payment::TYPE_ONEOFF) ->whereIn('status', [ - PaymentProvider::STATUS_OPEN, - PaymentProvider::STATUS_PENDING, - PaymentProvider::STATUS_AUTHORIZED + Payment::STATUS_OPEN, + Payment::STATUS_PENDING, + Payment::STATUS_AUTHORIZED ]) ->orderBy('created_at', 'desc') ->limit($pageSize + 1) diff --git a/src/app/Http/Controllers/API/V4/PolicyController.php b/src/app/Http/Controllers/API/V4/PolicyController.php --- a/src/app/Http/Controllers/API/V4/PolicyController.php +++ b/src/app/Http/Controllers/API/V4/PolicyController.php @@ -3,7 +3,6 @@ namespace App\Http\Controllers\API\V4; use App\Http\Controllers\Controller; -use App\Providers\PaymentProvider; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Validator; diff --git a/src/app/Http/Controllers/API/V4/WalletsController.php b/src/app/Http/Controllers/API/V4/WalletsController.php --- a/src/app/Http/Controllers/API/V4/WalletsController.php +++ b/src/app/Http/Controllers/API/V4/WalletsController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\API\V4; +use App\Payment; use App\Transaction; use App\Wallet; use App\Http\Controllers\ResourceController; @@ -36,7 +37,7 @@ $result = $wallet->toArray(); - $provider = \App\Providers\PaymentProvider::factory($wallet); + $provider = PaymentProvider::factory($wallet); $result['provider'] = $provider->name(); $result['notice'] = $this->getWalletNotice($wallet); @@ -116,7 +117,7 @@ $result = $wallet->payments() ->selectRaw('distinct date_format(updated_at, "%Y-%m") as ident') - ->where('status', PaymentProvider::STATUS_PAID) + ->where('status', Payment::STATUS_PAID) ->where('amount', '<>', 0) ->orderBy('ident', 'desc') ->get() diff --git a/src/app/Jobs/PaymentEmail.php b/src/app/Jobs/PaymentEmail.php --- a/src/app/Jobs/PaymentEmail.php +++ b/src/app/Jobs/PaymentEmail.php @@ -3,7 +3,6 @@ namespace App\Jobs; use App\Payment; -use App\Providers\PaymentProvider; use App\User; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; @@ -65,12 +64,12 @@ return; } - if ($this->payment->status == PaymentProvider::STATUS_PAID) { + if ($this->payment->status == Payment::STATUS_PAID) { $mail = new \App\Mail\PaymentSuccess($this->payment, $this->controller); $label = "Success"; } elseif ( - $this->payment->status == PaymentProvider::STATUS_EXPIRED - || $this->payment->status == PaymentProvider::STATUS_FAILED + $this->payment->status == Payment::STATUS_EXPIRED + || $this->payment->status == Payment::STATUS_FAILED ) { $mail = new \App\Mail\PaymentFailure($this->payment, $this->controller); $label = "Failure"; diff --git a/src/app/Payment.php b/src/app/Payment.php --- a/src/app/Payment.php +++ b/src/app/Payment.php @@ -2,7 +2,6 @@ namespace App; -use App\Providers\PaymentProvider; use Dyrynda\Database\Support\NullableFields; use Illuminate\Database\Eloquent\Model; @@ -23,6 +22,23 @@ { use NullableFields; + public const STATUS_OPEN = 'open'; + public const STATUS_CANCELED = 'canceled'; + public const STATUS_PENDING = 'pending'; + public const STATUS_AUTHORIZED = 'authorized'; + public const STATUS_EXPIRED = 'expired'; + public const STATUS_FAILED = 'failed'; + public const STATUS_PAID = 'paid'; + + public const TYPE_ONEOFF = 'oneoff'; + public const TYPE_RECURRING = 'recurring'; + public const TYPE_MANDATE = 'mandate'; + public const TYPE_REFUND = 'refund'; + public const TYPE_CHARGEBACK = 'chargeback'; + + /** const int Minimum amount of money in a single payment (in cents) */ + public const MIN_AMOUNT = 1000; + /** @var bool Indicates that the model should be timestamped or not */ public $incrementing = false; @@ -69,7 +85,7 @@ $db_payment = new Payment(); $db_payment->id = $payment['id']; $db_payment->description = $payment['description'] ?? ''; - $db_payment->status = $payment['status'] ?? PaymentProvider::STATUS_OPEN; + $db_payment->status = $payment['status'] ?? self::STATUS_OPEN; $db_payment->amount = $payment['amount'] ?? 0; $db_payment->credit_amount = $payment['credit_amount'] ?? ($payment['amount'] ?? 0); $db_payment->vat_rate_id = $payment['vat_rate_id'] ?? null; @@ -83,6 +99,26 @@ return $db_payment; } + /** + * Apply the successful payment's pecunia to the wallet + * + * @param string $method Payment method name + */ + public function credit($method): void + { + // TODO: Possibly we should sanity check that payment is paid, and not negative? + // TODO: Localization? + $description = $this->type == self::TYPE_RECURRING ? 'Auto-payment' : 'Payment'; + $description .= " transaction {$this->id} using {$method}"; + + $this->wallet->credit($this, $description); + + // Unlock the disabled auto-payment mandate + if ($this->wallet->balance >= 0) { + $this->wallet->setSetting('mandate_disabled', null); + } + } + /** * Creates a payment and transaction records for the refund/chargeback operation. * Deducts an amount of pecunia from the wallet. @@ -108,7 +144,7 @@ } // Apply the refund to the wallet balance - $method = $refund['type'] == PaymentProvider::TYPE_CHARGEBACK ? 'chargeback' : 'refund'; + $method = $refund['type'] == self::TYPE_CHARGEBACK ? 'chargeback' : 'refund'; $this->wallet->{$method}($credit_amount, $refund['description'] ?? ''); @@ -119,7 +155,7 @@ $refund['wallet_id'] = $this->wallet_id; $refund['provider'] = $this->provider; $refund['vat_rate_id'] = $this->vat_rate_id; - $refund['status'] = PaymentProvider::STATUS_PAID; + $refund['status'] = self::STATUS_PAID; // FIXME: Refunds/chargebacks are out of the reseller comissioning for now diff --git a/src/app/Providers/Payment/Coinbase.php b/src/app/Providers/Payment/Coinbase.php --- a/src/app/Providers/Payment/Coinbase.php +++ b/src/app/Providers/Payment/Coinbase.php @@ -141,7 +141,7 @@ */ public function payment(Wallet $wallet, array $payment): ?array { - if ($payment['type'] == self::TYPE_RECURRING) { + if ($payment['type'] == Payment::TYPE_RECURRING) { throw new \Exception("not supported"); } @@ -175,7 +175,7 @@ $json = json_decode($response->getBody(), true); // Store the payment reference in database - $payment['status'] = self::STATUS_OPEN; + $payment['status'] = Payment::STATUS_OPEN; //We take the code instead of the id because it fits into our current db schema and the id doesn't $payment['id'] = $json['data']['code']; //We store in satoshis (the database stores it as INTEGER type) @@ -229,7 +229,7 @@ if ($response->getStatusCode() == 200) { $db_payment = Payment::find($paymentId); - $db_payment->status = self::STATUS_CANCELED; + $db_payment->status = Payment::STATUS_CANCELED; $db_payment->save(); } else { $this->logError("Failed to cancel payment", $response); @@ -308,19 +308,19 @@ return 200; } - $newStatus = self::STATUS_PENDING; + $newStatus = Payment::STATUS_PENDING; // Even if we receive the payment delayed, we still have the money, and therefore credit it. if ($type == 'charge:resolved' || $type == 'charge:delayed') { // The payment is paid. Update the balance - if ($payment->status != self::STATUS_PAID && $payment->amount > 0) { + if ($payment->status != Payment::STATUS_PAID && $payment->amount > 0) { $credit = true; } - $newStatus = self::STATUS_PAID; + $newStatus = Payment::STATUS_PAID; } elseif ($type == 'charge:failed') { // Note: I didn't find a way to get any description of the problem with a payment \Log::info(sprintf('Coinbase payment failed (%s)', $payment->id)); - $newStatus = self::STATUS_FAILED; + $newStatus = Payment::STATUS_FAILED; } DB::beginTransaction(); @@ -328,14 +328,14 @@ // This is a sanity check, just in case the payment provider api // sent us open -> paid -> open -> paid. So, we lock the payment after // recivied a "final" state. - $pending_states = [self::STATUS_OPEN, self::STATUS_PENDING, self::STATUS_AUTHORIZED]; + $pending_states = [Payment::STATUS_OPEN, Payment::STATUS_PENDING, Payment::STATUS_AUTHORIZED]; if (in_array($payment->status, $pending_states)) { $payment->status = $newStatus; $payment->save(); } if (!empty($credit)) { - self::creditPayment($payment); + $payment->credit('Coinbase'); } DB::commit(); @@ -343,18 +343,6 @@ return 200; } - /** - * Apply the successful payment's pecunia to the wallet - */ - protected static function creditPayment($payment) - { - // TODO: Localization? - $description = 'Payment'; - $description .= " transaction {$payment->id} using Coinbase"; - - $payment->wallet->credit($payment, $description); - } - /** * List supported payment methods. * @@ -373,7 +361,7 @@ { $availableMethods = []; - if ($type == self::TYPE_ONEOFF) { + if ($type == Payment::TYPE_ONEOFF) { $availableMethods['bitcoin'] = [ 'id' => 'bitcoin', 'name' => "Bitcoin", diff --git a/src/app/Providers/Payment/Mollie.php b/src/app/Providers/Payment/Mollie.php --- a/src/app/Providers/Payment/Mollie.php +++ b/src/app/Providers/Payment/Mollie.php @@ -95,7 +95,7 @@ // Store the payment reference in database $payment['status'] = $response->status; $payment['id'] = $response->id; - $payment['type'] = self::TYPE_MANDATE; + $payment['type'] = Payment::TYPE_MANDATE; $this->storePayment($payment, $wallet->id); @@ -186,7 +186,7 @@ */ public function payment(Wallet $wallet, array $payment): ?array { - if ($payment['type'] == self::TYPE_RECURRING) { + if ($payment['type'] == Payment::TYPE_RECURRING) { return $this->paymentRecurring($wallet, $payment); } @@ -232,7 +232,6 @@ ]; } - /** * Cancel a pending payment. * @@ -252,7 +251,6 @@ return true; } - /** * Create a new automatic payment operation. * @@ -362,9 +360,9 @@ if ($mollie_payment->isPaid()) { // The payment is paid. Update the balance, and notify the user - if ($payment->status != self::STATUS_PAID && $payment->amount > 0) { + if ($payment->status != Payment::STATUS_PAID && $payment->amount > 0) { $credit = true; - $notify = $payment->type == self::TYPE_RECURRING; + $notify = $payment->type == Payment::TYPE_RECURRING; } // The payment has been (partially) refunded. @@ -376,7 +374,7 @@ 'id' => $refund->id, 'description' => $refund->description, 'amount' => round(floatval($refund->amount->value) * 100), - 'type' => self::TYPE_REFUND, + 'type' => Payment::TYPE_REFUND, 'currency' => $refund->amount->currency ]; } @@ -391,7 +389,7 @@ $refunds[] = [ 'id' => $chargeback->id, 'amount' => round(floatval($chargeback->amount->value) * 100), - 'type' => self::TYPE_CHARGEBACK, + 'type' => Payment::TYPE_CHARGEBACK, 'currency' => $chargeback->amount->currency ]; } @@ -403,7 +401,7 @@ // pointing to the one from the last payment not the successful one. // We make sure to use mandate id from the successful "first" payment. if ( - $payment->type == self::TYPE_MANDATE + $payment->type == Payment::TYPE_MANDATE && $mollie_payment->mandateId && $mollie_payment->sequenceType == Types\SequenceType::SEQUENCETYPE_FIRST ) { @@ -414,7 +412,7 @@ \Log::info(sprintf('Mollie payment failed (%s)', $payment->id)); // Disable the mandate - if ($payment->type == self::TYPE_RECURRING) { + if ($payment->type == Payment::TYPE_RECURRING) { $notify = true; $payment->wallet->setSetting('mandate_disabled', 1); } @@ -425,7 +423,7 @@ // This is a sanity check, just in case the payment provider api // sent us open -> paid -> open -> paid. So, we lock the payment after // recivied a "final" state. - $pending_states = [self::STATUS_OPEN, self::STATUS_PENDING, self::STATUS_AUTHORIZED]; + $pending_states = [Payment::STATUS_OPEN, Payment::STATUS_PENDING, Payment::STATUS_AUTHORIZED]; if (in_array($payment->status, $pending_states)) { $payment->status = $mollie_payment->status; $payment->save(); @@ -513,16 +511,7 @@ // Extract the payment method for transaction description $method = self::paymentMethod($mollie_payment, 'Mollie'); - // TODO: Localization? - $description = $payment->type == self::TYPE_RECURRING ? 'Auto-payment' : 'Payment'; - $description .= " transaction {$payment->id} using {$method}"; - - $payment->wallet->credit($payment, $description); - - // Unlock the disabled auto-payment mandate - if ($payment->wallet->balance >= 0) { - $payment->wallet->setSetting('mandate_disabled', null); - } + $payment->credit($method); } /** diff --git a/src/app/Providers/Payment/Stripe.php b/src/app/Providers/Payment/Stripe.php --- a/src/app/Providers/Payment/Stripe.php +++ b/src/app/Providers/Payment/Stripe.php @@ -87,7 +87,7 @@ $payment['currency_amount'] = 0; $payment['vat_rate_id'] = null; $payment['id'] = $session->setup_intent; - $payment['type'] = self::TYPE_MANDATE; + $payment['type'] = Payment::TYPE_MANDATE; $this->storePayment($payment, $wallet->id); @@ -177,7 +177,7 @@ */ public function payment(Wallet $wallet, array $payment): ?array { - if ($payment['type'] == self::TYPE_RECURRING) { + if ($payment['type'] == Payment::TYPE_RECURRING) { return $this->paymentRecurring($wallet, $payment); } @@ -292,26 +292,26 @@ $intent = $event->data->object; // @phpstan-ignore-line $payment = Payment::find($intent->id); - if (empty($payment) || $payment->type == self::TYPE_MANDATE) { + if (empty($payment) || $payment->type == Payment::TYPE_MANDATE) { return 404; } switch ($intent->status) { case StripeAPI\PaymentIntent::STATUS_CANCELED: - $status = self::STATUS_CANCELED; + $status = Payment::STATUS_CANCELED; break; case StripeAPI\PaymentIntent::STATUS_SUCCEEDED: - $status = self::STATUS_PAID; + $status = Payment::STATUS_PAID; break; default: - $status = self::STATUS_FAILED; + $status = Payment::STATUS_FAILED; } DB::beginTransaction(); - if ($status == self::STATUS_PAID) { + if ($status == Payment::STATUS_PAID) { // Update the balance, if it wasn't already - if ($payment->status != self::STATUS_PAID) { + if ($payment->status != Payment::STATUS_PAID) { $this->creditPayment($payment, $intent); } } else { @@ -325,13 +325,13 @@ } } - if ($payment->status != self::STATUS_PAID) { + if ($payment->status != Payment::STATUS_PAID) { $payment->status = $status; $payment->save(); - if ($status != self::STATUS_CANCELED && $payment->type == self::TYPE_RECURRING) { + if ($status != Payment::STATUS_CANCELED && $payment->type == Payment::TYPE_RECURRING) { // Disable the mandate - if ($status == self::STATUS_FAILED) { + if ($status == Payment::STATUS_FAILED) { $payment->wallet->setSetting('mandate_disabled', 1); } @@ -350,27 +350,27 @@ $intent = $event->data->object; // @phpstan-ignore-line $payment = Payment::find($intent->id); - if (empty($payment) || $payment->type != self::TYPE_MANDATE) { + if (empty($payment) || $payment->type != Payment::TYPE_MANDATE) { return 404; } switch ($intent->status) { case StripeAPI\SetupIntent::STATUS_CANCELED: - $status = self::STATUS_CANCELED; + $status = Payment::STATUS_CANCELED; break; case StripeAPI\SetupIntent::STATUS_SUCCEEDED: - $status = self::STATUS_PAID; + $status = Payment::STATUS_PAID; break; default: - $status = self::STATUS_FAILED; + $status = Payment::STATUS_FAILED; } - if ($status == self::STATUS_PAID) { + if ($status == Payment::STATUS_PAID) { $payment->wallet->setSetting('stripe_mandate_id', $intent->id); $threshold = intval((float) $payment->wallet->getSetting('mandate_balance') * 100); // Top-up the wallet if balance is below the threshold - if ($payment->wallet->balance < $threshold && $payment->status != self::STATUS_PAID) { + if ($payment->wallet->balance < $threshold && $payment->status != Payment::STATUS_PAID) { \App\Jobs\WalletCharge::dispatch($payment->wallet); } } @@ -451,16 +451,7 @@ $method = self::paymentMethod($pm); } - // TODO: Localization? - $description = $payment->type == self::TYPE_RECURRING ? 'Auto-payment' : 'Payment'; - $description .= " transaction {$payment->id} using {$method}"; - - $payment->wallet->credit($payment, $description); - - // Unlock the disabled auto-payment mandate - if ($payment->wallet->balance >= 0) { - $payment->wallet->setSetting('mandate_disabled', null); - } + $payment->credit($method); } /** @@ -500,30 +491,30 @@ //TODO get this from the stripe API? $availableMethods = []; switch ($type) { - case self::TYPE_ONEOFF: + case Payment::TYPE_ONEOFF: $availableMethods = [ self::METHOD_CREDITCARD => [ 'id' => self::METHOD_CREDITCARD, 'name' => "Credit Card", - 'minimumAmount' => self::MIN_AMOUNT, + 'minimumAmount' => Payment::MIN_AMOUNT, 'currency' => $currency, 'exchangeRate' => 1.0 ], self::METHOD_PAYPAL => [ 'id' => self::METHOD_PAYPAL, 'name' => "PayPal", - 'minimumAmount' => self::MIN_AMOUNT, + 'minimumAmount' => Payment::MIN_AMOUNT, 'currency' => $currency, 'exchangeRate' => 1.0 ] ]; break; - case self::TYPE_RECURRING: + case Payment::TYPE_RECURRING: $availableMethods = [ self::METHOD_CREDITCARD => [ 'id' => self::METHOD_CREDITCARD, 'name' => "Credit Card", - 'minimumAmount' => self::MIN_AMOUNT, // Converted to cents, + 'minimumAmount' => Payment::MIN_AMOUNT, // Converted to cents, 'currency' => $currency, 'exchangeRate' => 1.0 ] diff --git a/src/app/Providers/PaymentProvider.php b/src/app/Providers/PaymentProvider.php --- a/src/app/Providers/PaymentProvider.php +++ b/src/app/Providers/PaymentProvider.php @@ -2,27 +2,13 @@ namespace App\Providers; -use App\Transaction; use App\Payment; +use App\Transaction; use App\Wallet; use Illuminate\Support\Facades\Cache; abstract class PaymentProvider { - public const STATUS_OPEN = 'open'; - public const STATUS_CANCELED = 'canceled'; - public const STATUS_PENDING = 'pending'; - public const STATUS_AUTHORIZED = 'authorized'; - public const STATUS_EXPIRED = 'expired'; - public const STATUS_FAILED = 'failed'; - public const STATUS_PAID = 'paid'; - - public const TYPE_ONEOFF = 'oneoff'; - public const TYPE_RECURRING = 'recurring'; - public const TYPE_MANDATE = 'mandate'; - public const TYPE_REFUND = 'refund'; - public const TYPE_CHARGEBACK = 'chargeback'; - public const METHOD_CREDITCARD = 'creditcard'; public const METHOD_PAYPAL = 'paypal'; public const METHOD_BANKTRANSFER = 'banktransfer'; @@ -33,9 +19,6 @@ public const PROVIDER_STRIPE = 'stripe'; public const PROVIDER_COINBASE = 'coinbase'; - /** const int Minimum amount of money in a single payment (in cents) */ - public const MIN_AMOUNT = 1000; - private static $paymentMethodIcons = [ self::METHOD_CREDITCARD => ['prefix' => 'far', 'name' => 'credit-card'], self::METHOD_PAYPAL => ['prefix' => 'fab', 'name' => 'paypal'], @@ -248,10 +231,10 @@ { $methods = []; switch ($type) { - case self::TYPE_ONEOFF: + case Payment::TYPE_ONEOFF: $methods = explode(',', \config('app.payment.methods_oneoff')); break; - case PaymentProvider::TYPE_RECURRING: + case Payment::TYPE_RECURRING: $methods = explode(',', \config('app.payment.methods_recurring')); break; default: diff --git a/src/composer.json b/src/composer.json --- a/src/composer.json +++ b/src/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php": "^8.0", + "php": "^8.1", "bacon/bacon-qr-code": "^2.0", "barryvdh/laravel-dompdf": "^2.0.0", "doctrine/dbal": "^3.3.2", @@ -29,11 +29,11 @@ "mlocati/spf-lib": "^3.1", "mollie/laravel-mollie": "^2.19", "pear/crypt_gpg": "^1.6.6", - "predis/predis": "^1.1.10", + "predis/predis": "^2.0", "sabre/vobject": "^4.5", - "spatie/laravel-translatable": "^5.2", + "spatie/laravel-translatable": "^6.3", "spomky-labs/otphp": "~10.0.0", - "stripe/stripe-php": "^7.29" + "stripe/stripe-php": "^10.7" }, "require-dev": { "code-lts/doctum": "^5.5.1", diff --git a/src/tests/Browser/PaymentCoinbaseTest.php b/src/tests/Browser/PaymentCoinbaseTest.php --- a/src/tests/Browser/PaymentCoinbaseTest.php +++ b/src/tests/Browser/PaymentCoinbaseTest.php @@ -2,7 +2,6 @@ namespace Tests\Browser; -use App\Providers\PaymentProvider; use App\Wallet; use Tests\Browser; use Tests\Browser\Components\Dialog; diff --git a/src/tests/Browser/PaymentMollieTest.php b/src/tests/Browser/PaymentMollieTest.php --- a/src/tests/Browser/PaymentMollieTest.php +++ b/src/tests/Browser/PaymentMollieTest.php @@ -2,7 +2,7 @@ namespace Tests\Browser; -use App\Providers\PaymentProvider; +use App\Payment; use App\Wallet; use Tests\Browser; use Tests\Browser\Components\Dialog; @@ -118,7 +118,7 @@ ->with(new Dialog('@payment-dialog'), function (Browser $browser) { $browser->assertSeeIn('@title', 'Set up auto-payment') ->assertSeeIn('@body label[for="mandate_amount"]', 'Fill up by') - ->assertValue('@body #mandate_amount', PaymentProvider::MIN_AMOUNT / 100) + ->assertValue('@body #mandate_amount', Payment::MIN_AMOUNT / 100) ->assertSeeIn('@body label[for="mandate_balance"]', 'when account balance is below') // phpcs:ignore ->assertValue('@body #mandate_balance', '0') ->assertSeeIn('@button-cancel', 'Cancel') diff --git a/src/tests/Browser/PaymentStripeTest.php b/src/tests/Browser/PaymentStripeTest.php --- a/src/tests/Browser/PaymentStripeTest.php +++ b/src/tests/Browser/PaymentStripeTest.php @@ -2,7 +2,7 @@ namespace Tests\Browser; -use App\Providers\PaymentProvider; +use App\Payment; use App\Wallet; use Tests\Browser; use Tests\Browser\Components\Dialog; @@ -125,7 +125,7 @@ ->with(new Dialog('@payment-dialog'), function (Browser $browser) { $browser->assertSeeIn('@title', 'Set up auto-payment') ->assertSeeIn('@body label[for="mandate_amount"]', 'Fill up by') - ->assertValue('@body #mandate_amount', PaymentProvider::MIN_AMOUNT / 100) + ->assertValue('@body #mandate_amount', Payment::MIN_AMOUNT / 100) ->assertSeeIn('@body label[for="mandate_balance"]', 'when account balance is below') // phpcs:ignore ->assertValue('@body #mandate_balance', '0') ->assertSeeIn('@button-cancel', 'Cancel') diff --git a/src/tests/Browser/Reseller/PaymentMollieTest.php b/src/tests/Browser/Reseller/PaymentMollieTest.php --- a/src/tests/Browser/Reseller/PaymentMollieTest.php +++ b/src/tests/Browser/Reseller/PaymentMollieTest.php @@ -2,7 +2,6 @@ namespace Tests\Browser\Reseller; -use App\Providers\PaymentProvider; use App\Wallet; use Tests\Browser; use Tests\Browser\Components\Dialog; diff --git a/src/tests/Browser/Reseller/WalletTest.php b/src/tests/Browser/Reseller/WalletTest.php --- a/src/tests/Browser/Reseller/WalletTest.php +++ b/src/tests/Browser/Reseller/WalletTest.php @@ -3,7 +3,6 @@ namespace Tests\Browser\Reseller; use App\Payment; -use App\Providers\PaymentProvider; use App\Transaction; use App\Wallet; use Carbon\Carbon; @@ -132,8 +131,8 @@ $date = Carbon::create(intval(date('Y')) - 1, 3, 30); $payment = Payment::create([ 'id' => 'AAA1', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in March', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -149,8 +148,8 @@ $date = Carbon::create(intval(date('Y')) - 1, 4, 30); $payment = Payment::create([ 'id' => 'AAA2', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in April', 'wallet_id' => $wallet->id, 'provider' => 'stripe', diff --git a/src/tests/Browser/WalletTest.php b/src/tests/Browser/WalletTest.php --- a/src/tests/Browser/WalletTest.php +++ b/src/tests/Browser/WalletTest.php @@ -3,7 +3,6 @@ namespace Tests\Browser; use App\Payment; -use App\Providers\PaymentProvider; use App\Transaction; use App\Wallet; use Carbon\Carbon; @@ -125,8 +124,8 @@ $date = Carbon::create(intval(date('Y')) - 1, 3, 30); $payment = Payment::create([ 'id' => 'AAA1', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in March', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -142,8 +141,8 @@ $date = Carbon::create(intval(date('Y')) - 1, 4, 30); $payment = Payment::create([ 'id' => 'AAA2', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in April', 'wallet_id' => $wallet->id, 'provider' => 'stripe', diff --git a/src/tests/Feature/Console/Data/Stats/CollectorTest.php b/src/tests/Feature/Console/Data/Stats/CollectorTest.php --- a/src/tests/Feature/Console/Data/Stats/CollectorTest.php +++ b/src/tests/Feature/Console/Data/Stats/CollectorTest.php @@ -3,7 +3,7 @@ namespace Tests\Feature\Console\Data\Stats; use App\Http\Controllers\API\V4\Admin\StatsController; -use App\Providers\PaymentProvider; +use App\Payment; use Illuminate\Support\Facades\DB; use Tests\TestCase; @@ -51,10 +51,10 @@ \App\Payment::create([ 'id' => 'test1', 'description' => '', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 1000, 'credit_amount' => 1000, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $wallet->id, 'provider' => 'mollie', 'currency' => $wallet->currency, diff --git a/src/tests/Feature/Controller/Admin/StatsTest.php b/src/tests/Feature/Controller/Admin/StatsTest.php --- a/src/tests/Feature/Controller/Admin/StatsTest.php +++ b/src/tests/Feature/Controller/Admin/StatsTest.php @@ -4,7 +4,6 @@ use App\Http\Controllers\API\V4\Admin\StatsController; use App\Payment; -use App\Providers\PaymentProvider; use Illuminate\Support\Facades\DB; use Tests\TestCase; @@ -132,10 +131,10 @@ Payment::create([ 'id' => 'test1', 'description' => '', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 1000, 'credit_amount' => 1000, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $wallet->id, 'provider' => 'mollie', 'currency' => 'EUR', @@ -144,10 +143,10 @@ Payment::create([ 'id' => 'test2', 'description' => '', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 2000, 'credit_amount' => 2000, - 'type' => PaymentProvider::TYPE_RECURRING, + 'type' => Payment::TYPE_RECURRING, 'wallet_id' => $wallet->id, 'provider' => 'mollie', 'currency' => 'EUR', @@ -156,10 +155,10 @@ Payment::create([ 'id' => 'test3', 'description' => '', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 3000, 'credit_amount' => 3000, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $johns_wallet->id, 'provider' => 'mollie', 'currency' => 'EUR', @@ -168,10 +167,10 @@ Payment::create([ 'id' => 'test4', 'description' => '', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 4000, 'credit_amount' => 4000, - 'type' => PaymentProvider::TYPE_RECURRING, + 'type' => Payment::TYPE_RECURRING, 'wallet_id' => $johns_wallet->id, 'provider' => 'mollie', 'currency' => 'CHF', @@ -180,10 +179,10 @@ Payment::create([ 'id' => 'test5', 'description' => '', - 'status' => PaymentProvider::STATUS_OPEN, + 'status' => Payment::STATUS_OPEN, 'amount' => 5000, 'credit_amount' => 5000, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $johns_wallet->id, 'provider' => 'mollie', 'currency' => 'CHF', @@ -192,10 +191,10 @@ Payment::create([ 'id' => 'test6', 'description' => '', - 'status' => PaymentProvider::STATUS_FAILED, + 'status' => Payment::STATUS_FAILED, 'amount' => 6000, 'credit_amount' => 6000, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $johns_wallet->id, 'provider' => 'mollie', 'currency' => 'CHF', diff --git a/src/tests/Feature/Controller/PaymentsCoinbaseTest.php b/src/tests/Feature/Controller/PaymentsCoinbaseTest.php --- a/src/tests/Feature/Controller/PaymentsCoinbaseTest.php +++ b/src/tests/Feature/Controller/PaymentsCoinbaseTest.php @@ -4,7 +4,6 @@ use App\Http\Controllers\API\V4\PaymentsController; use App\Payment; -use App\Providers\PaymentProvider; use App\Transaction; use App\Wallet; use App\WalletSetting; @@ -89,7 +88,7 @@ $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + $min = $wallet->money(Payment::MIN_AMOUNT); $this->assertSame("Minimum amount for a single payment is {$min}.", $json['errors']['amount']); // Invalid currency @@ -178,7 +177,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); $transaction = $wallet->transactions() @@ -208,7 +207,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); $post = [ @@ -225,14 +224,14 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); // Test for payment failure Bus::fake(); $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $post = [ @@ -313,7 +312,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); } @@ -389,9 +388,9 @@ $this->assertSame(1, $json['page']); $this->assertSame(false, $json['hasMore']); $this->assertCount(1, $json['list']); - $this->assertSame(PaymentProvider::STATUS_OPEN, $json['list'][0]['status']); + $this->assertSame(Payment::STATUS_OPEN, $json['list'][0]['status']); $this->assertSame('CHF', $json['list'][0]['currency']); - $this->assertSame(PaymentProvider::TYPE_ONEOFF, $json['list'][0]['type']); + $this->assertSame(Payment::TYPE_ONEOFF, $json['list'][0]['type']); $this->assertSame(1234, $json['list'][0]['amount']); $response = $this->actingAs($user)->get("api/v4/payments/has-pending"); @@ -404,7 +403,7 @@ $this->assertCount(1, $payments); $payment = $payments[0]; - $payment->status = PaymentProvider::STATUS_PAID; + $payment->status = Payment::STATUS_PAID; $payment->save(); // They payment should be gone from the pending list now @@ -430,7 +429,7 @@ $user = $this->getTestUser('john@kolab.org'); - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_ONEOFF); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_ONEOFF); $response->assertStatus(200); $json = $response->json(); @@ -438,7 +437,7 @@ $this->assertSame('bitcoin', $json[3]['id']); $this->assertSame('BTC', $json[3]['currency']); - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_RECURRING); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_RECURRING); $response->assertStatus(200); $json = $response->json(); diff --git a/src/tests/Feature/Controller/PaymentsMollieEuroTest.php b/src/tests/Feature/Controller/PaymentsMollieEuroTest.php --- a/src/tests/Feature/Controller/PaymentsMollieEuroTest.php +++ b/src/tests/Feature/Controller/PaymentsMollieEuroTest.php @@ -94,13 +94,13 @@ $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + $min = $wallet->money(Payment::MIN_AMOUNT); $this->assertSame("Minimum amount for a single payment is {$min}.", $json['errors']['amount']); $this->assertMatchesRegularExpression("/[0-9.,]+ €\.$/", $json['errors']['amount']); // Test creating a mandate (negative balance, amount too small) Wallet::where('id', $wallet->id)->update(['balance' => -2000]); - $post = ['amount' => PaymentProvider::MIN_AMOUNT / 100, 'balance' => 0]; + $post = ['amount' => Payment::MIN_AMOUNT / 100, 'balance' => 0]; $response = $this->actingAs($user)->post("api/v4/payments/mandate", $post); $response->assertStatus(422); @@ -125,7 +125,7 @@ $this->assertSame(2010, $payment->amount); $this->assertSame($wallet->id, $payment->wallet_id); $this->assertSame($user->tenant->title . " Auto-Payment Setup", $payment->description); - $this->assertSame(PaymentProvider::TYPE_MANDATE, $payment->type); + $this->assertSame(Payment::TYPE_MANDATE, $payment->type); // Test fetching the mandate information $response = $this->actingAs($user)->get("api/v4/payments/mandate"); @@ -335,7 +335,7 @@ $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + $min = $wallet->money(Payment::MIN_AMOUNT); $this->assertSame("Minimum amount for a single payment is {$min}.", $json['errors']['amount']); $this->assertMatchesRegularExpression("/[0-9.,]+ €\.$/", $json['errors']['amount']); @@ -387,7 +387,7 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); $transaction = $wallet->transactions() @@ -411,7 +411,7 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); $mollie_response['status'] = 'paid'; @@ -421,14 +421,14 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); // Test for payment failure Bus::fake(); $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $mollie_response = [ @@ -494,7 +494,7 @@ // PaymentIntent already sets the status to 'paid', so we can test // immediately the balance update // Assert that email notification job has been dispatched - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->status); + $this->assertSame(Payment::STATUS_PAID, $payment->status); $this->assertEquals(2010, $wallet->fresh()->balance); $transaction = $wallet->transactions() ->where('type', Transaction::WALLET_CREDIT)->get()->last(); @@ -557,7 +557,7 @@ Bus::fake(); $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $mollie_response = [ @@ -578,7 +578,7 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(2010, $wallet->fresh()->balance); $transaction = $wallet->transactions() @@ -601,7 +601,7 @@ // Test for payment failure $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $wallet->setSetting('mollie_mandate_id', 'xxx'); @@ -621,7 +621,7 @@ $wallet->refresh(); - $this->assertSame(PaymentProvider::STATUS_FAILED, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_FAILED, $payment->fresh()->status); $this->assertEquals(2010, $wallet->balance); $this->assertTrue(!empty($wallet->getSetting('mandate_disabled'))); @@ -655,12 +655,12 @@ // Create a paid payment $payment = Payment::create([ 'id' => 'tr_123456', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 123, 'credit_amount' => 123, 'currency_amount' => 123, 'currency' => 'EUR', - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $wallet->id, 'provider' => 'mollie', 'description' => 'test', @@ -729,8 +729,8 @@ $this->assertCount(1, $payments); $this->assertSame(-101, $payments[0]->amount); $this->assertSame(-101, $payments[0]->currency_amount); - $this->assertSame(PaymentProvider::STATUS_PAID, $payments[0]->status); - $this->assertSame(PaymentProvider::TYPE_REFUND, $payments[0]->type); + $this->assertSame(Payment::STATUS_PAID, $payments[0]->status); + $this->assertSame(Payment::TYPE_REFUND, $payments[0]->type); $this->assertSame("mollie", $payments[0]->provider); $this->assertSame("refund desc", $payments[0]->description); @@ -786,8 +786,8 @@ $this->assertCount(1, $payments); $this->assertSame(-15, $payments[0]->amount); - $this->assertSame(PaymentProvider::STATUS_PAID, $payments[0]->status); - $this->assertSame(PaymentProvider::TYPE_CHARGEBACK, $payments[0]->type); + $this->assertSame(Payment::STATUS_PAID, $payments[0]->status); + $this->assertSame(Payment::TYPE_CHARGEBACK, $payments[0]->type); $this->assertSame("mollie", $payments[0]->provider); $this->assertSame('', $payments[0]->description); @@ -860,9 +860,9 @@ $this->assertSame(1, $json['page']); $this->assertSame(false, $json['hasMore']); $this->assertCount(1, $json['list']); - $this->assertSame(PaymentProvider::STATUS_OPEN, $json['list'][0]['status']); + $this->assertSame(Payment::STATUS_OPEN, $json['list'][0]['status']); $this->assertSame('EUR', $json['list'][0]['currency']); - $this->assertSame(PaymentProvider::TYPE_ONEOFF, $json['list'][0]['type']); + $this->assertSame(Payment::TYPE_ONEOFF, $json['list'][0]['type']); $this->assertSame(1234, $json['list'][0]['amount']); $response = $this->actingAs($user)->get("api/v4/payments/has-pending"); @@ -875,7 +875,7 @@ $this->assertCount(1, $payments); $payment = $payments[0]; - $payment->status = PaymentProvider::STATUS_PAID; + $payment->status = Payment::STATUS_PAID; $payment->save(); // They payment should be gone from the pending list now @@ -904,7 +904,7 @@ $wallet->currency = 'EUR'; $wallet->save(); - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_ONEOFF); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_ONEOFF); $response->assertStatus(200); $json = $response->json(); @@ -926,7 +926,7 @@ $this->assertSame('BTC', $json[3]['currency']); } - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_RECURRING); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_RECURRING); $response->assertStatus(200); $json = $response->json(); diff --git a/src/tests/Feature/Controller/PaymentsMollieTest.php b/src/tests/Feature/Controller/PaymentsMollieTest.php --- a/src/tests/Feature/Controller/PaymentsMollieTest.php +++ b/src/tests/Feature/Controller/PaymentsMollieTest.php @@ -125,12 +125,12 @@ $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + $min = $wallet->money(Payment::MIN_AMOUNT); $this->assertSame("Minimum amount for a single payment is {$min}.", $json['errors']['amount']); // Test creating a mandate (negative balance, amount too small) Wallet::where('id', $wallet->id)->update(['balance' => -2000]); - $post = ['amount' => PaymentProvider::MIN_AMOUNT / 100, 'balance' => 0]; + $post = ['amount' => Payment::MIN_AMOUNT / 100, 'balance' => 0]; $response = $this->actingAs($user)->post("api/v4/payments/mandate", $post); $response->assertStatus(422); @@ -155,7 +155,7 @@ $this->assertSame(2010, $payment->amount); $this->assertSame($wallet->id, $payment->wallet_id); $this->assertSame($user->tenant->title . " Auto-Payment Setup", $payment->description); - $this->assertSame(PaymentProvider::TYPE_MANDATE, $payment->type); + $this->assertSame(Payment::TYPE_MANDATE, $payment->type); // Test fetching the mandate information $response = $this->actingAs($user)->get("api/v4/payments/mandate"); @@ -362,7 +362,7 @@ $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + $min = $wallet->money(Payment::MIN_AMOUNT); $this->assertSame("Minimum amount for a single payment is {$min}.", $json['errors']['amount']); // Invalid currency @@ -413,7 +413,7 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); $transaction = $wallet->transactions() @@ -437,7 +437,7 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); $mollie_response['status'] = 'paid'; @@ -447,14 +447,14 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); // Test for payment failure Bus::fake(); $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $mollie_response = [ @@ -522,7 +522,7 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); } @@ -562,7 +562,7 @@ // PaymentIntent already sets the status to 'paid', so we can test // immediately the balance update // Assert that email notification job has been dispatched - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->status); + $this->assertSame(Payment::STATUS_PAID, $payment->status); $this->assertEquals(2010, $wallet->fresh()->balance); $transaction = $wallet->transactions() ->where('type', Transaction::WALLET_CREDIT)->get()->last(); @@ -625,7 +625,7 @@ Bus::fake(); $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $mollie_response = [ @@ -646,7 +646,7 @@ $response = $this->post("api/webhooks/payment/mollie", $post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(2010, $wallet->fresh()->balance); $transaction = $wallet->transactions() @@ -669,7 +669,7 @@ // Test for payment failure $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $wallet->setSetting('mollie_mandate_id', 'xxx'); @@ -689,7 +689,7 @@ $wallet->refresh(); - $this->assertSame(PaymentProvider::STATUS_FAILED, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_FAILED, $payment->fresh()->status); $this->assertEquals(2010, $wallet->balance); $this->assertTrue(!empty($wallet->getSetting('mandate_disabled'))); @@ -785,12 +785,12 @@ // Create a paid payment $payment = Payment::create([ 'id' => 'tr_123456', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 123, 'credit_amount' => 123, 'currency_amount' => 123, 'currency' => 'CHF', - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $wallet->id, 'provider' => 'mollie', 'description' => 'test', @@ -859,8 +859,8 @@ $this->assertCount(1, $payments); $this->assertSame(-101, $payments[0]->amount); $this->assertSame(-101, $payments[0]->currency_amount); - $this->assertSame(PaymentProvider::STATUS_PAID, $payments[0]->status); - $this->assertSame(PaymentProvider::TYPE_REFUND, $payments[0]->type); + $this->assertSame(Payment::STATUS_PAID, $payments[0]->status); + $this->assertSame(Payment::TYPE_REFUND, $payments[0]->type); $this->assertSame("mollie", $payments[0]->provider); $this->assertSame("refund desc", $payments[0]->description); @@ -916,8 +916,8 @@ $this->assertCount(1, $payments); $this->assertSame(-15, $payments[0]->amount); - $this->assertSame(PaymentProvider::STATUS_PAID, $payments[0]->status); - $this->assertSame(PaymentProvider::TYPE_CHARGEBACK, $payments[0]->type); + $this->assertSame(Payment::STATUS_PAID, $payments[0]->status); + $this->assertSame(Payment::TYPE_CHARGEBACK, $payments[0]->type); $this->assertSame("mollie", $payments[0]->provider); $this->assertSame('', $payments[0]->description); @@ -944,12 +944,12 @@ // Create a paid payment $payment = Payment::create([ 'id' => 'tr_123456', - 'status' => PaymentProvider::STATUS_PAID, + 'status' => Payment::STATUS_PAID, 'amount' => 1234, 'credit_amount' => 1234, 'currency_amount' => 1117, 'currency' => 'EUR', - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $wallet->id, 'provider' => 'mollie', 'description' => 'test', @@ -1081,9 +1081,9 @@ $this->assertSame(1, $json['page']); $this->assertSame(false, $json['hasMore']); $this->assertCount(1, $json['list']); - $this->assertSame(PaymentProvider::STATUS_OPEN, $json['list'][0]['status']); + $this->assertSame(Payment::STATUS_OPEN, $json['list'][0]['status']); $this->assertSame('CHF', $json['list'][0]['currency']); - $this->assertSame(PaymentProvider::TYPE_ONEOFF, $json['list'][0]['type']); + $this->assertSame(Payment::TYPE_ONEOFF, $json['list'][0]['type']); $this->assertSame(1234, $json['list'][0]['amount']); $response = $this->actingAs($user)->get("api/v4/payments/has-pending"); @@ -1096,7 +1096,7 @@ $this->assertCount(1, $payments); $payment = $payments[0]; - $payment->status = PaymentProvider::STATUS_PAID; + $payment->status = Payment::STATUS_PAID; $payment->save(); // They payment should be gone from the pending list now @@ -1122,7 +1122,7 @@ $user = $this->getTestUser('john@kolab.org'); - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_ONEOFF); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_ONEOFF); $response->assertStatus(200); $json = $response->json(); @@ -1141,7 +1141,7 @@ $this->assertSame('BTC', $json[3]['currency']); } - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_RECURRING); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_RECURRING); $response->assertStatus(200); $json = $response->json(); diff --git a/src/tests/Feature/Controller/PaymentsStripeTest.php b/src/tests/Feature/Controller/PaymentsStripeTest.php --- a/src/tests/Feature/Controller/PaymentsStripeTest.php +++ b/src/tests/Feature/Controller/PaymentsStripeTest.php @@ -114,12 +114,12 @@ $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + $min = $wallet->money(Payment::MIN_AMOUNT); $this->assertSame("Minimum amount for a single payment is {$min}.", $json['errors']['amount']); // Test creating a mandate (negative balance, amount too small) Wallet::where('id', $wallet->id)->update(['balance' => -2000]); - $post = ['amount' => PaymentProvider::MIN_AMOUNT / 100, 'balance' => 0]; + $post = ['amount' => Payment::MIN_AMOUNT / 100, 'balance' => 0]; $response = $this->actingAs($user)->post("api/v4/payments/mandate", $post); $response->assertStatus(422); @@ -144,7 +144,7 @@ $payment = Payment::where('wallet_id', $wallet->id)->first(); $this->assertSame(0, $payment->amount); $this->assertSame($user->tenant->title . " Auto-Payment Setup", $payment->description); - $this->assertSame(PaymentProvider::TYPE_MANDATE, $payment->type); + $this->assertSame(Payment::TYPE_MANDATE, $payment->type); // Test fetching the mandate information $response = $this->actingAs($user)->get("api/v4/payments/mandate"); @@ -312,7 +312,7 @@ $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); - $min = $wallet->money(PaymentProvider::MIN_AMOUNT); + $min = $wallet->money(Payment::MIN_AMOUNT); $this->assertSame("Minimum amount for a single payment is {$min}.", $json['errors']['amount']); // Invalid currency @@ -373,7 +373,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); $transaction = $wallet->transactions() @@ -393,12 +393,12 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); // Test for payment failure ('failed' status) $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $post['type'] = "payment_intent.payment_failed"; @@ -407,7 +407,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_FAILED, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_FAILED, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); // Assert that email notification job wasn't dispatched, @@ -416,7 +416,7 @@ // Test for payment failure ('canceled' status) $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $post['type'] = "payment_intent.canceled"; @@ -425,7 +425,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_CANCELED, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_CANCELED, $payment->fresh()->status); $this->assertEquals(1234, $wallet->fresh()->balance); // Assert that email notification job wasn't dispatched, @@ -451,8 +451,8 @@ $payment = $wallet->payments()->first(); - $this->assertSame(PaymentProvider::STATUS_OPEN, $payment->status); - $this->assertSame(PaymentProvider::TYPE_MANDATE, $payment->type); + $this->assertSame(Payment::STATUS_OPEN, $payment->status); + $this->assertSame(Payment::TYPE_MANDATE, $payment->type); $this->assertSame(0, $payment->amount); $post = [ @@ -483,7 +483,7 @@ $payment->refresh(); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->status); + $this->assertSame(Payment::STATUS_PAID, $payment->status); $this->assertSame($payment->id, $wallet->fresh()->getSetting('stripe_mandate_id')); // Expect a WalletCharge job if the balance is negative @@ -639,7 +639,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_PAID, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_PAID, $payment->fresh()->status); $this->assertEquals(2010, $wallet->fresh()->balance); $transaction = $wallet->transactions() ->where('type', Transaction::WALLET_CREDIT)->get()->last(); @@ -661,7 +661,7 @@ // Test for payment failure ('failed' status) $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $wallet->setSetting('mandate_disabled', null); @@ -674,7 +674,7 @@ $wallet->refresh(); - $this->assertSame(PaymentProvider::STATUS_FAILED, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_FAILED, $payment->fresh()->status); $this->assertEquals(2010, $wallet->balance); $this->assertTrue(!empty($wallet->getSetting('mandate_disabled'))); @@ -689,7 +689,7 @@ // Test for payment failure ('canceled' status) $payment->refresh(); - $payment->status = PaymentProvider::STATUS_OPEN; + $payment->status = Payment::STATUS_OPEN; $payment->save(); $post['type'] = "payment_intent.canceled"; @@ -698,7 +698,7 @@ $response = $this->webhookRequest($post); $response->assertStatus(200); - $this->assertSame(PaymentProvider::STATUS_CANCELED, $payment->fresh()->status); + $this->assertSame(Payment::STATUS_CANCELED, $payment->fresh()->status); $this->assertEquals(2010, $wallet->fresh()->balance); // Assert that email notification job wasn't dispatched, @@ -823,7 +823,7 @@ $user = $this->getTestUser('john@kolab.org'); - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_ONEOFF); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_ONEOFF); $response->assertStatus(200); $json = $response->json(); @@ -834,7 +834,7 @@ $this->assertSame('paypal', $json[1]['id']); $this->assertSame('bitcoin', $json[2]['id']); - $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_RECURRING); + $response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_RECURRING); $response->assertStatus(200); $json = $response->json(); diff --git a/src/tests/Feature/Controller/Reseller/PaymentsMollieTest.php b/src/tests/Feature/Controller/Reseller/PaymentsMollieTest.php --- a/src/tests/Feature/Controller/Reseller/PaymentsMollieTest.php +++ b/src/tests/Feature/Controller/Reseller/PaymentsMollieTest.php @@ -4,7 +4,6 @@ use App\Http\Controllers\API\V4\Reseller\PaymentsController; use App\Payment; -use App\Providers\PaymentProvider; use App\Transaction; use App\Wallet; use App\WalletSetting; @@ -90,7 +89,7 @@ $this->assertSame(2010, $payment->amount); $this->assertSame($wallet->id, $payment->wallet_id); $this->assertSame($reseller->tenant->title . " Auto-Payment Setup", $payment->description); - $this->assertSame(PaymentProvider::TYPE_MANDATE, $payment->type); + $this->assertSame(Payment::TYPE_MANDATE, $payment->type); // Test fetching the mandate information $response = $this->actingAs($reseller)->get("api/v4/payments/mandate"); @@ -246,7 +245,7 @@ $reseller = $this->getTestUser('reseller@' . \config('app.domain')); - $response = $this->actingAs($reseller)->get('api/v4/payments/methods?type=' . PaymentProvider::TYPE_ONEOFF); + $response = $this->actingAs($reseller)->get('api/v4/payments/methods?type=' . Payment::TYPE_ONEOFF); $response->assertStatus(200); $json = $response->json(); diff --git a/src/tests/Feature/Controller/WalletsTest.php b/src/tests/Feature/Controller/WalletsTest.php --- a/src/tests/Feature/Controller/WalletsTest.php +++ b/src/tests/Feature/Controller/WalletsTest.php @@ -4,7 +4,6 @@ use App\Http\Controllers\API\V4\WalletsController; use App\Payment; -use App\Providers\PaymentProvider; use App\Transaction; use Carbon\Carbon; use Tests\TestCase; @@ -174,8 +173,8 @@ $date = Carbon::create(intval(date('Y')) - 1, 4, 30); $payment = Payment::create([ 'id' => 'AAA1', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in April', 'wallet_id' => $wallet->id, 'provider' => 'stripe', diff --git a/src/tests/Feature/Documents/ReceiptTest.php b/src/tests/Feature/Documents/ReceiptTest.php --- a/src/tests/Feature/Documents/ReceiptTest.php +++ b/src/tests/Feature/Documents/ReceiptTest.php @@ -4,7 +4,6 @@ use App\Documents\Receipt; use App\Payment; -use App\Providers\PaymentProvider; use App\User; use App\Wallet; use App\VatRate; @@ -227,8 +226,8 @@ $payment = Payment::create([ 'id' => 'AAA1', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in April', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -243,8 +242,8 @@ $payment = Payment::create([ 'id' => 'AAA2', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in June', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -259,8 +258,8 @@ $payment = Payment::create([ 'id' => 'AAA3', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Auto-Payment Setup', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -275,8 +274,8 @@ $payment = Payment::create([ 'id' => 'AAA4', - 'status' => PaymentProvider::STATUS_OPEN, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_OPEN, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Payment not yet paid', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -292,8 +291,8 @@ // ... so we expect the five three on the receipt $payment = Payment::create([ 'id' => 'AAA5', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Payment OK', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -308,8 +307,8 @@ $payment = Payment::create([ 'id' => 'AAA6', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Payment OK', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -324,8 +323,8 @@ $payment = Payment::create([ 'id' => 'AAA7', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_RECURRING, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_RECURRING, 'description' => 'Payment OK', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -340,8 +339,8 @@ $payment = Payment::create([ 'id' => 'ref1', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_REFUND, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_REFUND, 'description' => 'refund desc', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -356,8 +355,8 @@ $payment = Payment::create([ 'id' => 'chback1', - 'status' => PaymentProvider::STATUS_PAID, - 'type' => PaymentProvider::TYPE_CHARGEBACK, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_CHARGEBACK, 'description' => '', 'wallet_id' => $wallet->id, 'provider' => 'stripe', diff --git a/src/tests/Feature/Jobs/PaymentEmailTest.php b/src/tests/Feature/Jobs/PaymentEmailTest.php --- a/src/tests/Feature/Jobs/PaymentEmailTest.php +++ b/src/tests/Feature/Jobs/PaymentEmailTest.php @@ -6,7 +6,6 @@ use App\Mail\PaymentFailure; use App\Mail\PaymentSuccess; use App\Payment; -use App\Providers\PaymentProvider; use App\User; use Illuminate\Support\Facades\Mail; use Tests\TestCase; @@ -56,10 +55,10 @@ $payment->credit_amount = 100; $payment->currency_amount = 100; $payment->currency = 'CHF'; - $payment->status = PaymentProvider::STATUS_PAID; + $payment->status = Payment::STATUS_PAID; $payment->description = 'test'; $payment->provider = 'stripe'; - $payment->type = PaymentProvider::TYPE_ONEOFF; + $payment->type = Payment::TYPE_ONEOFF; $payment->save(); Mail::fake(); @@ -78,7 +77,7 @@ return $mail->hasTo('ext@email.tld') && !$mail->hasCc('ext@email.tld'); }); - $payment->status = PaymentProvider::STATUS_FAILED; + $payment->status = Payment::STATUS_FAILED; $payment->save(); $job = new PaymentEmail($payment); @@ -92,7 +91,7 @@ return $mail->hasTo('ext@email.tld') && !$mail->hasCc('ext@email.tld'); }); - $payment->status = PaymentProvider::STATUS_EXPIRED; + $payment->status = Payment::STATUS_EXPIRED; $payment->save(); $job = new PaymentEmail($payment); @@ -105,10 +104,10 @@ Mail::fake(); $states = [ - PaymentProvider::STATUS_OPEN, - PaymentProvider::STATUS_CANCELED, - PaymentProvider::STATUS_PENDING, - PaymentProvider::STATUS_AUTHORIZED, + Payment::STATUS_OPEN, + Payment::STATUS_CANCELED, + Payment::STATUS_PENDING, + Payment::STATUS_AUTHORIZED, ]; foreach ($states as $state) { diff --git a/src/tests/Feature/PaymentTest.php b/src/tests/Feature/PaymentTest.php --- a/src/tests/Feature/PaymentTest.php +++ b/src/tests/Feature/PaymentTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature; use App\Payment; -use App\Providers\PaymentProvider; use App\Transaction; use App\Wallet; use App\VatRate; @@ -36,6 +35,64 @@ parent::tearDown(); } + /** + * Test credit() method + */ + public function testCredit(): void + { + Queue::fake(); + + $user = $this->getTestUser('jane@kolabnow.com'); + $wallet = $user->wallets()->first(); + + $wallet->setSetting('mandate_disabled', 1); + + $payment1 = Payment::createFromArray([ + 'id' => 'test-payment1', + 'amount' => 10750, + 'currency' => $wallet->currency, + 'currency_amount' => 10750, + 'type' => Payment::TYPE_ONEOFF, + 'wallet_id' => $wallet->id, + 'status' => Payment::STATUS_PAID, + ]); + + $payment2 = Payment::createFromArray([ + 'id' => 'test-payment2', + 'amount' => 1075, + 'currency' => $wallet->currency, + 'currency_amount' => 1075, + 'type' => Payment::TYPE_RECURRING, + 'wallet_id' => $wallet->id, + 'status' => Payment::STATUS_PAID, + ]); + + // Credit the 1st payment + $payment1->credit('Test1'); + $wallet->refresh(); + $transaction = $wallet->transactions()->first(); + + $this->assertSame($payment1->credit_amount, $wallet->balance); + $this->assertNull($wallet->getSetting('mandate_disabled')); + $this->assertSame($payment1->credit_amount, $transaction->amount); + $this->assertSame("Payment transaction {$payment1->id} using Test1", $transaction->description); + + $wallet->transactions()->delete(); + $wallet->setSetting('mandate_disabled', 1); + $wallet->balance = -5000; + $wallet->save(); + + // Credit the 2nd payment + $payment2->credit('Test2'); + $wallet->refresh(); + $transaction = $wallet->transactions()->first(); + + $this->assertSame($payment2->credit_amount - 5000, $wallet->balance); + $this->assertSame('1', $wallet->getSetting('mandate_disabled')); + $this->assertSame($payment2->credit_amount, $transaction->amount); + $this->assertSame("Auto-payment transaction {$payment2->id} using Test2", $transaction->description); + } + /** * Test createFromArray() and refund() methods */ @@ -58,7 +115,7 @@ 'amount' => 10750, 'currency' => 'USD', 'currency_amount' => 9000, - 'type' => PaymentProvider::TYPE_ONEOFF, + 'type' => Payment::TYPE_ONEOFF, 'wallet_id' => $wallet->id, ]; @@ -73,7 +130,7 @@ $this->assertSame($payment1Array['currency_amount'], $payment1->currency_amount); $this->assertSame($payment1Array['currency'], $payment1->currency); $this->assertSame($payment1Array['type'], $payment1->type); - $this->assertSame(PaymentProvider::STATUS_OPEN, $payment1->status); + $this->assertSame(Payment::STATUS_OPEN, $payment1->status); $this->assertSame($payment1Array['wallet_id'], $payment1->wallet_id); $this->assertCount(1, Payment::where('id', $payment1->id)->get()); @@ -87,8 +144,8 @@ 'credit_amount' => 10000, 'currency' => $wallet->currency, 'currency_amount' => 10750, - 'type' => PaymentProvider::TYPE_ONEOFF, - 'status' => PaymentProvider::STATUS_OPEN, + 'type' => Payment::TYPE_ONEOFF, + 'status' => Payment::STATUS_OPEN, 'wallet_id' => $wallet->id, ]; @@ -110,7 +167,7 @@ $refundArray = [ 'id' => 'test-refund', - 'type' => PaymentProvider::TYPE_CHARGEBACK, + 'type' => Payment::TYPE_CHARGEBACK, 'description' => 'test refund desc', ]; @@ -128,7 +185,7 @@ $this->assertSame(-4651, $refund->credit_amount); $this->assertSame(-5000, $refund->currency_amount); $this->assertSame($refundArray['type'], $refund->type); - $this->assertSame(PaymentProvider::STATUS_PAID, $refund->status); + $this->assertSame(Payment::STATUS_PAID, $refund->status); $this->assertSame($payment2->currency, $refund->currency); $this->assertSame($payment2->provider, $refund->provider); $this->assertSame($payment2->wallet_id, $refund->wallet_id); @@ -145,7 +202,7 @@ // Test non-wallet currency $refundArray['id'] = 'test-refund-2'; $refundArray['amount'] = 9000; - $refundArray['type'] = PaymentProvider::TYPE_REFUND; + $refundArray['type'] = Payment::TYPE_REFUND; $refund = $payment1->refund($refundArray); @@ -155,7 +212,7 @@ $this->assertSame(-10750, $refund->credit_amount); $this->assertSame(-9000, $refund->currency_amount); $this->assertSame($refundArray['type'], $refund->type); - $this->assertSame(PaymentProvider::STATUS_PAID, $refund->status); + $this->assertSame(Payment::STATUS_PAID, $refund->status); $this->assertSame($payment1->currency, $refund->currency); $this->assertSame($payment1->provider, $refund->provider); $this->assertSame($payment1->wallet_id, $refund->wallet_id); diff --git a/src/tests/Feature/Stories/RateLimitTest.php b/src/tests/Feature/Stories/RateLimitTest.php --- a/src/tests/Feature/Stories/RateLimitTest.php +++ b/src/tests/Feature/Stories/RateLimitTest.php @@ -2,6 +2,7 @@ namespace Tests\Feature\Stories; +use App\Payment; use App\Policy\RateLimit; use Illuminate\Support\Facades\DB; use Tests\TestCase; @@ -20,12 +21,12 @@ $this->setUpTest(); $this->useServicesUrl(); - \App\Payment::query()->delete(); + Payment::query()->delete(); } public function tearDown(): void { - \App\Payment::query()->delete(); + Payment::query()->delete(); parent::tearDown(); } @@ -163,12 +164,12 @@ $wallet = $this->publicDomainUser->wallets()->first(); // Ensure there are no payments for the wallet - \App\Payment::where('wallet_id', $wallet->id)->delete(); + Payment::where('wallet_id', $wallet->id)->delete(); $payment = [ 'id' => \App\Utils::uuidInt(), - 'status' => \App\Providers\PaymentProvider::STATUS_PAID, - 'type' => \App\Providers\PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in March', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -178,7 +179,7 @@ 'currency' => 'CHF', ]; - \App\Payment::create($payment); + Payment::create($payment); $wallet->credit(1111); $request = [ @@ -201,7 +202,7 @@ // create a second payment $payment['id'] = \App\Utils::uuidInt(); - \App\Payment::create($payment); + Payment::create($payment); $wallet->credit(1111); // the tenth request should now be allowed @@ -251,12 +252,12 @@ $wallet = $this->publicDomainUser->wallets()->first(); // Ensure there are no payments for the wallet - \App\Payment::where('wallet_id', $wallet->id)->delete(); + Payment::where('wallet_id', $wallet->id)->delete(); $payment = [ 'id' => \App\Utils::uuidInt(), - 'status' => \App\Providers\PaymentProvider::STATUS_PAID, - 'type' => \App\Providers\PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in March', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -266,7 +267,7 @@ 'currency' => 'CHF', ]; - \App\Payment::create($payment); + Payment::create($payment); $wallet->credit(1111); $request = [ @@ -300,7 +301,7 @@ $payment['id'] = \App\Utils::uuidInt(); - \App\Payment::create($payment); + Payment::create($payment); $wallet->credit(1111); // the tenth request should now be allowed @@ -395,12 +396,12 @@ $wallet = $this->domainOwner->wallets()->first(); // Ensure there are no payments for the wallet - \App\Payment::where('wallet_id', $wallet->id)->delete(); + Payment::where('wallet_id', $wallet->id)->delete(); $payment = [ 'id' => \App\Utils::uuidInt(), - 'status' => \App\Providers\PaymentProvider::STATUS_PAID, - 'type' => \App\Providers\PaymentProvider::TYPE_ONEOFF, + 'status' => Payment::STATUS_PAID, + 'type' => Payment::TYPE_ONEOFF, 'description' => 'Paid in March', 'wallet_id' => $wallet->id, 'provider' => 'stripe', @@ -410,7 +411,7 @@ 'currency' => 'CHF', ]; - \App\Payment::create($payment); + Payment::create($payment); $wallet->credit(1111); $request = [ @@ -443,7 +444,7 @@ // create a second payment $payment['id'] = \App\Utils::uuidInt(); - \App\Payment::create($payment); + Payment::create($payment); $response = $this->post('api/webhooks/policy/ratelimit', $request); $response->assertStatus(200);