mirror of
https://github.com/anna-sara/lan_kiosk
synced 2026-09-03 11:35:01 +02:00
185 lines
7.3 KiB
PHP
185 lines
7.3 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\Deposit;
|
|
use App\Models\Transaction;
|
|
|
|
/**
|
|
* The callback is where money is created out of an HTTP request, so this is the
|
|
* file to read first if something about the payment flow ever feels uncertain.
|
|
*/
|
|
class SwishCallbackTest extends SwishTestCase
|
|
{
|
|
public function test_a_paid_callback_credits_the_customer(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100]);
|
|
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
|
|
$customer->refresh();
|
|
$this->assertSame(800, $customer->deposit);
|
|
$this->assertSame(800, $customer->amount_left);
|
|
$this->assertSame('PAID', Transaction::first()->status);
|
|
$this->assertSame(1, Deposit::where('customer_id', $customer->id)->count());
|
|
}
|
|
|
|
public function test_it_rejects_a_callback_without_the_identifier(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id]);
|
|
|
|
$this->postCallback($this->paidPayload(), null)->assertStatus(403);
|
|
|
|
$this->assertSame(700, $customer->refresh()->deposit);
|
|
$this->assertSame('pending', Transaction::first()->status);
|
|
}
|
|
|
|
public function test_it_rejects_a_callback_with_the_wrong_identifier(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id]);
|
|
|
|
$this->postCallback($this->paidPayload(), 'ffffffff-ffff-ffff-ffff-ffffffffffff')
|
|
->assertStatus(403);
|
|
|
|
$this->assertSame(700, $customer->refresh()->deposit);
|
|
$this->assertSame('pending', Transaction::first()->status);
|
|
}
|
|
|
|
public function test_it_rejects_a_callback_for_a_transaction_that_was_never_registered(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id, 'callback_identifier' => null]);
|
|
|
|
$this->postCallback($this->paidPayload())->assertStatus(403);
|
|
|
|
$this->assertSame(700, $customer->refresh()->deposit);
|
|
}
|
|
|
|
public function test_a_repeated_callback_only_credits_once(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100]);
|
|
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
|
|
$this->assertSame(800, $customer->refresh()->deposit);
|
|
$this->assertSame(1, Deposit::count());
|
|
}
|
|
|
|
public function test_it_refuses_an_amount_that_differs_from_the_payment_request(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100]);
|
|
|
|
$this->postCallback($this->paidPayload(['amount' => 5000]))->assertNoContent();
|
|
|
|
$this->assertSame(700, $customer->refresh()->deposit);
|
|
$this->assertSame('amount_mismatch', Transaction::first()->status);
|
|
$this->assertSame(0, Deposit::count());
|
|
}
|
|
|
|
public function test_it_does_not_round_an_amount_with_ore(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100]);
|
|
|
|
$this->postCallback($this->paidPayload(['amount' => 99.50]))->assertNoContent();
|
|
|
|
$this->assertSame(700, $customer->refresh()->deposit);
|
|
$this->assertSame('amount_mismatch', Transaction::first()->status);
|
|
}
|
|
|
|
public function test_a_declined_payment_is_recorded_but_not_credited(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id]);
|
|
|
|
$this->postCallback($this->paidPayload([
|
|
'status' => 'DECLINED',
|
|
'errorCode' => 'BANKIDCL',
|
|
]))->assertNoContent();
|
|
|
|
$this->assertSame(700, $customer->refresh()->deposit);
|
|
$this->assertSame('DECLINED', Transaction::first()->status);
|
|
}
|
|
|
|
public function test_an_unknown_reference_changes_nothing(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
|
|
$this->postCallback($this->paidPayload(['payeePaymentReference' => 'LAN-NOSUCHREF']))
|
|
->assertNoContent();
|
|
|
|
$this->assertSame(700, $customer->refresh()->deposit);
|
|
$this->assertSame(0, Deposit::count());
|
|
}
|
|
|
|
public function test_a_group_member_payment_lands_on_the_group_account(): void
|
|
{
|
|
$group = $this->customer([
|
|
'lan_id' => 10, 'name' => 'Klanen', 'deposit' => 500, 'amount_left' => 500,
|
|
'is_in_group' => 0, 'customer_group_id' => 7,
|
|
]);
|
|
$member = $this->customer([
|
|
'lan_id' => 11, 'name' => 'Anna', 'deposit' => 0, 'amount_left' => 0,
|
|
'is_in_group' => 1, 'customer_group_id' => 7,
|
|
]);
|
|
|
|
$this->transaction(['customer_id' => $member->id, 'expected_amount' => 100]);
|
|
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
|
|
$this->assertSame(600, $group->refresh()->deposit);
|
|
$this->assertSame(600, $group->amount_left);
|
|
$this->assertSame(0, $member->refresh()->deposit);
|
|
}
|
|
|
|
public function test_a_payment_to_a_customer_of_their_own_lands_on_themselves(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700, 'is_in_group' => 0]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100]);
|
|
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
|
|
$this->assertSame(800, $customer->refresh()->deposit);
|
|
}
|
|
|
|
public function test_a_late_callback_on_an_expired_transaction_is_still_booked(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100, 'status' => 'expired']);
|
|
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
|
|
$this->assertSame(800, $customer->refresh()->deposit);
|
|
$this->assertSame('PAID', Transaction::first()->status);
|
|
}
|
|
|
|
public function test_the_leftover_choice_from_the_payment_follows_along(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 0, 'amount_left' => 0, 'give_leftover' => 0]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100, 'give_leftover' => 1]);
|
|
|
|
$this->postCallback($this->paidPayload())->assertNoContent();
|
|
|
|
$this->assertSame(1, (int) $customer->refresh()->give_leftover);
|
|
}
|
|
|
|
public function test_it_still_understands_the_old_reference_in_the_message_field(): void
|
|
{
|
|
$customer = $this->customer(['deposit' => 700, 'amount_left' => 700]);
|
|
$this->transaction(['customer_id' => $customer->id, 'expected_amount' => 100]);
|
|
|
|
$payload = $this->paidPayload(['message' => 'kiosk|LAN-TEST0001']);
|
|
unset($payload['payeePaymentReference']);
|
|
|
|
$this->postCallback($payload)->assertNoContent();
|
|
|
|
$this->assertSame(800, $customer->refresh()->deposit);
|
|
}
|
|
}
|