Page MenuHomePhorge

D5104.1775291825.diff
No OneTemporary

Authored By
Unknown
Size
21 KB
Referenced Files
None
Subscribers
None

D5104.1775291825.diff

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
@@ -67,7 +67,7 @@
if ($wallet->balance < round($request->balance * 100)) {
$mandate['amount'] = (int) round($request->amount * 100);
- self::addTax($wallet, $mandate);
+ $mandate = $wallet->paymentRequest($mandate);
}
$provider = PaymentProvider::factory($wallet);
@@ -290,15 +290,13 @@
$currency = $request->currency;
- $request = [
+ $request = $wallet->paymentRequest([
'type' => Payment::TYPE_ONEOFF,
'currency' => $currency,
'amount' => $amount,
'methodId' => $request->methodId ?: PaymentProvider::METHOD_CREDITCARD,
'description' => Tenant::getConfig($user->tenant_id, 'app.name') . ' Payment',
- ];
-
- self::addTax($wallet, $request);
+ ]);
$provider = PaymentProvider::factory($wallet, $currency);
@@ -361,82 +359,6 @@
return response($code < 400 ? 'Success' : 'Server error', $code);
}
- /**
- * Top up a wallet with a "recurring" payment.
- *
- * @param \App\Wallet $wallet The wallet to charge
- *
- * @return bool True if the payment has been initialized
- */
- public static function topUpWallet(Wallet $wallet): bool
- {
- $settings = $wallet->getSettings(['mandate_disabled', 'mandate_balance', 'mandate_amount']);
-
- \Log::debug("Requested top-up for wallet {$wallet->id}");
-
- if (!empty($settings['mandate_disabled'])) {
- \Log::debug("Top-up for wallet {$wallet->id}: mandate disabled");
- return false;
- }
-
- $min_balance = (int) round(floatval($settings['mandate_balance']) * 100);
- $amount = (int) round(floatval($settings['mandate_amount']) * 100);
-
- // The wallet balance is greater than the auto-payment threshold
- if ($wallet->balance >= $min_balance) {
- // Do nothing
- return false;
- }
-
- $provider = PaymentProvider::factory($wallet);
- $mandate = (array) $provider->getMandate($wallet);
-
- if (empty($mandate['isValid'])) {
- \Log::warning("Top-up for wallet {$wallet->id}: mandate invalid");
- if (empty($mandate['isPending'])) {
- \Log::warning("Disabling mandate");
- $wallet->setSetting('mandate_disabled', '1');
- }
- return false;
- }
-
- // The defined top-up amount is not enough
- // Disable auto-payment and notify the user
- if ($wallet->balance + $amount < 0) {
- // Disable (not remove) the mandate
- \Log::warning("Top-up for wallet {$wallet->id}: mandate too little");
- $wallet->setSetting('mandate_disabled', '1');
- \App\Jobs\PaymentMandateDisabledEmail::dispatch($wallet);
- return false;
- }
-
- $appName = Tenant::getConfig($wallet->owner->tenant_id, 'app.name');
- $description = "{$appName} Recurring Payment";
- if ($plan = $wallet->plan()) {
- if ($plan->months == 12) {
- $description = "{$appName} Annual Payment";
- } elseif ($plan->months == 3) {
- $description = "{$appName} Quarterly Payment";
- } elseif ($plan->months == 1) {
- $description = "{$appName} Monthly Payment";
- }
- }
-
- $request = [
- 'type' => Payment::TYPE_RECURRING,
- 'currency' => $wallet->currency,
- 'amount' => $amount,
- 'methodId' => PaymentProvider::METHOD_CREDITCARD,
- 'description' => $description,
- ];
-
- self::addTax($wallet, $request);
-
- $result = $provider->payment($wallet, $request);
-
- return !empty($result);
- }
-
/**
* Returns auto-payment mandate info for the specified wallet
*
@@ -582,33 +504,4 @@
'page' => $page,
]);
}
-
- /**
- * Calculates tax for the payment, fills the request with additional properties
- *
- * @param \App\Wallet $wallet The wallet
- * @param array $request The request data with the payment amount
- */
- protected static function addTax(Wallet $wallet, array &$request): void
- {
- $request['vat_rate_id'] = null;
- $request['credit_amount'] = $request['amount'];
-
- if ($rate = $wallet->vatRate()) {
- $request['vat_rate_id'] = $rate->id;
-
- switch (\config('app.vat.mode')) {
- case 1:
- // In this mode tax is added on top of the payment. The amount
- // to pay grows, but we keep wallet balance without tax.
- $request['amount'] = $request['amount'] + round($request['amount'] * $rate->rate / 100);
- break;
-
- default:
- // In this mode tax is "swallowed" by the vendor. The payment
- // amount does not change
- break;
- }
- }
- }
}
diff --git a/src/app/Jobs/WalletCharge.php b/src/app/Jobs/WalletCharge.php
--- a/src/app/Jobs/WalletCharge.php
+++ b/src/app/Jobs/WalletCharge.php
@@ -3,7 +3,6 @@
namespace App\Jobs;
use App\Wallet;
-use App\Http\Controllers\API\V4\PaymentsController;
class WalletCharge extends CommonJob
{
@@ -48,7 +47,7 @@
$this->logJobStart($this->walletId);
if ($wallet = Wallet::find($this->walletId)) {
- PaymentsController::topUpWallet($wallet);
+ $wallet->topUp();
}
}
}
diff --git a/src/app/Jobs/WalletCheck.php b/src/app/Jobs/WalletCheck.php
--- a/src/app/Jobs/WalletCheck.php
+++ b/src/app/Jobs/WalletCheck.php
@@ -2,7 +2,6 @@
namespace App\Jobs;
-use App\Http\Controllers\API\V4\PaymentsController;
use App\Wallet;
use Carbon\Carbon;
@@ -69,7 +68,7 @@
$this->wallet->chargeEntitlements();
try {
- PaymentsController::topUpWallet($this->wallet);
+ $this->wallet->topUp();
} catch (\Exception $e) {
\Log::error("Failed to top-up wallet {$this->walletId}: " . $e->getMessage());
// Notification emails should be sent even if the top-up fails
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
@@ -60,7 +60,7 @@
*/
public static function factory($provider_or_wallet = null, $currency = null)
{
- if (\strtolower($currency) == 'btc') {
+ if (is_string($currency) && \strtolower($currency) == 'btc') {
return new \App\Providers\Payment\Coinbase();
}
switch (self::providerName($provider_or_wallet)) {
diff --git a/src/app/Wallet.php b/src/app/Wallet.php
--- a/src/app/Wallet.php
+++ b/src/app/Wallet.php
@@ -2,6 +2,7 @@
namespace App;
+use App\Providers\PaymentProvider;
use App\Traits\SettingsTrait;
use App\Traits\UuidStrKeyTrait;
use Carbon\Carbon;
@@ -380,6 +381,36 @@
return $this->belongsTo(User::class, 'user_id', 'id');
}
+ /**
+ * Prepare a payment. Calculates tax for the payment, fills the request with additional properties.
+ *
+ * @param array $request The request data with the payment amount
+ */
+ public function paymentRequest(array $request): array
+ {
+ $request['vat_rate_id'] = null;
+ $request['credit_amount'] = $request['amount'];
+
+ if ($rate = $this->vatRate()) {
+ $request['vat_rate_id'] = $rate->id;
+
+ switch (\config('app.vat.mode')) {
+ case 1:
+ // In this mode tax is added on top of the payment. The amount
+ // to pay grows, but we keep wallet balance without tax.
+ $request['amount'] = $request['amount'] + round($request['amount'] * $rate->rate / 100);
+ break;
+
+ default:
+ // In this mode tax is "swallowed" by the vendor. The payment
+ // amount does not change
+ break;
+ }
+ }
+
+ return $request;
+ }
+
/**
* Payments on this wallet.
*
@@ -442,6 +473,79 @@
return $this->balanceUpdate(Transaction::WALLET_REFUND, $amount, $description);
}
+ /**
+ * Top up a wallet with a "recurring" payment.
+ *
+ * @return bool True if the payment has been initialized
+ */
+ public function topUp(): bool
+ {
+ $settings = $this->getSettings(['mandate_disabled', 'mandate_balance', 'mandate_amount']);
+
+ \Log::debug("Requested top-up for wallet {$this->id}");
+
+ if (!empty($settings['mandate_disabled'])) {
+ \Log::debug("Top-up for wallet {$this->id}: mandate disabled");
+ return false;
+ }
+
+ $min_balance = (int) round(floatval($settings['mandate_balance']) * 100);
+ $amount = (int) round(floatval($settings['mandate_amount']) * 100);
+
+ // The wallet balance is greater than the auto-payment threshold
+ if ($this->balance >= $min_balance) {
+ // Do nothing
+ return false;
+ }
+
+ $provider = PaymentProvider::factory($this);
+ $mandate = (array) $provider->getMandate($this);
+
+ if (empty($mandate['isValid'])) {
+ \Log::warning("Top-up for wallet {$this->id}: mandate invalid");
+ if (empty($mandate['isPending'])) {
+ \Log::warning("Disabling mandate");
+ $this->setSetting('mandate_disabled', '1');
+ }
+
+ return false;
+ }
+
+ // The defined top-up amount is not enough
+ // Disable auto-payment and notify the user
+ if ($this->balance + $amount < 0) {
+ // Disable (not remove) the mandate
+ \Log::warning("Top-up for wallet {$this->id}: mandate too little");
+ $this->setSetting('mandate_disabled', '1');
+ \App\Jobs\PaymentMandateDisabledEmail::dispatch($this);
+ return false;
+ }
+
+ $appName = Tenant::getConfig($this->owner->tenant_id, 'app.name');
+ $description = "{$appName} Recurring Payment";
+ if ($plan = $this->plan()) {
+ if ($plan->months == 12) {
+ $description = "{$appName} Annual Payment";
+ } elseif ($plan->months == 3) {
+ $description = "{$appName} Quarterly Payment";
+ } elseif ($plan->months == 1) {
+ $description = "{$appName} Monthly Payment";
+ }
+ }
+
+ $request = $this->paymentRequest([
+ 'type' => Payment::TYPE_RECURRING,
+ 'currency' => $this->currency,
+ 'amount' => $amount,
+ 'methodId' => PaymentProvider::METHOD_CREDITCARD,
+ 'description' => $description,
+ ]);
+
+ $result = $provider->payment($this, $request);
+
+ return !empty($result);
+ }
+
/**
* Get the VAT rate for the wallet owner country.
*
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
@@ -2,7 +2,6 @@
namespace Tests\Feature\Controller;
-use App\Http\Controllers\API\V4\PaymentsController;
use App\Payment;
use App\Transaction;
use App\Wallet;
@@ -443,5 +442,6 @@
$json = $response->json();
$this->assertCount(1, $json);
+ $this->assertSame('creditcard', $json[0]['id']);
}
}
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
@@ -2,7 +2,6 @@
namespace Tests\Feature\Controller;
-use App\Http\Controllers\API\V4\PaymentsController;
use App\Payment;
use App\Providers\PaymentProvider;
use App\Transaction;
@@ -457,7 +456,7 @@
// Expect a recurring payment as we have a valid mandate at this point
// and the balance is below the threshold
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertTrue($result);
// Check that the payments table contains a new record with proper amount.
@@ -494,7 +493,7 @@
// Expect no payment if the mandate is disabled
$wallet->setSetting('mandate_disabled', 1);
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -502,7 +501,7 @@
$wallet->setSetting('mandate_disabled', null);
$wallet->balance = 1000;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -510,7 +509,7 @@
$wallet->setSetting('mandate_disabled', null);
$wallet->balance = -2050;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -524,7 +523,7 @@
$wallet->setSetting('mollie_mandate_id', null);
$wallet->balance = 0;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -631,8 +630,6 @@
$wallet->save();
$wallet->transactions()->delete();
- $mollie = PaymentProvider::factory('mollie');
-
// Create a paid payment
$payment = Payment::create([
'id' => 'tr_123456',
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
@@ -2,7 +2,6 @@
namespace Tests\Feature\Controller;
-use App\Http\Controllers\API\V4\PaymentsController;
use App\Payment;
use App\Plan;
use App\Providers\PaymentProvider;
@@ -579,7 +578,7 @@
// Expect a recurring payment as we have a valid mandate at this point
// and the balance is below the threshold
- $this->assertTrue(PaymentsController::topUpWallet($wallet));
+ $this->assertTrue($wallet->topUp());
// Check that the payments table contains a new record with proper amount.
// There should be two records, one for the mandate payment and another for
@@ -615,7 +614,7 @@
// Expect no payment if the mandate is disabled
$wallet->setSetting('mandate_disabled', 1);
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -623,7 +622,7 @@
$wallet->setSetting('mandate_disabled', null);
$wallet->balance = 1000;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -631,7 +630,7 @@
$wallet->setSetting('mandate_disabled', null);
$wallet->balance = -2050;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -645,7 +644,7 @@
$wallet->setSetting('mollie_mandate_id', null);
$wallet->balance = 0;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(2, $wallet->payments()->get());
@@ -792,7 +791,7 @@
// Top-up (recurring payment)
// Expect a recurring payment as we have a valid mandate at this point
// and the balance is below the threshold
- $this->assertTrue(PaymentsController::topUpWallet($wallet));
+ $this->assertTrue($wallet->topUp());
// Check that the payments table contains a new record with proper amount(s)
$payment = $wallet->payments()->first();
@@ -815,8 +814,6 @@
$wallet = $user->wallets()->first();
$wallet->transactions()->delete();
- $mollie = PaymentProvider::factory('mollie');
-
// Create a paid payment
$payment = Payment::create([
'id' => 'tr_123456',
@@ -974,8 +971,6 @@
$wallet = $user->wallets()->first();
$wallet->transactions()->delete();
- $mollie = PaymentProvider::factory('mollie');
-
// Create a paid payment
$payment = Payment::create([
'id' => 'tr_123456',
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
@@ -2,7 +2,6 @@
namespace Tests\Feature\Controller;
-use App\Http\Controllers\API\V4\PaymentsController;
use App\Payment;
use App\Providers\PaymentProvider;
use App\Transaction;
@@ -587,7 +586,7 @@
$client->addResponse($paymentMethod);
// Expect a recurring payment as we have a valid mandate at this point
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertTrue($result);
// Check that the payments table contains a new record with proper amount
@@ -601,7 +600,7 @@
// Expect no payment if the mandate is disabled
$wallet->setSetting('mandate_disabled', 1);
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(1, $wallet->payments()->get());
@@ -609,7 +608,7 @@
$wallet->setSetting('mandate_disabled', null);
$wallet->balance = 1000;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(1, $wallet->payments()->get());
@@ -618,7 +617,7 @@
$wallet->balance = -2050;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(1, $wallet->payments()->get());
@@ -632,7 +631,7 @@
$wallet->setSetting('mollie_mandate_id', null);
$wallet->balance = 0;
$wallet->save();
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertFalse($result);
$this->assertCount(1, $wallet->payments()->get());
@@ -831,7 +830,7 @@
$client->addResponse($setupIntent);
$client->addResponse($paymentIntent);
- $result = PaymentsController::topUpWallet($wallet);
+ $result = $wallet->topUp();
$this->assertTrue($result);
// Check that the payments table contains a new record with proper amount(s)
@@ -862,7 +861,9 @@
$this->assertCount(2 + intval($hasCoinbase), $json);
$this->assertSame('creditcard', $json[0]['id']);
$this->assertSame('paypal', $json[1]['id']);
- $this->assertSame('bitcoin', $json[2]['id']);
+ if ($hasCoinbase) {
+ $this->assertSame('bitcoin', $json[2]['id']);
+ }
$response = $this->actingAs($user)->get('api/v4/payments/methods?type=' . Payment::TYPE_RECURRING);
$response->assertStatus(200);
diff --git a/src/tests/Feature/Jobs/WalletCheckTest.php b/src/tests/Feature/Jobs/WalletCheckTest.php
--- a/src/tests/Feature/Jobs/WalletCheckTest.php
+++ b/src/tests/Feature/Jobs/WalletCheckTest.php
@@ -130,8 +130,7 @@
$this->assertTrue($wallet->balance < 0); // @phpstan-ignore-line
- // TODO: How to mock PaymentsProvider::topUpWallet() to make sure it was called?
- // We should probably move this method to the App\Wallet class to make it possible.
+ // TODO: Wallet::topUp() to make sure it was called
$this->markTestIncomplete();
}
diff --git a/src/tests/Feature/WalletTest.php b/src/tests/Feature/WalletTest.php
--- a/src/tests/Feature/WalletTest.php
+++ b/src/tests/Feature/WalletTest.php
@@ -883,6 +883,16 @@
$this->assertSame('test', $transaction->description);
}
+ /**
+ * Tests for topUp()
+ */
+ public function testTopUp(): void
+ {
+ // TODO: Tests from tests/Feature/Controller/Payments*Test.php that invoke
+ // Wallet::topUp() should be moved here
+ $this->markTestIncomplete();
+ }
+
/**
* Tests for updateEntitlements()
*/

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 8:37 AM (1 d, 1 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18828670
Default Alt Text
D5104.1775291825.diff (21 KB)

Event Timeline