Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117819365
D5104.1775291825.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
21 KB
Referenced Files
None
Subscribers
None
D5104.1775291825.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D5104: Move wallet top-up code into Wallet
Attached
Detach File
Event Timeline