Page MenuHomePhorge

D2104.1775184382.diff
No OneTemporary

Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None

D2104.1775184382.diff

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
@@ -7,6 +7,7 @@
use App\Wallet;
use Illuminate\Support\Facades\DB;
use Mollie\Api\Exceptions\ApiException;
+use Mollie\Api\Types;
class Mollie extends \App\Providers\PaymentProvider
{
@@ -352,6 +353,18 @@
}
}
}
+
+ // In case there were multiple auto-payment setup requests (e.g. caused by a double
+ // form submission) we end up with multiple payment records and mollie_mandate_id
+ // 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
+ && $mollie_payment->mandateId
+ && $mollie_payment->sequenceType == Types\SequenceType::SEQUENCETYPE_FIRST
+ ) {
+ $payment->wallet->setSetting('mollie_mandate_id', $mollie_payment->mandateId);
+ }
} elseif ($mollie_payment->isFailed()) {
// Note: I didn't find a way to get any description of the problem with a payment
\Log::info(sprintf('Mollie payment failed (%s)', $payment->id));
diff --git a/src/resources/js/app.js b/src/resources/js/app.js
--- a/src/resources/js/app.js
+++ b/src/resources/js/app.js
@@ -381,7 +381,10 @@
// Add a axios response interceptor for general/validation error handler
window.axios.interceptors.response.use(
response => {
- // Do nothing
+ if (response.config.onFinish) {
+ response.config.onFinish()
+ }
+
return response
},
error => {
@@ -393,6 +396,10 @@
return Promise.reject(error)
}
+ if (error.config.onFinish) {
+ error.config.onFinish()
+ }
+
if (error.response && status == 422) {
error_msg = "Form validation error"
diff --git a/src/resources/vue/Wallet.vue b/src/resources/vue/Wallet.vue
--- a/src/resources/vue/Wallet.vue
+++ b/src/resources/vue/Wallet.vue
@@ -247,6 +247,7 @@
})
}
+ this.formLock = false
this.paymentForm = 'init'
this.paymentDialogTitle = 'Top up your wallet'
@@ -255,9 +256,17 @@
}).modal()
},
payment() {
+ if (this.formLock) {
+ return
+ }
+
+ // Lock the form to prevent from double submission
+ this.formLock = true
+ let onFinish = () => { this.formLock = false }
+
this.$root.clearFormValidation($('#payment-form'))
- axios.post('/api/v4/payments', {amount: this.amount})
+ axios.post('/api/v4/payments', {amount: this.amount}, { onFinish })
.then(response => {
if (response.data.redirectUrl) {
location.href = response.data.redirectUrl
@@ -267,6 +276,14 @@
})
},
autoPayment() {
+ if (this.formLock) {
+ return
+ }
+
+ // Lock the form to prevent from double submission
+ this.formLock = true
+ let onFinish = () => { this.formLock = false }
+
const method = this.mandate.id && (this.mandate.isValid || this.mandate.isPending) ? 'put' : 'post'
const post = {
amount: this.mandate.amount,
@@ -275,7 +292,7 @@
this.$root.clearFormValidation($('#auto-payment form'))
- axios[method]('/api/v4/payments/mandate', post)
+ axios[method]('/api/v4/payments/mandate', post, { onFinish })
.then(response => {
if (method == 'post') {
this.mandate.id = null
@@ -310,6 +327,7 @@
autoPaymentForm(event, title) {
this.paymentForm = 'auto'
this.paymentDialogTitle = title || 'Add auto-payment'
+ this.formLock = false
setTimeout(() => { this.dialog.find('#mandate_amount').focus()}, 10)
},
receiptDownload() {
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
@@ -46,7 +46,7 @@
'password' => 'simple123',
]);
- $this->browse(function (Browser $browser) {
+ $this->browse(function (Browser $browser) use ($user) {
$browser->visit(new Home())
->submitLogon('payment-test@kolabnow.com', 'simple123', true, ['paymentProvider' => 'mollie'])
->on(new Dashboard())
@@ -66,12 +66,16 @@
->assertSeeIn('#amount + span + .invalid-feedback', 'The amount must be a number.')
// Submit valid data
->type('@body #amount', '12.34')
+ // Note we use double click to assert it does not create redundant requests
+ ->click('@body #payment-form button')
->click('@body #payment-form button');
})
->on(new PaymentMollie())
->assertSeeIn('@title', \config('app.name') . ' Payment')
->assertSeeIn('@amount', 'CHF 12.34');
+ $this->assertSame(1, $user->wallets()->first()->payments()->count());
+
// Looks like the Mollie testing mode is limited.
// We'll select credit card method and mark the payment as paid
// We can't do much more, we have to trust Mollie their page works ;)
@@ -109,7 +113,7 @@
'password' => 'simple123',
]);
- $this->browse(function (Browser $browser) {
+ $this->browse(function (Browser $browser) use ($user) {
$browser->visit(new Home())
->submitLogon('payment-test@kolabnow.com', 'simple123', true, ['paymentProvider' => 'mollie'])
->on(new Dashboard())
@@ -150,6 +154,8 @@
// Submit valid data
->type('@body #mandate_amount', '100')
->type('@body #mandate_balance', '0')
+ // Note we use double click to assert it does not create redundant requests
+ ->click('@button-action')
->click('@button-action');
})
->on(new PaymentMollie())
@@ -171,6 +177,8 @@
->assertMissing('@body .alert')
->click('@button-cancel');
});
+
+ $this->assertSame(1, $user->wallets()->first()->payments()->count());
});
// Test updating (disabled) auto-payment

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 2:46 AM (10 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18822279
Default Alt Text
D2104.1775184382.diff (6 KB)

Event Timeline