From 8c2a011c82607226a54a5b54c1afab4814cf35ce Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 1 May 2024 07:07:52 -0600 Subject: [PATCH 01/36] Rename payment method to payment instrument --- ...ctory.php => PaymentInstrumentFactory.php} | 8 ++-- .../factories/PaymentTransactionFactory.php | 8 ++-- ..._01_000010_create_base_checkout_tables.php | 8 ++-- src/Contracts/CheckoutRequester.php | 24 +++++----- src/Contracts/CheckoutResponder.php | 16 +++---- src/Facades/Checkout.php | 8 ++-- ...aymentMethod.php => PaymentInstrument.php} | 24 +++++----- src/Models/PaymentTransaction.php | 6 +-- src/Models/PaymentType.php | 6 +-- src/Models/Wallet.php | 6 +-- src/Traits/CheckoutRequests.php | 24 +++++----- src/Traits/CheckoutResponses.php | 18 +++---- src/Traits/ConfiguresCheckoutGateway.php | 2 +- tests/Unit/TestCheckoutGateway.php | 48 +++++++++---------- 14 files changed, 103 insertions(+), 103 deletions(-) rename database/factories/{PaymentMethodFactory.php => PaymentInstrumentFactory.php} (83%) rename src/Models/{PaymentMethod.php => PaymentInstrument.php} (77%) diff --git a/database/factories/PaymentMethodFactory.php b/database/factories/PaymentInstrumentFactory.php similarity index 83% rename from database/factories/PaymentMethodFactory.php rename to database/factories/PaymentInstrumentFactory.php index e4248ee..f855554 100644 --- a/database/factories/PaymentMethodFactory.php +++ b/database/factories/PaymentInstrumentFactory.php @@ -4,17 +4,17 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Payavel\Checkout\Models\Wallet; -use Payavel\Checkout\Models\PaymentMethod; +use Payavel\Checkout\Models\PaymentInstrument; use Payavel\Checkout\Models\PaymentType; -class PaymentMethodFactory extends Factory +class PaymentInstrumentFactory extends Factory { /** * The name of the factory's corresponding model. * * @var string */ - protected $model = PaymentMethod::class; + protected $model = PaymentInstrument::class; /** * Define the model's default state. @@ -35,7 +35,7 @@ public function definition() */ public function configure() { - return $this->afterMaking(function (PaymentMethod $paymentMethod) { + return $this->afterMaking(function (PaymentInstrument $paymentMethod) { if(is_null($paymentMethod->wallet_id)) { $wallet = Wallet::inRandomOrder()->firstOr( fn () => Wallet::factory()->create() diff --git a/database/factories/PaymentTransactionFactory.php b/database/factories/PaymentTransactionFactory.php index 810d935..906f4e1 100644 --- a/database/factories/PaymentTransactionFactory.php +++ b/database/factories/PaymentTransactionFactory.php @@ -41,8 +41,8 @@ public function configure() { return $this->afterMaking(function (PaymentTransaction $transaction) { if (is_null($transaction->provider_id)) { - $provider = ! is_null($transaction->payment_method_id) - ? $transaction->paymentMethod->provider + $provider = ! is_null($transaction->payment_instrument_id) + ? $transaction->paymentInstrument->provider : Provider::whereHas( 'accounts', fn ($query) => $query->where('payment_accounts.id', $transaction->account_id) @@ -54,8 +54,8 @@ public function configure() } if (is_null($transaction->account_id)) { - $account = ! is_null($transaction->payment_method_id) - ? $transaction->paymentMethod->account + $account = ! is_null($transaction->payment_instrument_id) + ? $transaction->paymentInstrument->account : Account::whereHas( 'providers', fn ($query) => $query->where('payment_providers.id', $transaction->provider_id) diff --git a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php index 468ef94..17c997c 100644 --- a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php +++ b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php @@ -37,7 +37,7 @@ public function up() } }); - Schema::create('payment_methods', function (Blueprint $table) { + Schema::create('payment_instruments', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('wallet_id'); $table->string('token'); @@ -56,7 +56,7 @@ public function up() $table->string('reference'); $table->unsignedInteger('amount'); $table->char('currency', 3)->default('USD'); - $table->unsignedBigInteger('payment_method_id')->nullable(); + $table->unsignedBigInteger('payment_instrument_id')->nullable(); $table->unsignedSmallInteger('status_code'); $table->json('details')->nullable(); $table->timestamps(); @@ -66,7 +66,7 @@ public function up() $table->foreign('account_id')->references('id')->on('accounts')->onUpdate('cascade'); } - $table->foreign('payment_method_id')->references('id')->on('payment_methods')->onDelete('set null'); + $table->foreign('payment_instrument_id')->references('id')->on('payment_instruments')->onDelete('set null'); }); Schema::create('payment_transaction_events', function (Blueprint $table) { @@ -91,7 +91,7 @@ public function down() { Schema::dropIfExists('payment_transaction_events'); Schema::dropIfExists('payment_transactions'); - Schema::dropIfExists('payment_methods'); + Schema::dropIfExists('payment_instruments'); Schema::dropIfExists('payment_types'); Schema::dropIfExists('wallets'); } diff --git a/src/Contracts/CheckoutRequester.php b/src/Contracts/CheckoutRequester.php index 8904eb7..a7e2b14 100644 --- a/src/Contracts/CheckoutRequester.php +++ b/src/Contracts/CheckoutRequester.php @@ -3,7 +3,7 @@ namespace Payavel\Checkout\Contracts; use Payavel\Checkout\Contracts\Billable; -use Payavel\Checkout\Models\PaymentMethod; +use Payavel\Checkout\Models\PaymentInstrument; use Payavel\Checkout\Models\PaymentTransaction; use Payavel\Checkout\Models\Wallet; @@ -18,38 +18,38 @@ interface CheckoutRequester public function getWallet(Wallet $wallet); /** - * Retrieve the payment method's details from the provider. + * Retrieve the payment instrument's details from the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function getPaymentMethod(PaymentMethod $paymentMethod); + public function getPaymentInstrument(PaymentInstrument $paymentInstrument); /** - * Store the payment method details at the provider. + * Store the payment instrument details at the provider. * * @param \Payavel\Checkout\Contracts\Billable $billable * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function tokenizePaymentMethod(Billable $billable, $data); + public function tokenizePaymentInstrument(Billable $billable, $data); /** - * Update the payment method's details at the provider. + * Update the payment instrument's details at the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function updatePaymentMethod(PaymentMethod $paymentMethod, $data); + public function updatePaymentInstrument(PaymentInstrument $paymentInstrument, $data); /** - * Delete the payment method at the provider. + * Delete the payment instrument at the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function deletePaymentMethod(PaymentMethod $paymentMethod); + public function deletePaymentInstrument(PaymentInstrument $paymentInstrument); /** * Authorize a transaction. diff --git a/src/Contracts/CheckoutResponder.php b/src/Contracts/CheckoutResponder.php index fe6e2c6..dfe2cdc 100644 --- a/src/Contracts/CheckoutResponder.php +++ b/src/Contracts/CheckoutResponder.php @@ -12,32 +12,32 @@ interface CheckoutResponder public function getWalletResponse(); /** - * Maps details from the getPaymentMethod() response to the expected format. + * Maps details from the getPaymentInstrument() response to the expected format. * * @return array|mixed */ - public function getPaymentMethodResponse(); + public function getPaymentInstrumentResponse(); /** - * Maps details from the tokenizePaymentMethod() response to the expected format. + * Maps details from the tokenizePaymentInstrument() response to the expected format. * * @return array|mixed */ - public function tokenizePaymentMethodResponse(); + public function tokenizePaymentInstrumentResponse(); /** - * Maps details from the updatePaymentMethod() response to the expected format. + * Maps details from the updatePaymentInstrument() response to the expected format. * * @return array|mixed */ - public function updatePaymentMethodResponse(); + public function updatePaymentInstrumentResponse(); /** - * Maps details from the deletePaymentMethod() response to the expected format. + * Maps details from the deletePaymentInstrument() response to the expected format. * * @return array|mixed */ - public function deletePaymentMethodResponse(); + public function deletePaymentInstrumentResponse(); /** * Maps details from the authorize() response to the expected format. diff --git a/src/Facades/Checkout.php b/src/Facades/Checkout.php index 7eb583f..7d71816 100644 --- a/src/Facades/Checkout.php +++ b/src/Facades/Checkout.php @@ -16,10 +16,10 @@ * @method static void reset() * @method static string|int|\Payavel\Orchestration\Contracts\Accountable getDefaultAccount() * @method static \Payavel\Checkout\CheckoutResponse getWallet(\Payavel\Checkout\Models\Wallet $wallet) - * @method static \Payavel\Checkout\CheckoutResponse getPaymentMethod(\Payavel\Checkout\Models\PaymentMethod $paymentMethod) - * @method static \Payavel\Checkout\CheckoutResponse tokenizePaymentMethod(\Payavel\Checkout\Contracts\Billable $billable, $data) - * @method static \Payavel\Checkout\CheckoutResponse updatePaymentMethod(\Payavel\Checkout\Models\PaymentMethod $paymentMethod, $data) - * @method static \Payavel\Checkout\CheckoutResponse deletePaymentMethod(\Payavel\Checkout\Models\PaymentMethod $paymentMethod) + * @method static \Payavel\Checkout\CheckoutResponse getPaymentInstrument(\Payavel\Checkout\Models\PaymentInstrument $paymentInstrument) + * @method static \Payavel\Checkout\CheckoutResponse tokenizePaymentInstrument(\Payavel\Checkout\Contracts\Billable $billable, $data) + * @method static \Payavel\Checkout\CheckoutResponse updatePaymentInstrument(\Payavel\Checkout\Models\PaymentInstrument $paymentInstrument, $data) + * @method static \Payavel\Checkout\CheckoutResponse deletePaymentInstrument(\Payavel\Checkout\Models\PaymentInstrument $paymentInstrument) * @method static \Payavel\Checkout\CheckoutResponse authorize($data, \Payavel\Checkout\Contracts\Billable $billable = null) * @method static \Payavel\Checkout\CheckoutResponse capture(\Payavel\Checkout\Models\PaymentTransaction $transaction, $data = []) * @method static \Payavel\Checkout\CheckoutResponse getTransaction(\Payavel\Checkout\Models\PaymentTransaction $transaction) diff --git a/src/Models/PaymentMethod.php b/src/Models/PaymentInstrument.php similarity index 77% rename from src/Models/PaymentMethod.php rename to src/Models/PaymentInstrument.php index 171f237..d00fbd9 100644 --- a/src/Models/PaymentMethod.php +++ b/src/Models/PaymentInstrument.php @@ -7,7 +7,7 @@ use Payavel\Orchestration\Support\ServiceConfig; use Payavel\Orchestration\Traits\HasFactory; -class PaymentMethod extends Model +class PaymentInstrument extends Model { use ConfiguresCheckoutGateway; use HasFactory; @@ -49,7 +49,7 @@ protected static function getFactoryNamespace() } /** - * Get the payment method's provider. + * Get the payment instrument's provider. * * @return \Payavel\Orchestration\Models\Provider */ @@ -59,7 +59,7 @@ public function getProviderAttribute() } /** - * Get the payment method's account. + * Get the payment instrument's account. * * @return \Payavel\Orchestration\Models\Account */ @@ -69,7 +69,7 @@ public function getAccountAttribute() } /** - * Get the wallet the payment method belongs to. + * Get the wallet the payment instrument belongs to. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ @@ -79,7 +79,7 @@ public function wallet() } /** - * Get the payment method's type + * Get the payment instrument's type * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ @@ -89,7 +89,7 @@ public function type() } /** - * Get the transactions that this payment method has triggered. + * Get the transactions that this payment instrument has triggered. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ @@ -99,33 +99,33 @@ public function transactions() } /** - * Fetch the payment method details from the provider. + * Fetch the payment instrument details from the provider. * * @return \Payavel\Checkout\CheckoutResponse */ public function fetch() { - return $this->gateway->getPaymentMethod($this); + return $this->gateway->getPaymentInstrument($this); } /** - * Request the provider to update the payment method's details. + * Request the provider to update the payment instrument's details. * * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse */ public function patch($data) { - return $this->gateway->updatePaymentMethod($this, $data); + return $this->gateway->updatePaymentInstrument($this, $data); } /** - * Request the provider to remove the payment method from their system. + * Request the provider to remove the payment instrument from their system. * * @return \Payavel\Checkout\CheckoutResponse */ public function disable() { - return $this->gateway->deletePaymentMethod($this); + return $this->gateway->deletePaymentInstrument($this); } } diff --git a/src/Models/PaymentTransaction.php b/src/Models/PaymentTransaction.php index 18cb662..857b604 100644 --- a/src/Models/PaymentTransaction.php +++ b/src/Models/PaymentTransaction.php @@ -50,13 +50,13 @@ protected static function getFactoryNamespace() } /** - * Get the payment method used for this transaction. + * Get the payment instrument used for this transaction. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function paymentMethod() + public function paymentInstrument() { - return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentMethod::class, PaymentMethod::class)); + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class)); } /** diff --git a/src/Models/PaymentType.php b/src/Models/PaymentType.php index 45d1825..b60bb18 100644 --- a/src/Models/PaymentType.php +++ b/src/Models/PaymentType.php @@ -28,13 +28,13 @@ protected static function getFactoryNamespace() } /** - * Get the payment methods that inherit this type. + * Get the payment instruments that inherit this type. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function paymentMethods() + public function paymentInstruments() { - return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentMethod::class, PaymentMethod::class), 'type_id'); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class), 'type_id'); } /** diff --git a/src/Models/Wallet.php b/src/Models/Wallet.php index cb1d405..25555ec 100644 --- a/src/Models/Wallet.php +++ b/src/Models/Wallet.php @@ -69,13 +69,13 @@ public function account() } /** - * Get the wallet's payment methods. + * Get the wallet's payment instruments. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function paymentMethods() + public function paymentInstruments() { - return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentMethod::class, PaymentMethod::class)); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class)); } /** diff --git a/src/Traits/CheckoutRequests.php b/src/Traits/CheckoutRequests.php index 2540602..ae31530 100644 --- a/src/Traits/CheckoutRequests.php +++ b/src/Traits/CheckoutRequests.php @@ -3,7 +3,7 @@ namespace Payavel\Checkout\Traits; use Payavel\Checkout\Contracts\Billable; -use Payavel\Checkout\Models\PaymentMethod; +use Payavel\Checkout\Models\PaymentInstrument; use Payavel\Checkout\Models\PaymentTransaction; use Payavel\Checkout\Models\Wallet; use Payavel\Orchestration\Traits\ThrowsRuntimeException; @@ -24,47 +24,47 @@ public function getWallet(Wallet $wallet) } /** - * Retrieve the payment method's details from the provider. + * Retrieve the payment instrument's details from the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function getPaymentMethod(PaymentMethod $paymentMethod) + public function getPaymentInstrument(PaymentInstrument $paymentInstrument) { $this->throwRuntimeException(__FUNCTION__); } /** - * Store the payment method details at the provider. + * Store the payment instrument details at the provider. * * @param \Payavel\Checkout\Contracts\Billable $billable * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function tokenizePaymentMethod(Billable $billable, $data) + public function tokenizePaymentInstrument(Billable $billable, $data) { $this->throwRuntimeException(__FUNCTION__); } /** - * Update the payment method's details at the provider. + * Update the payment instrument's details at the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function updatePaymentMethod(PaymentMethod $paymentMethod, $data) + public function updatePaymentInstrument(PaymentInstrument $paymentInstrument, $data) { $this->throwRuntimeException(__FUNCTION__); } /** - * Delete the payment method at the provider. + * Delete the payment instrument at the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function deletePaymentMethod(PaymentMethod $paymentMethod) + public function deletePaymentInstrument(PaymentInstrument $paymentInstrument) { $this->throwRuntimeException(__FUNCTION__); } diff --git a/src/Traits/CheckoutResponses.php b/src/Traits/CheckoutResponses.php index 80fc9ce..f68b34b 100644 --- a/src/Traits/CheckoutResponses.php +++ b/src/Traits/CheckoutResponses.php @@ -23,49 +23,49 @@ public function getWalletResponse() } /** - * Maps details from the getPaymentMethod() response to the expected format. + * Maps details from the getPaymentInstrument() response to the expected format. * * @return array|mixed * * @throws \RuntimeException|Exception */ - public function getPaymentMethodResponse() + public function getPaymentInstrumentResponse() { return $this->genericResponse(__FUNCTION__); } /** - * Maps details from the tokenizePaymentMethod() response to the expected format. + * Maps details from the tokenizePaymentInstrument() response to the expected format. * * @return array|mixed * * @throws \RuntimeException|Exception */ - public function tokenizePaymentMethodResponse() + public function tokenizePaymentInstrumentResponse() { return $this->genericResponse(__FUNCTION__); } /** - * Maps details from the updatePaymentMethod() response to the expected format. + * Maps details from the updatePaymentInstrument() response to the expected format. * * @return array|mixed * * @throws \RuntimeException|Exception */ - public function updatePaymentMethodResponse() + public function updatePaymentInstrumentResponse() { return $this->genericResponse(__FUNCTION__); } /** - * Maps details from the deletePaymentMethod() response to the expected format. + * Maps details from the deletePaymentInstrument() response to the expected format. * * @return array|mixed * * @throws \RuntimeException|Exception */ - public function deletePaymentMethodResponse() + public function deletePaymentInstrumentResponse() { return $this->genericResponse(__FUNCTION__); } @@ -129,7 +129,7 @@ public function refundResponse() } /** - * Attempts to call the generic response method, else throws RuntimeException. + * Attempts to call the generic response Instrument, else throws RuntimeException. * * @param string $function * @return array|mixed diff --git a/src/Traits/ConfiguresCheckoutGateway.php b/src/Traits/ConfiguresCheckoutGateway.php index 1211fad..d3d1218 100644 --- a/src/Traits/ConfiguresCheckoutGateway.php +++ b/src/Traits/ConfiguresCheckoutGateway.php @@ -14,7 +14,7 @@ trait ConfiguresCheckoutGateway private $checkoutGateway; /** - * Retrieve the payment method's configured gateway. + * Retrieve the payment instrument's configured gateway. * * @return \Payavel\Checkout\CheckoutGateway */ diff --git a/tests/Unit/TestCheckoutGateway.php b/tests/Unit/TestCheckoutGateway.php index 332fb9f..09be8c0 100644 --- a/tests/Unit/TestCheckoutGateway.php +++ b/tests/Unit/TestCheckoutGateway.php @@ -4,7 +4,7 @@ use Payavel\Checkout\Contracts\Billable; use Payavel\Checkout\Facades\Checkout; -use Payavel\Checkout\Models\PaymentMethod; +use Payavel\Checkout\Models\PaymentInstrument; use Payavel\Checkout\Models\PaymentTransaction; use Payavel\Checkout\Models\Wallet; use Payavel\Checkout\CheckoutRequest; @@ -53,72 +53,72 @@ public function get_wallet_method_returns_configured_response() } #[Test] - public function get_payment_method_method_returns_configured_response() + public function get_payment_instrument_method_returns_configured_response() { $wallet = Wallet::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); - $paymentMethod = PaymentMethod::factory()->create([ + $paymentInstrument = PaymentInstrument::factory()->create([ 'wallet_id' => $wallet->id, ]); - $response = Checkout::getPaymentMethod($paymentMethod); + $response = Checkout::getPaymentInstrument($paymentInstrument); $this->assertResponseIsConfigured($response); - $this->assertEquals('getPaymentMethod', $response->data['requestMethod']); + $this->assertEquals('getPaymentInstrument', $response->data['requestMethod']); } #[Test] - public function tokenize_payment_method_method_returns_configured_response() + public function tokenize_payment_instrument_method_returns_configured_response() { $user = User::factory()->create(); - $response = Checkout::tokenizePaymentMethod($user, []); + $response = Checkout::tokenizePaymentInstrument($user, []); $this->assertResponseIsConfigured($response); - $this->assertEquals('tokenizePaymentMethod', $response->data['requestMethod']); + $this->assertEquals('tokenizePaymentInstrument', $response->data['requestMethod']); } #[Test] - public function update_payment_method_method_returns_configured_response() + public function update_payment_instrument_method_returns_configured_response() { $wallet = Wallet::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); - $paymentMethod = PaymentMethod::factory()->create([ + $paymentInstrument = PaymentInstrument::factory()->create([ 'wallet_id' => $wallet->id, ]); - $response = Checkout::updatePaymentMethod($paymentMethod, []); + $response = Checkout::updatePaymentInstrument($paymentInstrument, []); $this->assertResponseIsConfigured($response); - $this->assertEquals('updatePaymentMethod', $response->data['requestMethod']); + $this->assertEquals('updatePaymentInstrument', $response->data['requestMethod']); } #[Test] - public function delete_payment_method_method_returns_configured_response() + public function delete_payment_instrument_method_returns_configured_response() { $wallet = Wallet::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); - $paymentMethod = PaymentMethod::factory()->create([ + $paymentInstrument = PaymentInstrument::factory()->create([ 'wallet_id' => $wallet->id, ]); - $response = Checkout::deletePaymentMethod($paymentMethod); + $response = Checkout::deletePaymentInstrument($paymentInstrument); $this->assertResponseIsConfigured($response); - $this->assertEquals('deletePaymentMethod', $response->data['requestMethod']); + $this->assertEquals('deletePaymentInstrument', $response->data['requestMethod']); } #[Test] @@ -212,22 +212,22 @@ public function getWallet(Wallet $wallet) return new TestCheckoutResponse([]); } - public function getPaymentMethod(PaymentMethod $paymentMethod) + public function getPaymentInstrument(PaymentInstrument $paymentInstrument) { return new TestCheckoutResponse([]); } - public function tokenizePaymentMethod(Billable $billable, $data) + public function tokenizePaymentInstrument(Billable $billable, $data) { return new TestCheckoutResponse([]); } - public function updatePaymentMethod(PaymentMethod $paymentMethod, $data) + public function updatePaymentInstrument(PaymentInstrument $paymentInstrument, $data) { return new TestCheckoutResponse([]); } - public function deletePaymentMethod(PaymentMethod $paymentMethod) + public function deletePaymentInstrument(PaymentInstrument $paymentInstrument) { return new TestCheckoutResponse([]); } @@ -267,28 +267,28 @@ public function getWalletResponse() ]; } - public function getPaymentMethodResponse() + public function getPaymentInstrumentResponse() { return [ 'requestMethod' => $this->requestMethod, ]; } - public function tokenizePaymentMethodResponse() + public function tokenizePaymentInstrumentResponse() { return [ 'requestMethod' => $this->requestMethod, ]; } - public function updatePaymentMethodResponse() + public function updatePaymentInstrumentResponse() { return [ 'requestMethod' => $this->requestMethod, ]; } - public function deletePaymentMethodResponse() + public function deletePaymentInstrumentResponse() { return [ 'requestMethod' => $this->requestMethod, From c10f975d991d9ba1d388601e121aa93f5f9bc6ad Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 1 May 2024 07:08:14 -0600 Subject: [PATCH 02/36] Update payavel/orchestration to v2.0.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4341fe9..5a3a473 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "test": "vendor/bin/phpunit" }, "require": { - "payavel/orchestration": "dev-master" + "payavel/orchestration": "^2.0" }, "require-dev": { "orchestra/testbench": "^8.0|^9.0" From d97590cfaf0388acc3b7f42f85392a930a4d228c Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sat, 4 May 2024 07:42:20 -0600 Subject: [PATCH 03/36] Fix payment instrument renaming issues --- .../factories/PaymentInstrumentFactory.php | 10 ++++---- stubs/config-service.stub | 2 +- stubs/service-request.stub | 24 +++++++++---------- stubs/service-response.stub | 16 ++++++------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/database/factories/PaymentInstrumentFactory.php b/database/factories/PaymentInstrumentFactory.php index f855554..ac4ea35 100644 --- a/database/factories/PaymentInstrumentFactory.php +++ b/database/factories/PaymentInstrumentFactory.php @@ -35,21 +35,21 @@ public function definition() */ public function configure() { - return $this->afterMaking(function (PaymentInstrument $paymentMethod) { - if(is_null($paymentMethod->wallet_id)) { + return $this->afterMaking(function (PaymentInstrument $paymentInstrument) { + if(is_null($paymentInstrument->wallet_id)) { $wallet = Wallet::inRandomOrder()->firstOr( fn () => Wallet::factory()->create() ); - $paymentMethod->wallet_id = $wallet->id; + $paymentInstrument->wallet_id = $wallet->id; } - if (is_null($paymentMethod->type_id)) { + if (is_null($paymentInstrument->type_id)) { $type = PaymentType::inRandomOrder()->firstOr( fn () => PaymentType::factory()->create() ); - $paymentMethod->type_id = $type->id; + $paymentInstrument->type_id = $type->id; } }); } diff --git a/stubs/config-service.stub b/stubs/config-service.stub index 3978dbd..9a55273 100644 --- a/stubs/config-service.stub +++ b/stubs/config-service.stub @@ -83,7 +83,7 @@ return [ | */ // 'models' => [ - // \Payavel\Checkout\Models\PaymentMethod::class => \App\Models\PaymentMethod::class, + // \Payavel\Checkout\Models\PaymentInstrument::class => \App\Models\PaymentInstrument::class, // \Payavel\Checkout\Models\PaymentTransaction::class => \App\Models\PaymentTransaction::class, // \Payavel\Checkout\Models\PaymentTransactionEvent::class => \App\Models\PaymentTransactionEvent::class, // \Payavel\Checkout\Models\PaymentType::class => \App\Models\PaymentType::class, diff --git a/stubs/service-request.stub b/stubs/service-request.stub index fcec122..a50adae 100644 --- a/stubs/service-request.stub +++ b/stubs/service-request.stub @@ -5,7 +5,7 @@ namespace App\Services\Checkout; use App\Services\Checkout\Contracts\CheckoutRequester; use Payavel\Checkout\CheckoutRequest; use Payavel\Checkout\Contracts\Billable; -use Payavel\Checkout\Models\PaymentMethod; +use Payavel\Checkout\Models\PaymentInstrument; use Payavel\Checkout\Models\PaymentTransaction; use Payavel\Checkout\Models\Wallet; @@ -33,47 +33,47 @@ class {{ Provider }}CheckoutRequest extends CheckoutRequest implements CheckoutR } /** - * Retrieve the payment method's details from the provider. + * Retrieve the payment instrument's details from the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function getPaymentMethod(PaymentMethod $paymentMethod) + public function getPaymentInstrument(PaymentInstrument $paymentInstrument) { // } /** - * Store the payment method details at the provider. + * Store the payment instrument details at the provider. * * @param \Payavel\Checkout\Contracts\Billable $billable * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function tokenizePaymentMethod(Billable $billable, $data) + public function tokenizePaymentInstrument(Billable $billable, $data) { // } /** - * Update the payment method's details at the provider. + * Update the payment instrument's details at the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function updatePaymentMethod(PaymentMethod $paymentMethod, $data) + public function updatePaymentInstrument(PaymentInstrument $paymentInstrument, $data) { // } /** - * Delete the payment method at the provider. + * Delete the payment instrument at the provider. * - * @param \Payavel\Checkout\Models\PaymentMethod $paymentMethod + * @param \Payavel\Checkout\Models\PaymentInstrument $paymentInstrument * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function deletePaymentMethod(PaymentMethod $paymentMethod) + public function deletePaymentInstrument(PaymentInstrument $paymentInstrument) { // } diff --git a/stubs/service-response.stub b/stubs/service-response.stub index a5f7f26..30a78f1 100644 --- a/stubs/service-response.stub +++ b/stubs/service-response.stub @@ -38,41 +38,41 @@ class {{ Provider }}CheckoutResponse extends CheckoutResponse implements Checkou } /** - * Maps details from the getPaymentMethod() response to the expected format. + * Maps details from the getPaymentInstrument() response to the expected format. * * @return array|mixed */ - public function getPaymentMethodResponse() + public function getPaymentInstrumentResponse() { // } /** - * Maps details from the tokenizePaymentMethod() response to the expected format. + * Maps details from the tokenizePaymentInstrument() response to the expected format. * * @return array|mixed */ - public function tokenizePaymentMethodResponse() + public function tokenizePaymentInstrumentResponse() { // } /** - * Maps details from the updatePaymentMethod() response to the expected format. + * Maps details from the updatePaymentInstrument() response to the expected format. * * @return array|mixed */ - public function updatePaymentMethodResponse() + public function updatePaymentInstrumentResponse() { // } /** - * Maps details from the deletePaymentMethod() response to the expected format. + * Maps details from the deletePaymentInstrument() response to the expected format. * * @return array|mixed */ - public function deletePaymentMethodResponse() + public function deletePaymentInstrumentResponse() { // } From 76369ce68eb2f0d3d2e0a499cb0d0b513016cce5 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sat, 4 May 2024 08:33:31 -0600 Subject: [PATCH 04/36] Rename PaymentTransaction to Payment --- ...nsactionFactory.php => PaymentFactory.php} | 8 +++--- .../PaymentTransactionEventFactory.php | 8 +++--- ..._01_000010_create_base_checkout_tables.php | 8 +++--- src/Contracts/CheckoutRequester.php | 27 ++++++++++--------- src/Facades/Checkout.php | 8 +++--- .../{PaymentTransaction.php => Payment.php} | 18 +++++++------ src/Models/PaymentInstrument.php | 6 ++--- src/Models/PaymentTransactionEvent.php | 8 +++--- src/Traits/CheckoutRequests.php | 27 ++++++++++--------- stubs/config-service.stub | 2 +- stubs/service-request.stub | 26 +++++++++--------- tests/Unit/TestCheckoutGateway.php | 20 +++++++------- 12 files changed, 86 insertions(+), 80 deletions(-) rename database/factories/{PaymentTransactionFactory.php => PaymentFactory.php} (90%) rename src/Models/{PaymentTransaction.php => Payment.php} (85%) diff --git a/database/factories/PaymentTransactionFactory.php b/database/factories/PaymentFactory.php similarity index 90% rename from database/factories/PaymentTransactionFactory.php rename to database/factories/PaymentFactory.php index 906f4e1..d9ddbd9 100644 --- a/database/factories/PaymentTransactionFactory.php +++ b/database/factories/PaymentFactory.php @@ -3,19 +3,19 @@ namespace Payavel\Checkout\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; -use Payavel\Checkout\Models\PaymentTransaction; +use Payavel\Checkout\Models\Payment; use Payavel\Checkout\CheckoutStatus; use Payavel\Orchestration\Models\Account; use Payavel\Orchestration\Models\Provider; -class PaymentTransactionFactory extends Factory +class PaymentFactory extends Factory { /** * The name of the factory's corresponding model. * * @var string */ - protected $model = PaymentTransaction::class; + protected $model = Payment::class; /** * Define the model's default state. @@ -39,7 +39,7 @@ public function definition() */ public function configure() { - return $this->afterMaking(function (PaymentTransaction $transaction) { + return $this->afterMaking(function (Payment $transaction) { if (is_null($transaction->provider_id)) { $provider = ! is_null($transaction->payment_instrument_id) ? $transaction->paymentInstrument->provider diff --git a/database/factories/PaymentTransactionEventFactory.php b/database/factories/PaymentTransactionEventFactory.php index 275b072..2ce55a1 100644 --- a/database/factories/PaymentTransactionEventFactory.php +++ b/database/factories/PaymentTransactionEventFactory.php @@ -3,7 +3,7 @@ namespace Payavel\Checkout\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; -use Payavel\Checkout\Models\PaymentTransaction; +use Payavel\Checkout\Models\Payment; use Payavel\Checkout\Models\PaymentTransactionEvent; use Payavel\Checkout\CheckoutStatus; @@ -43,10 +43,10 @@ public function definition() public function configure() { return $this->afterMaking(function (PaymentTransactionEvent $transactionEvent) { - if (is_null($transactionEvent->transaction_id)) { - $transaction = PaymentTransaction::factory()->create(); + if (is_null($transactionEvent->payment_id)) { + $payment = Payment::factory()->create(); - $transactionEvent->transaction_id = $transaction->id; + $transactionEvent->payment_id = $payment->id; } if (is_null($transactionEvent->amount)) { diff --git a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php index 17c997c..73667d3 100644 --- a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php +++ b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php @@ -49,7 +49,7 @@ public function up() $table->foreign('type_id')->references('id')->on('payment_types'); }); - Schema::create('payment_transactions', function (Blueprint $table) use ($usingDatabaseDriver) { + Schema::create('payments', function (Blueprint $table) use ($usingDatabaseDriver) { $table->bigIncrements('id'); $table->string('provider_id'); $table->string('account_id'); @@ -71,14 +71,14 @@ public function up() Schema::create('payment_transaction_events', function (Blueprint $table) { $table->bigIncrements('id'); - $table->unsignedBigInteger('transaction_id'); + $table->unsignedBigInteger('payment_id'); $table->string('reference')->nullable(); $table->unsignedBigInteger('amount'); $table->smallInteger('status_code'); $table->json('details')->nullable(); $table->timestamps(); - $table->foreign('transaction_id')->references('id')->on('payment_transactions')->onDelete('cascade'); + $table->foreign('payment_id')->references('id')->on('payments')->onDelete('cascade'); }); } @@ -90,7 +90,7 @@ public function up() public function down() { Schema::dropIfExists('payment_transaction_events'); - Schema::dropIfExists('payment_transactions'); + Schema::dropIfExists('payments'); Schema::dropIfExists('payment_instruments'); Schema::dropIfExists('payment_types'); Schema::dropIfExists('wallets'); diff --git a/src/Contracts/CheckoutRequester.php b/src/Contracts/CheckoutRequester.php index a7e2b14..cef067a 100644 --- a/src/Contracts/CheckoutRequester.php +++ b/src/Contracts/CheckoutRequester.php @@ -4,7 +4,7 @@ use Payavel\Checkout\Contracts\Billable; use Payavel\Checkout\Models\PaymentInstrument; -use Payavel\Checkout\Models\PaymentTransaction; +use Payavel\Checkout\Models\Payment; use Payavel\Checkout\Models\Wallet; interface CheckoutRequester @@ -52,7 +52,7 @@ public function updatePaymentInstrument(PaymentInstrument $paymentInstrument, $d public function deletePaymentInstrument(PaymentInstrument $paymentInstrument); /** - * Authorize a transaction. + * Authorize a payment. * * @param array|mixed $data * @param \Payavel\Checkout\Contracts\Billable|null $billable @@ -61,37 +61,38 @@ public function deletePaymentInstrument(PaymentInstrument $paymentInstrument); public function authorize($data, Billable $billable = null); /** - * Capture a previously authorized transaction. + * Capture an authorized payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function capture(PaymentTransaction $transaction, $data = []); + public function capture(Payment $payment, $data = []); + // ToDo: The param should be an instance of Transactionable (Payment, Refund or Dispute) /** * Retrieve the transaction details from the provider. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $transaction * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function getTransaction(PaymentTransaction $transaction); + public function getTransaction(Payment $transaction); /** - * Void a previously authorized transaction. + * Void an authorized payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function void(PaymentTransaction $transaction, $data = []); + public function void(Payment $payment, $data = []); /** - * Refund a previously captured transaction. + * Refund a payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function refund(PaymentTransaction $transaction, $data = []); + public function refund(Payment $payment, $data = []); } diff --git a/src/Facades/Checkout.php b/src/Facades/Checkout.php index 7d71816..cd134e4 100644 --- a/src/Facades/Checkout.php +++ b/src/Facades/Checkout.php @@ -21,10 +21,10 @@ * @method static \Payavel\Checkout\CheckoutResponse updatePaymentInstrument(\Payavel\Checkout\Models\PaymentInstrument $paymentInstrument, $data) * @method static \Payavel\Checkout\CheckoutResponse deletePaymentInstrument(\Payavel\Checkout\Models\PaymentInstrument $paymentInstrument) * @method static \Payavel\Checkout\CheckoutResponse authorize($data, \Payavel\Checkout\Contracts\Billable $billable = null) - * @method static \Payavel\Checkout\CheckoutResponse capture(\Payavel\Checkout\Models\PaymentTransaction $transaction, $data = []) - * @method static \Payavel\Checkout\CheckoutResponse getTransaction(\Payavel\Checkout\Models\PaymentTransaction $transaction) - * @method static \Payavel\Checkout\CheckoutResponse void(\Payavel\Checkout\Models\PaymentTransaction $transaction, $data = []) - * @method static \Payavel\Checkout\CheckoutResponse refund(\Payavel\Checkout\Models\PaymentTransaction $transaction, $data = []) + * @method static \Payavel\Checkout\CheckoutResponse capture(\Payavel\Checkout\Models\Payment $payment, $data = []) + * @method static \Payavel\Checkout\CheckoutResponse getTransaction(\Payavel\Checkout\Models\Payment $transaction) + * @method static \Payavel\Checkout\CheckoutResponse void(\Payavel\Checkout\Models\Payment $payment, $data = []) + * @method static \Payavel\Checkout\CheckoutResponse refund(\Payavel\Checkout\Models\Payment $payment, $data = []) * * @see \Payavel\Checkout\CheckoutGateway */ diff --git a/src/Models/PaymentTransaction.php b/src/Models/Payment.php similarity index 85% rename from src/Models/PaymentTransaction.php rename to src/Models/Payment.php index 857b604..514b10d 100644 --- a/src/Models/PaymentTransaction.php +++ b/src/Models/Payment.php @@ -9,7 +9,7 @@ use Payavel\Orchestration\Support\ServiceConfig; use Payavel\Orchestration\Traits\HasFactory; -class PaymentTransaction extends Model +class Payment extends Model { use ConfiguresCheckoutGateway; use HasFactory; @@ -50,7 +50,7 @@ protected static function getFactoryNamespace() } /** - * Get the payment instrument used for this transaction. + * Get the payment instrument used to process this payment. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ @@ -60,7 +60,7 @@ public function paymentInstrument() } /** - * Get the provider the transaction belongs to. + * Get the provider that processed the payment. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ @@ -70,7 +70,7 @@ public function provider() } /** - * Get the account the transaction belongs to. + * Get the account the payment belongs to. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ @@ -80,7 +80,7 @@ public function account() } /** - * Get the transaction's event history. + * Get the payment transaction's event history. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ @@ -89,8 +89,10 @@ public function events() return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentTransactionEvent::class, PaymentTransactionEvent::class), 'transaction_id'); } + // ToDo: Figure out the new TransactionEvent idea. + /** - * Fetch the transaction details from the provider. + * Fetch the payment details from the provider. * * @return \Payavel\Checkout\CheckoutResponse */ @@ -100,7 +102,7 @@ public function fetch() } /** - * Request the provider to void the transaction. + * Request the provider to void the payment. * * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse @@ -111,7 +113,7 @@ public function void($data = []) } /** - * Request the provider to refund the transaction. + * Request the provider to refund the payment. * * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse diff --git a/src/Models/PaymentInstrument.php b/src/Models/PaymentInstrument.php index d00fbd9..7a6ae98 100644 --- a/src/Models/PaymentInstrument.php +++ b/src/Models/PaymentInstrument.php @@ -89,13 +89,13 @@ public function type() } /** - * Get the transactions that this payment instrument has triggered. + * Get the payments that this instrument has been used for. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function transactions() + public function payments() { - return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentTransaction::class, PaymentTransaction::class)); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); } /** diff --git a/src/Models/PaymentTransactionEvent.php b/src/Models/PaymentTransactionEvent.php index 48ccf75..47d80f1 100644 --- a/src/Models/PaymentTransactionEvent.php +++ b/src/Models/PaymentTransactionEvent.php @@ -46,12 +46,14 @@ protected static function getFactoryNamespace() } /** - * Get the event's original transaction. + * Get the event's originating payment. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function transaction() + public function payment() { - return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentTransaction::class, PaymentTransaction::class)); + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); } + + // ToDo: Figure out the new TransactionEvent idea. } diff --git a/src/Traits/CheckoutRequests.php b/src/Traits/CheckoutRequests.php index ae31530..facecca 100644 --- a/src/Traits/CheckoutRequests.php +++ b/src/Traits/CheckoutRequests.php @@ -4,7 +4,7 @@ use Payavel\Checkout\Contracts\Billable; use Payavel\Checkout\Models\PaymentInstrument; -use Payavel\Checkout\Models\PaymentTransaction; +use Payavel\Checkout\Models\Payment; use Payavel\Checkout\Models\Wallet; use Payavel\Orchestration\Traits\ThrowsRuntimeException; @@ -70,7 +70,7 @@ public function deletePaymentInstrument(PaymentInstrument $paymentInstrument) } /** - * Authorize a transaction. + * Authorize a payment. * * @param array|mixed $data * @param \Payavel\Checkout\Contracts\Billable|null $billable @@ -82,48 +82,49 @@ public function authorize($data, Billable $billable = null) } /** - * Capture a previously authorized transaction. + * Capture an authorized payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function capture(PaymentTransaction $transaction, $data = []) + public function capture(Payment $payment, $data = []) { $this->throwRuntimeException(__FUNCTION__); } + // ToDo: The param should be an instance of Transactionable (Payment, Refund or Dispute) /** * Retrieve the transaction details from the provider. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $transaction * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function getTransaction(PaymentTransaction $transaction) + public function getTransaction(Payment $transaction) { $this->throwRuntimeException(__FUNCTION__); } /** - * Void a previously authorized transaction. + * Void an authorized payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $paymentTransaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function void(PaymentTransaction $paymentTransaction, $data = []) + public function void(Payment $payment, $data = []) { $this->throwRuntimeException(__FUNCTION__); } /** - * Refund a previously captured transaction. + * Refund a payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $paymentTransaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function refund(PaymentTransaction $paymentTransaction, $data = []) + public function refund(Payment $payment, $data = []) { $this->throwRuntimeException(__FUNCTION__); } diff --git a/stubs/config-service.stub b/stubs/config-service.stub index 9a55273..9bdac91 100644 --- a/stubs/config-service.stub +++ b/stubs/config-service.stub @@ -84,7 +84,7 @@ return [ */ // 'models' => [ // \Payavel\Checkout\Models\PaymentInstrument::class => \App\Models\PaymentInstrument::class, - // \Payavel\Checkout\Models\PaymentTransaction::class => \App\Models\PaymentTransaction::class, + // \Payavel\Checkout\Models\Payment::class => \App\Models\Payment::class, // \Payavel\Checkout\Models\PaymentTransactionEvent::class => \App\Models\PaymentTransactionEvent::class, // \Payavel\Checkout\Models\PaymentType::class => \App\Models\PaymentType::class, // \Payavel\Checkout\Models\Wallet::class => \App\Models\Wallet::class, diff --git a/stubs/service-request.stub b/stubs/service-request.stub index a50adae..b9d1ec7 100644 --- a/stubs/service-request.stub +++ b/stubs/service-request.stub @@ -6,7 +6,7 @@ use App\Services\Checkout\Contracts\CheckoutRequester; use Payavel\Checkout\CheckoutRequest; use Payavel\Checkout\Contracts\Billable; use Payavel\Checkout\Models\PaymentInstrument; -use Payavel\Checkout\Models\PaymentTransaction; +use Payavel\Checkout\Models\Payment; use Payavel\Checkout\Models\Wallet; class {{ Provider }}CheckoutRequest extends CheckoutRequest implements CheckoutRequester @@ -79,7 +79,7 @@ class {{ Provider }}CheckoutRequest extends CheckoutRequest implements CheckoutR } /** - * Authorize a transaction. + * Authorize a payment. * * @param array|mixed $data * @param \Payavel\Checkout\Contracts\Billable|null $billable @@ -91,13 +91,13 @@ class {{ Provider }}CheckoutRequest extends CheckoutRequest implements CheckoutR } /** - * Capture a previously authorized transaction. + * Capture any authorized payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function capture(PaymentTransaction $transaction, $data = []) + public function capture(Payment $payment, $data = []) { // } @@ -105,34 +105,34 @@ class {{ Provider }}CheckoutRequest extends CheckoutRequest implements CheckoutR /** * Retrieve the transaction details from the provider. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $transaction * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function getTransaction(PaymentTransaction $transaction) + public function getTransaction(Payment $transaction) { // } /** - * Void a previously authorized transaction. + * Void an authorized payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed $data * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function void(PaymentTransaction $transaction, $data = []) + public function void(Payment $payment, $data = []) { // } /** - * Refund a previously captured transaction. + * Refund a payment. * - * @param \Payavel\Checkout\Models\PaymentTransaction $transaction + * @param \Payavel\Checkout\Models\Payment $payment * @param array|mixed * @return \Payavel\Checkout\CheckoutResponse|mixed */ - public function refund(PaymentTransaction $transaction, $data = []) + public function refund(Payment $payment, $data = []) { // } diff --git a/tests/Unit/TestCheckoutGateway.php b/tests/Unit/TestCheckoutGateway.php index 09be8c0..81da450 100644 --- a/tests/Unit/TestCheckoutGateway.php +++ b/tests/Unit/TestCheckoutGateway.php @@ -5,7 +5,7 @@ use Payavel\Checkout\Contracts\Billable; use Payavel\Checkout\Facades\Checkout; use Payavel\Checkout\Models\PaymentInstrument; -use Payavel\Checkout\Models\PaymentTransaction; +use Payavel\Checkout\Models\Payment; use Payavel\Checkout\Models\Wallet; use Payavel\Checkout\CheckoutRequest; use Payavel\Checkout\CheckoutResponse; @@ -134,12 +134,12 @@ public function authorize_method_returns_configured_response() #[Test] public function capture_method_returns_configured_response() { - $transaction = PaymentTransaction::factory()->create([ + $payment = Payment::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); - $response = Checkout::capture($transaction); + $response = Checkout::capture($payment); $this->assertResponseIsConfigured($response); @@ -149,7 +149,7 @@ public function capture_method_returns_configured_response() #[Test] public function get_transaction_method_returns_configured_response() { - $transaction = PaymentTransaction::factory()->create([ + $transaction = Payment::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); @@ -164,7 +164,7 @@ public function get_transaction_method_returns_configured_response() #[Test] public function void_method_returns_configured_response() { - $transaction = PaymentTransaction::factory()->create([ + $transaction = Payment::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); @@ -179,7 +179,7 @@ public function void_method_returns_configured_response() #[Test] public function refund_method_returns_configured_response() { - $transaction = PaymentTransaction::factory()->create([ + $transaction = Payment::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); @@ -237,22 +237,22 @@ public function authorize($data, Billable $billable = null) return new TestCheckoutResponse([]); } - public function capture(PaymentTransaction $transaction, $data = []) + public function capture(Payment $transaction, $data = []) { return new TestCheckoutResponse([]); } - public function getTransaction(PaymentTransaction $transaction) + public function getTransaction(Payment $transaction) { return new TestCheckoutResponse([]); } - public function void(PaymentTransaction $paymentTransaction, $data = []) + public function void(Payment $paymentTransaction, $data = []) { return new TestCheckoutResponse([]); } - public function refund(PaymentTransaction $paymentTransaction, $data = []) + public function refund(Payment $paymentTransaction, $data = []) { return new TestCheckoutResponse([]); } From 21b2f0546e6519856708fd4155c23570839eb80c Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sat, 4 May 2024 08:36:53 -0600 Subject: [PATCH 05/36] There is more... --- tests/Unit/TestCheckoutGateway.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Unit/TestCheckoutGateway.php b/tests/Unit/TestCheckoutGateway.php index 81da450..42d8018 100644 --- a/tests/Unit/TestCheckoutGateway.php +++ b/tests/Unit/TestCheckoutGateway.php @@ -149,12 +149,12 @@ public function capture_method_returns_configured_response() #[Test] public function get_transaction_method_returns_configured_response() { - $transaction = Payment::factory()->create([ + $payment = Payment::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); - $response = Checkout::getTransaction($transaction); + $response = Checkout::getTransaction($payment); $this->assertResponseIsConfigured($response); @@ -164,12 +164,12 @@ public function get_transaction_method_returns_configured_response() #[Test] public function void_method_returns_configured_response() { - $transaction = Payment::factory()->create([ + $payment = Payment::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); - $response = Checkout::void($transaction); + $response = Checkout::void($payment); $this->assertResponseIsConfigured($response); @@ -179,12 +179,12 @@ public function void_method_returns_configured_response() #[Test] public function refund_method_returns_configured_response() { - $transaction = Payment::factory()->create([ + $payment = Payment::factory()->create([ 'provider_id' => Checkout::getProvider()->getId(), 'account_id' => Checkout::getAccount()->getId(), ]); - $response = Checkout::refund($transaction); + $response = Checkout::refund($payment); $this->assertResponseIsConfigured($response); @@ -237,7 +237,7 @@ public function authorize($data, Billable $billable = null) return new TestCheckoutResponse([]); } - public function capture(Payment $transaction, $data = []) + public function capture(Payment $payment, $data = []) { return new TestCheckoutResponse([]); } @@ -247,12 +247,12 @@ public function getTransaction(Payment $transaction) return new TestCheckoutResponse([]); } - public function void(Payment $paymentTransaction, $data = []) + public function void(Payment $payment, $data = []) { return new TestCheckoutResponse([]); } - public function refund(Payment $paymentTransaction, $data = []) + public function refund(Payment $payment, $data = []) { return new TestCheckoutResponse([]); } From 4d5d1947a5c7f437122c50e99cebc973f8241d0c Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sat, 4 May 2024 09:22:38 -0600 Subject: [PATCH 06/36] Rename PaymentTransactionEvent to TransactionEvent --- database/factories/PaymentFactory.php | 26 +++++++++---------- ...actory.php => TransactionEventFactory.php} | 8 +++--- ..._01_000010_create_base_checkout_tables.php | 8 +++--- src/Models/Payment.php | 6 ++--- src/Models/PaymentType.php | 2 +- ...nsactionEvent.php => TransactionEvent.php} | 2 +- stubs/config-service.stub | 2 +- 7 files changed, 27 insertions(+), 27 deletions(-) rename database/factories/{PaymentTransactionEventFactory.php => TransactionEventFactory.php} (83%) rename src/Models/{PaymentTransactionEvent.php => TransactionEvent.php} (96%) diff --git a/database/factories/PaymentFactory.php b/database/factories/PaymentFactory.php index d9ddbd9..a11ef62 100644 --- a/database/factories/PaymentFactory.php +++ b/database/factories/PaymentFactory.php @@ -39,36 +39,36 @@ public function definition() */ public function configure() { - return $this->afterMaking(function (Payment $transaction) { - if (is_null($transaction->provider_id)) { - $provider = ! is_null($transaction->payment_instrument_id) - ? $transaction->paymentInstrument->provider + return $this->afterMaking(function (Payment $payment) { + if (is_null($payment->provider_id)) { + $provider = ! is_null($payment->instrument_id) + ? $payment->instrument->provider : Provider::whereHas( 'accounts', - fn ($query) => $query->where('payment_accounts.id', $transaction->account_id) + fn ($query) => $query->where('payment_accounts.id', $payment->account_id) )->inRandomOrder()->firstOr( fn () => Provider::factory()->create() ); - $transaction->provider_id = $provider->id; + $payment->provider_id = $provider->id; } - if (is_null($transaction->account_id)) { - $account = ! is_null($transaction->payment_instrument_id) - ? $transaction->paymentInstrument->account + if (is_null($payment->account_id)) { + $account = ! is_null($payment->instrument_id) + ? $payment->instrument->account : Account::whereHas( 'providers', - fn ($query) => $query->where('payment_providers.id', $transaction->provider_id) + fn ($query) => $query->where('payment_providers.id', $payment->provider_id) )->inRandomOrder() - ->firstOr(function () use ($transaction) { + ->firstOr(function () use ($payment) { $account = Account::factory()->create(); - $account->providers()->attach($transaction->provider_id, ['is_default' => true]); + $account->providers()->attach($payment->provider_id, ['is_default' => true]); return $account; }); - $transaction->account_id = $account->id; + $payment->account_id = $account->id; } }); } diff --git a/database/factories/PaymentTransactionEventFactory.php b/database/factories/TransactionEventFactory.php similarity index 83% rename from database/factories/PaymentTransactionEventFactory.php rename to database/factories/TransactionEventFactory.php index 2ce55a1..6e71931 100644 --- a/database/factories/PaymentTransactionEventFactory.php +++ b/database/factories/TransactionEventFactory.php @@ -4,17 +4,17 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Payavel\Checkout\Models\Payment; -use Payavel\Checkout\Models\PaymentTransactionEvent; +use Payavel\Checkout\Models\TransactionEvent; use Payavel\Checkout\CheckoutStatus; -class PaymentTransactionEventFactory extends Factory +class TransactionEventFactory extends Factory { /** * The name of the factory's corresponding model. * * @var string */ - protected $model = PaymentTransactionEvent::class; + protected $model = TransactionEvent::class; /** * Define the model's default state. @@ -42,7 +42,7 @@ public function definition() */ public function configure() { - return $this->afterMaking(function (PaymentTransactionEvent $transactionEvent) { + return $this->afterMaking(function (TransactionEvent $transactionEvent) { if (is_null($transactionEvent->payment_id)) { $payment = Payment::factory()->create(); diff --git a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php index 73667d3..3741b26 100644 --- a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php +++ b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php @@ -56,7 +56,7 @@ public function up() $table->string('reference'); $table->unsignedInteger('amount'); $table->char('currency', 3)->default('USD'); - $table->unsignedBigInteger('payment_instrument_id')->nullable(); + $table->unsignedBigInteger('instrument_id')->nullable(); $table->unsignedSmallInteger('status_code'); $table->json('details')->nullable(); $table->timestamps(); @@ -66,10 +66,10 @@ public function up() $table->foreign('account_id')->references('id')->on('accounts')->onUpdate('cascade'); } - $table->foreign('payment_instrument_id')->references('id')->on('payment_instruments')->onDelete('set null'); + $table->foreign('instrument_id')->references('id')->on('payment_instruments')->onDelete('set null'); }); - Schema::create('payment_transaction_events', function (Blueprint $table) { + Schema::create('transaction_events', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('payment_id'); $table->string('reference')->nullable(); @@ -89,7 +89,7 @@ public function up() */ public function down() { - Schema::dropIfExists('payment_transaction_events'); + Schema::dropIfExists('transaction_events'); Schema::dropIfExists('payments'); Schema::dropIfExists('payment_instruments'); Schema::dropIfExists('payment_types'); diff --git a/src/Models/Payment.php b/src/Models/Payment.php index 514b10d..92cb295 100644 --- a/src/Models/Payment.php +++ b/src/Models/Payment.php @@ -50,11 +50,11 @@ protected static function getFactoryNamespace() } /** - * Get the payment instrument used to process this payment. + * Get the instrument used to process this payment. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function paymentInstrument() + public function instrument() { return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class)); } @@ -86,7 +86,7 @@ public function account() */ public function events() { - return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentTransactionEvent::class, PaymentTransactionEvent::class), 'transaction_id'); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . TransactionEvent::class, TransactionEvent::class), 'transaction_id'); } // ToDo: Figure out the new TransactionEvent idea. diff --git a/src/Models/PaymentType.php b/src/Models/PaymentType.php index b60bb18..c00fe00 100644 --- a/src/Models/PaymentType.php +++ b/src/Models/PaymentType.php @@ -32,7 +32,7 @@ protected static function getFactoryNamespace() * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function paymentInstruments() + public function instruments() { return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class), 'type_id'); } diff --git a/src/Models/PaymentTransactionEvent.php b/src/Models/TransactionEvent.php similarity index 96% rename from src/Models/PaymentTransactionEvent.php rename to src/Models/TransactionEvent.php index 47d80f1..a74f425 100644 --- a/src/Models/PaymentTransactionEvent.php +++ b/src/Models/TransactionEvent.php @@ -6,7 +6,7 @@ use Payavel\Orchestration\Support\ServiceConfig; use Payavel\Orchestration\Traits\HasFactory; -class PaymentTransactionEvent extends Model +class TransactionEvent extends Model { use HasFactory; diff --git a/stubs/config-service.stub b/stubs/config-service.stub index 9bdac91..988d8b0 100644 --- a/stubs/config-service.stub +++ b/stubs/config-service.stub @@ -85,7 +85,7 @@ return [ // 'models' => [ // \Payavel\Checkout\Models\PaymentInstrument::class => \App\Models\PaymentInstrument::class, // \Payavel\Checkout\Models\Payment::class => \App\Models\Payment::class, - // \Payavel\Checkout\Models\PaymentTransactionEvent::class => \App\Models\PaymentTransactionEvent::class, + // \Payavel\Checkout\Models\TransactionEvent::class => \App\Models\TransactionEvent::class, // \Payavel\Checkout\Models\PaymentType::class => \App\Models\PaymentType::class, // \Payavel\Checkout\Models\Wallet::class => \App\Models\Wallet::class, // ], From 2edab897b185a6ee873981d91ce14b698cce488c Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sat, 4 May 2024 13:49:26 -0600 Subject: [PATCH 07/36] Update base migrations for checkout --- ..._01_000010_create_base_checkout_tables.php | 72 +++++++++++++++---- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php index 3741b26..f8db810 100644 --- a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php +++ b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php @@ -16,37 +16,49 @@ public function up() $usingDatabaseDriver = ServiceConfig::get('checkout', 'defaults.driver') === 'database'; Schema::create('payment_types', function (Blueprint $table) { - $table->smallIncrements('id'); + $table->string('id')->primary(); $table->string('name'); - $table->string('slug')->unique(); + $table->string('logo'); $table->timestamps(); }); + Schema::create('payment_rails', function (Blueprint $table) { + $table->string('id')->primary(); + $table->string('parent_type_id'); + $table->string('type_id'); + $table->timestamps(); + + $table->foreign('parent_type_id')->references('id')->on('payment_types')->onUpdate('cascade')->onDelete('cascade'); + $table->foreign('type_id')->references('id')->on('payment_types')->onUpdate('cascade')->onDelete('cascade'); + }); + Schema::create('wallets', function (Blueprint $table) use ($usingDatabaseDriver) { $table->bigIncrements('id'); - $table->unsignedBigInteger('billable_id')->nullable(); - $table->string('billable_type')->nullable(); + $table->morphs('billable'); $table->string('provider_id'); $table->string('account_id'); - $table->string('token'); + $table->string('reference'); $table->timestamps(); if ($usingDatabaseDriver) { $table->foreign('provider_id')->references('id')->on('providers')->onUpdate('cascade')->onDelete('cascade'); $table->foreign('account_id')->references('id')->on('accounts')->onUpdate('cascade')->onDelete('cascade'); } + + $table->index('reference'); }); Schema::create('payment_instruments', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('wallet_id'); - $table->string('token'); - $table->unsignedSmallInteger('type_id'); + $table->string('type_id'); + $table->string('reference'); $table->json('details')->nullable(); $table->timestamps(); $table->foreign('wallet_id')->references('id')->on('wallets')->onDelete('cascade'); - $table->foreign('type_id')->references('id')->on('payment_types'); + $table->foreign('type_id')->references('id')->on('payment_types')->onUpdate('cascade'); + $table->index('reference'); }); Schema::create('payments', function (Blueprint $table) use ($usingDatabaseDriver) { @@ -54,10 +66,11 @@ public function up() $table->string('provider_id'); $table->string('account_id'); $table->string('reference'); + $table->boolean('authorized')->default(true); $table->unsignedInteger('amount'); $table->char('currency', 3)->default('USD'); + $table->string('rail_id'); $table->unsignedBigInteger('instrument_id')->nullable(); - $table->unsignedSmallInteger('status_code'); $table->json('details')->nullable(); $table->timestamps(); @@ -66,19 +79,49 @@ public function up() $table->foreign('account_id')->references('id')->on('accounts')->onUpdate('cascade'); } + $table->index('reference'); + $table->index('authorized'); + $table->foreign('rail_id')->references('id')->on('payment_rails')->onUpdate('cascade'); $table->foreign('instrument_id')->references('id')->on('payment_instruments')->onDelete('set null'); }); + Schema::create('refunds', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->unsignedBigInteger('payment_id'); + $table->string('reference'); + $table->unsignedInteger('amount'); + $table->json('details')->nullable(); + $table->timestamps(); + + $table->foreign('payment_id')->references('id')->on('payments')->onDelete('cascade'); + $table->index('reference'); + }); + + Schema::create('disputes', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->unsignedBigInteger('payment_id'); + $table->string('reference'); + $table->unsignedInteger('amount'); + $table->json('details')->nullable(); + $table->timestamps(); + + $table->foreign('payment_id')->references('id')->on('payments')->onDelete('cascade'); + $table->index('reference'); + }); + Schema::create('transaction_events', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('payment_id'); - $table->string('reference')->nullable(); - $table->unsignedBigInteger('amount'); - $table->smallInteger('status_code'); + $table->morphs('transactionable'); + $table->string('reference'); + $table->unsignedInteger('status_code'); + $table->unsignedInteger('amount'); $table->json('details')->nullable(); $table->timestamps(); $table->foreign('payment_id')->references('id')->on('payments')->onDelete('cascade'); + $table->index('reference'); + $table->index('status_code'); }); } @@ -90,9 +133,12 @@ public function up() public function down() { Schema::dropIfExists('transaction_events'); + Schema::dropIfExists('disputes'); + Schema::dropIfExists('refunds'); Schema::dropIfExists('payments'); Schema::dropIfExists('payment_instruments'); - Schema::dropIfExists('payment_types'); Schema::dropIfExists('wallets'); + Schema::dropDatabaseIfExists('payment_rails'); + Schema::dropIfExists('payment_types'); } }; From cc5c1c5267e7670808e34d181ec086b9f83f8f18 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sun, 5 May 2024 06:08:42 -0600 Subject: [PATCH 08/36] Adapt `Wallet` Model --- database/factories/WalletFactory.php | 2 +- src/Models/Wallet.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/factories/WalletFactory.php b/database/factories/WalletFactory.php index 50c3af6..6b77739 100644 --- a/database/factories/WalletFactory.php +++ b/database/factories/WalletFactory.php @@ -24,7 +24,7 @@ class WalletFactory extends Factory public function definition() { return [ - 'token' => $this->faker->uuid(), + 'reference' => $this->faker->uuid(), ]; } diff --git a/src/Models/Wallet.php b/src/Models/Wallet.php index 25555ec..462421e 100644 --- a/src/Models/Wallet.php +++ b/src/Models/Wallet.php @@ -26,7 +26,7 @@ class Wallet extends Model * * @var array */ - protected $hidden = ['token']; + protected $hidden = ['reference']; /** * Custom factory namespace fallback. From 6d63e26edae883313b86fb54bfb2fa56f5dd6040 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sun, 5 May 2024 07:27:17 -0600 Subject: [PATCH 09/36] Adapt `PaymentType` & `PaymentRail` models --- database/factories/PaymentRailFactory.php | 133 ++++++++++++++++++++++ database/factories/PaymentTypeFactory.php | 41 ++++--- database/seeders/PaymentTypeSeeder.php | 24 ---- src/Models/PaymentRail.php | 72 ++++++++++++ src/Models/PaymentType.php | 22 ++-- 5 files changed, 231 insertions(+), 61 deletions(-) create mode 100644 database/factories/PaymentRailFactory.php delete mode 100644 database/seeders/PaymentTypeSeeder.php create mode 100644 src/Models/PaymentRail.php diff --git a/database/factories/PaymentRailFactory.php b/database/factories/PaymentRailFactory.php new file mode 100644 index 0000000..5c323ac --- /dev/null +++ b/database/factories/PaymentRailFactory.php @@ -0,0 +1,133 @@ + 'visa', + 'type_id' => 'visa', + ], + [ + 'parent_type_id' => 'mastercard', + 'type_id' => 'mastercard', + ], + [ + 'parent_type_id' => 'amex', + 'type_id' => 'amex', + ], + [ + 'parent_type_id' => 'discover', + 'type_id' => 'discover', + ], + [ + 'parent_type_id' => 'diners_club', + 'type_id' => 'diners_club', + ], + [ + 'parent_type_id' => 'jcb', + 'type_id' => 'jcb', + ], + [ + 'parent_type_id' => 'apple_pay', + 'type_id' => 'visa', + ], + [ + 'parent_type_id' => 'apple_pay', + 'type_id' => 'mastercard', + ], + [ + 'parent_type_id' => 'apple_pay', + 'type_id' => 'amex', + ], + [ + 'parent_type_id' => 'apple_pay', + 'type_id' => 'discover', + ], + [ + 'parent_type_id' => 'google_pay', + 'type_id' => 'visa', + ], + [ + 'parent_type_id' => 'google_pay', + 'type_id' => 'mastercard', + ], + [ + 'parent_type_id' => 'google_pay', + 'type_id' => 'amex', + ], + [ + 'parent_type_id' => 'google_pay', + 'type_id' => 'discover', + ], + [ + 'parent_type_id' => 'paypal', + 'type_id' => 'paypal', + ], + ]; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + return []; + } + + public function real() + { + return $this->state(function () { + $existingPaymentRails = PaymentRail::all()->pluck('id'); + + $rail = collect(static::REAL) + ->filter(function ($realPaymentRail) use ($existingPaymentRails) { + $realPaymentRailId = $realPaymentRail['parent_type_id'] === $realPaymentRail['type_id'] + ? $realPaymentRail['type_id'] + : "{$realPaymentRail['parent_type_id']}:{$realPaymentRail['type_id']}"; + + return $existingPaymentRails->doesntContain($realPaymentRailId); + }) + ->first(); + + if (is_null($rail)) { + return []; + } + + return $rail; + }); + } + + /** + * Configure the model factory. + * + * @return $this + */ + public function configure() + { + return $this->afterMaking(function (PaymentRail $paymentRail) { + if (is_null($paymentRail->parent_type_id)) { + $paymentRail->parent_type_id = PaymentType::inRandomOrder()->firstOr( + fn () => PaymentType::factory()->create() + )->id; + } + + if (is_null($paymentRail->type_id)) { + $paymentRail->type_id = PaymentType::factory()->create()->id; + } + }); + } +} diff --git a/database/factories/PaymentTypeFactory.php b/database/factories/PaymentTypeFactory.php index bac4a86..0d9bd97 100644 --- a/database/factories/PaymentTypeFactory.php +++ b/database/factories/PaymentTypeFactory.php @@ -3,6 +3,7 @@ namespace Payavel\Checkout\Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; +use Illuminate\Support\Str; use Payavel\Checkout\Models\PaymentType; class PaymentTypeFactory extends Factory @@ -14,46 +15,42 @@ class PaymentTypeFactory extends Factory */ protected $model = PaymentType::class; - public const DEFAULTS = [ + public const REAL = [ [ + 'id' => 'visa', 'name' => 'VISA', - 'slug' => 'visa', ], [ + 'id' => 'mastercard', 'name' => 'MasterCard', - 'slug' => 'mastercard', ], [ + 'id' => 'amex', 'name' => 'AMEX', - 'slug' => 'amex', ], [ - 'name' => 'Alipay', - 'slug' => 'alipay', - ], - [ - 'name' => 'Apple Pay', - 'slug' => 'apple_pay', + 'id' => 'discover', + 'name' => 'Discover', ], [ - 'name' => 'Google Pay', - 'slug' => 'google_pay', + 'id' => 'diners_club', + 'name' => 'Diners Club', ], [ + 'id' => 'jcb', 'name' => 'JCB', - 'slug' => 'jcb', ], [ - 'name' => 'Diners Club', - 'slug' => 'diners_club', + 'id' => 'apple_pay', + 'name' => 'Apple Pay', ], [ - 'name' => 'Discover', - 'slug' => 'discover', + 'id' => 'google_pay', + 'name' => 'Google Pay', ], [ + 'id' => 'paypal', 'name' => 'PayPal', - 'slug' => 'paypal', ], ]; @@ -64,18 +61,18 @@ class PaymentTypeFactory extends Factory */ public function definition() { - $name = $this->faker->unique()->lexify('????'); + $name = Str::ucfirst($this->faker->unique()->lexify('????')); return [ - 'name' => ucfirst($name), - 'slug' => PaymentType::slugify($name), + 'id' => preg_replace('/[^a-z0-9]+/i', '_', Str::lower($name)), + 'name' => $name, ]; } public function real() { return $this->state(function () { - $type = collect(static::DEFAULTS)->whereNotIn('slug', PaymentType::all()->pluck('slug'))->first(); + $type = collect(static::REAL)->whereNotIn('id', PaymentType::all()->pluck('id'))->first(); if (is_null($type)) { return []; diff --git a/database/seeders/PaymentTypeSeeder.php b/database/seeders/PaymentTypeSeeder.php deleted file mode 100644 index 65fc868..0000000 --- a/database/seeders/PaymentTypeSeeder.php +++ /dev/null @@ -1,24 +0,0 @@ - $paymentType['slug'] - ], - [ - 'name' => $paymentType['name'], - ] - ); - } - } -} \ No newline at end of file diff --git a/src/Models/PaymentRail.php b/src/Models/PaymentRail.php new file mode 100644 index 0000000..9cd8444 --- /dev/null +++ b/src/Models/PaymentRail.php @@ -0,0 +1,72 @@ +id = $paymentRail->parent_type_id === $paymentRail->type_id + ? $paymentRail->type_id + : "{$paymentRail->parent_type_id}:{$paymentRail->type_id}"; + }); + } + + /** + * Custom factory namespace fallback. + * + * @return string + */ + protected static function getFactoryNamespace() + { + return 'Payavel\\Checkout\\Database\\Factories'; + } + + /** + * Get the parent payment type. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function parentType() + { + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentType::class, PaymentType::class)); + } + + /** + * Get the rail's payment type. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function type() + { + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentType::class, PaymentType::class)); + } + + /** + * Get the payments that were processed over this rail. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function payments() + { + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class), 'rail_id'); + } +} diff --git a/src/Models/PaymentType.php b/src/Models/PaymentType.php index c00fe00..8b345fb 100644 --- a/src/Models/PaymentType.php +++ b/src/Models/PaymentType.php @@ -10,13 +10,6 @@ class PaymentType extends Model { use HasFactory; - /** - * The attributes that aren't mass assignable. - * - * @var string[]|bool - */ - protected $guarded = ['id']; - /** * Custom factory namespace fallback. * @@ -28,23 +21,22 @@ protected static function getFactoryNamespace() } /** - * Get the payment instruments that inherit this type. + * Get the payment rail this type could potentially use. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function instruments() + public function rails() { - return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class), 'type_id'); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentRail::class, PaymentRail::class), 'parent_type_id'); } /** - * Generate a slug based off a string that follows a set of rules to make it valid. + * Get the payment instruments that inherit this type. * - * @param string $name - * @return string + * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public static function slugify($name) + public function instruments() { - return preg_replace('/[^a-z0-9]+/i', '_', trim(strtolower($name))); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class), 'type_id'); } } From ad48c3489b6cff86146d15905301fb7ce898d427 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sun, 5 May 2024 07:34:49 -0600 Subject: [PATCH 10/36] Adapt `PaymentInstrument` model --- database/factories/PaymentInstrumentFactory.php | 4 ++-- src/Models/PaymentInstrument.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/database/factories/PaymentInstrumentFactory.php b/database/factories/PaymentInstrumentFactory.php index ac4ea35..4ae9a06 100644 --- a/database/factories/PaymentInstrumentFactory.php +++ b/database/factories/PaymentInstrumentFactory.php @@ -24,7 +24,7 @@ class PaymentInstrumentFactory extends Factory public function definition() { return [ - 'token' => $this->faker->uuid(), + 'reference' => $this->faker->uuid(), ]; } @@ -36,7 +36,7 @@ public function definition() public function configure() { return $this->afterMaking(function (PaymentInstrument $paymentInstrument) { - if(is_null($paymentInstrument->wallet_id)) { + if (is_null($paymentInstrument->wallet_id)) { $wallet = Wallet::inRandomOrder()->firstOr( fn () => Wallet::factory()->create() ); diff --git a/src/Models/PaymentInstrument.php b/src/Models/PaymentInstrument.php index 7a6ae98..12fb25a 100644 --- a/src/Models/PaymentInstrument.php +++ b/src/Models/PaymentInstrument.php @@ -25,7 +25,7 @@ class PaymentInstrument extends Model * @var array */ protected $hidden = [ - 'token', + 'reference', 'details', ]; From 8db5ebfdd32b3c7d8099023709ca14611552c173 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sun, 5 May 2024 07:53:14 -0600 Subject: [PATCH 11/36] Adapt `Payment` model --- database/factories/PaymentFactory.php | 16 ++++++++-- src/Models/Payment.php | 42 +++++++++++++++++++-------- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/database/factories/PaymentFactory.php b/database/factories/PaymentFactory.php index a11ef62..0cd5200 100644 --- a/database/factories/PaymentFactory.php +++ b/database/factories/PaymentFactory.php @@ -4,7 +4,7 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Payavel\Checkout\Models\Payment; -use Payavel\Checkout\CheckoutStatus; +use Payavel\Checkout\Models\PaymentRail; use Payavel\Orchestration\Models\Account; use Payavel\Orchestration\Models\Provider; @@ -28,7 +28,6 @@ public function definition() 'reference' => $this->faker->uuid(), 'amount' => $this->faker->numberBetween(1, 999) * 100, 'currency' => $this->faker->currencyCode(), - 'status_code' => CheckoutStatus::AUTHORIZED, ]; } @@ -70,6 +69,19 @@ public function configure() $payment->account_id = $account->id; } + + if (is_null($payment->rail_id)) { + $rail = ! is_null($payment->instrument_id) + ? $payment->instrument->type->rails()->inRandomOrder()->firstOrCreate( + ['parent_type_id' => $payment->instrument->type_id], + ['type_id' => $payment->instrument->type_id] + ) : PaymentRail::inRandomOrder() + ->firstOr( + fn () => PaymentRail::factory()->create() + ); + + $payment->rail_id = $rail->id; + } }); } } diff --git a/src/Models/Payment.php b/src/Models/Payment.php index 92cb295..f3aa25d 100644 --- a/src/Models/Payment.php +++ b/src/Models/Payment.php @@ -50,46 +50,64 @@ protected static function getFactoryNamespace() } /** - * Get the instrument used to process this payment. + * Get the provider that processed the payment. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function instrument() + public function provider() { - return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class)); + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Provider::class, Provider::class)); } /** - * Get the provider that processed the payment. + * Get the account the payment belongs to. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function provider() + public function account() { - return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Provider::class, Provider::class)); + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Account::class, Account::class)); } /** - * Get the account the payment belongs to. + * Get the rail the payment was processed on. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function account() + public function rail() { - return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Account::class, Account::class)); + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentRail::class, PaymentRail::class)); } /** - * Get the payment transaction's event history. + * Get the instrument used to process this payment. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function instrument() + { + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . PaymentInstrument::class, PaymentInstrument::class)); + } + + /** + * Get the payment event full history. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function events() { - return $this->hasMany(ServiceConfig::get('checkout', 'models.' . TransactionEvent::class, TransactionEvent::class), 'transaction_id'); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . TransactionEvent::class, TransactionEvent::class)); } - // ToDo: Figure out the new TransactionEvent idea. + /** + * Get the transaction specific events. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function transactionEvents() + { + return $this->morphMany(ServiceConfig::get('checkout', 'models.' . TransactionEvent::class, TransactionEvent::class), 'transactionable'); + } /** * Fetch the payment details from the provider. From 3746f1386a74f4372da2ada53ad9b7182ae3859c Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sun, 5 May 2024 07:58:41 -0600 Subject: [PATCH 12/36] Fix integrity constraint violations --- .../2024_01_01_000010_create_base_checkout_tables.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php index f8db810..08c754b 100644 --- a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php +++ b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php @@ -18,7 +18,7 @@ public function up() Schema::create('payment_types', function (Blueprint $table) { $table->string('id')->primary(); $table->string('name'); - $table->string('logo'); + $table->string('logo')->default('checkoutshopper-live.adyen.com/checkoutshopper/images/logos/card.svg'); $table->timestamps(); }); @@ -34,7 +34,7 @@ public function up() Schema::create('wallets', function (Blueprint $table) use ($usingDatabaseDriver) { $table->bigIncrements('id'); - $table->morphs('billable'); + $table->nullableMorphs('billable'); $table->string('provider_id'); $table->string('account_id'); $table->string('reference'); From 06dab33db4345b1aafb27d05da8391a153318338 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sun, 5 May 2024 13:41:13 -0600 Subject: [PATCH 13/36] Define `Refund` model --- database/factories/RefundFactory.php | 49 ++++++++++++++++++ src/Models/Refund.php | 77 ++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 database/factories/RefundFactory.php create mode 100644 src/Models/Refund.php diff --git a/database/factories/RefundFactory.php b/database/factories/RefundFactory.php new file mode 100644 index 0000000..607e677 --- /dev/null +++ b/database/factories/RefundFactory.php @@ -0,0 +1,49 @@ + $this->faker->uuid(), + ]; + } + + /** + * Configure the model factory. + * + * @return $this + */ + public function configure() + { + return $this->afterMaking(function (Refund $refund) { + if (is_null($refund->payment_id)) { + $refund->payment_id = Payment::inRandomOrder()->firstOr( + fn () => Payment::factory()->create() + )->id; + } + + if (is_null($refund->amount)) { + $refund->amount = $refund->payment->amount; + } + }); + } +} diff --git a/src/Models/Refund.php b/src/Models/Refund.php new file mode 100644 index 0000000..435d94c --- /dev/null +++ b/src/Models/Refund.php @@ -0,0 +1,77 @@ + 'array', + ]; + + /** + * Custom factory namespace fallback. + * + * @return string + */ + protected static function getFactoryNamespace() + { + return 'Payavel\\Checkout\\Database\\Factories'; + } + + /** + * Get the payment that is being refunded. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function payment() + { + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); + } + + /** + * Get the refund's provider. + * + * @return \Payavel\Orchestration\Models\Provider + */ + public function getProviderAttribute() + { + return $this->payment->provider; + } + + /** + * Get the refund's account. + * + * @return \Payavel\Orchestration\Models\Account + */ + public function getAccountAttribute() + { + return $this->payment->account; + } +} From 343b6324205edd15973a17fef0bcb19a3bf84844 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sun, 5 May 2024 13:45:23 -0600 Subject: [PATCH 14/36] Define `Dispute` model --- database/factories/DisputeFactory.php | 49 +++++++++++++++++ src/Models/Dispute.php | 77 +++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 database/factories/DisputeFactory.php create mode 100644 src/Models/Dispute.php diff --git a/database/factories/DisputeFactory.php b/database/factories/DisputeFactory.php new file mode 100644 index 0000000..604c8aa --- /dev/null +++ b/database/factories/DisputeFactory.php @@ -0,0 +1,49 @@ + $this->faker->uuid(), + ]; + } + + /** + * Configure the model factory. + * + * @return $this + */ + public function configure() + { + return $this->afterMaking(function (Dispute $dispute) { + if (is_null($dispute->payment_id)) { + $dispute->payment_id = Payment::inRandomOrder()->firstOr( + fn () => Payment::factory()->create() + )->id; + } + + if (is_null($dispute->amount)) { + $dispute->amount = $dispute->payment->amount; + } + }); + } +} diff --git a/src/Models/Dispute.php b/src/Models/Dispute.php new file mode 100644 index 0000000..cbbaa5f --- /dev/null +++ b/src/Models/Dispute.php @@ -0,0 +1,77 @@ + 'array', + ]; + + /** + * Custom factory namespace fallback. + * + * @return string + */ + protected static function getFactoryNamespace() + { + return 'Payavel\\Checkout\\Database\\Factories'; + } + + /** + * Get the payment that is being refunded. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function payment() + { + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); + } + + /** + * Get the refund's provider. + * + * @return \Payavel\Orchestration\Models\Provider + */ + public function getProviderAttribute() + { + return $this->payment->provider; + } + + /** + * Get the refund's account. + * + * @return \Payavel\Orchestration\Models\Account + */ + public function getAccountAttribute() + { + return $this->payment->account; + } +} From 282bb390d9a96fb77205853b203f8b52f89b7eb2 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Mon, 6 May 2024 06:43:26 -0600 Subject: [PATCH 15/36] Adapt `TransactionEvent` model --- .../factories/TransactionEventFactory.php | 26 ++++++++++++------- src/Models/Dispute.php | 10 +++++++ src/Models/Refund.php | 10 +++++++ src/Models/TransactionEvent.php | 10 ++++++- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/database/factories/TransactionEventFactory.php b/database/factories/TransactionEventFactory.php index 6e71931..c968f61 100644 --- a/database/factories/TransactionEventFactory.php +++ b/database/factories/TransactionEventFactory.php @@ -6,6 +6,8 @@ use Payavel\Checkout\Models\Payment; use Payavel\Checkout\Models\TransactionEvent; use Payavel\Checkout\CheckoutStatus; +use Payavel\Checkout\Models\Dispute; +use Payavel\Checkout\Models\Refund; class TransactionEventFactory extends Factory { @@ -25,13 +27,6 @@ public function definition() { return [ 'reference' => $this->faker->uuid(), - 'status_code' => $this->faker->randomElement([ - CheckoutStatus::CAPTURED, - CheckoutStatus::SETTLED, - CheckoutStatus::VOIDED, - CheckoutStatus::REFUNDED, - CheckoutStatus::REFUND_SETTLED, - ]), ]; } @@ -44,13 +39,24 @@ public function configure() { return $this->afterMaking(function (TransactionEvent $transactionEvent) { if (is_null($transactionEvent->payment_id)) { - $payment = Payment::factory()->create(); + $transactionEvent->payment_id = Payment::factory()->create()->id; + } - $transactionEvent->payment_id = $payment->id; + if (is_null($transactionEvent->transactionable_id)) { + $transactionEvent->transactionable_id = $transactionEvent->payment_id; + $transactionEvent->transactionable_type = Payment::class; } if (is_null($transactionEvent->amount)) { - $transactionEvent->amount = $transactionEvent->transaction->amount; + $transactionEvent->amount = $transactionEvent->transactionable->amount; + } + + if (is_null($transactionEvent->status_code)) { + $transactionEvent->status_code = [ + Payment::class => CheckoutStatus::AUTHORIZED, + Refund::class => CheckoutStatus::REFUNDED, + Dispute::class => CheckoutStatus::CHARGEBACK, + ][$transactionEvent->transactionable_type]; } }); } diff --git a/src/Models/Dispute.php b/src/Models/Dispute.php index cbbaa5f..3a1cb7e 100644 --- a/src/Models/Dispute.php +++ b/src/Models/Dispute.php @@ -74,4 +74,14 @@ public function getAccountAttribute() { return $this->payment->account; } + + /** + * Get the transaction specific events. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function transactionEvents() + { + return $this->morphMany(ServiceConfig::get('checkout', 'models.' . TransactionEvent::class, TransactionEvent::class), 'transactionable'); + } } diff --git a/src/Models/Refund.php b/src/Models/Refund.php index 435d94c..104d03a 100644 --- a/src/Models/Refund.php +++ b/src/Models/Refund.php @@ -74,4 +74,14 @@ public function getAccountAttribute() { return $this->payment->account; } + + /** + * Get the transaction specific events. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphMany + */ + public function transactionEvents() + { + return $this->morphMany(ServiceConfig::get('checkout', 'models.' . TransactionEvent::class, TransactionEvent::class), 'transactionable'); + } } diff --git a/src/Models/TransactionEvent.php b/src/Models/TransactionEvent.php index a74f425..ca93308 100644 --- a/src/Models/TransactionEvent.php +++ b/src/Models/TransactionEvent.php @@ -55,5 +55,13 @@ public function payment() return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); } - // ToDo: Figure out the new TransactionEvent idea. + /** + * Get the event's originating transaction. + * + * @return \Illuminate\Database\Eloquent\Relations\MorphTo + */ + public function transactionable() + { + return $this->morphTo(); + } } From cc7c429f6384d3705eecf4295ca9971b13f07240 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Mon, 6 May 2024 08:17:39 -0600 Subject: [PATCH 16/36] Add new models to config-service.stub --- stubs/config-service.stub | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stubs/config-service.stub b/stubs/config-service.stub index 988d8b0..a6d275a 100644 --- a/stubs/config-service.stub +++ b/stubs/config-service.stub @@ -83,11 +83,14 @@ return [ | */ // 'models' => [ + // \Payavel\Checkout\Models\PaymentType::class => \App\Models\PaymentType::class, + // \Payavel\Checkout\Models\PaymentRail::class => \App\Models\PaymentRail::class, + // \Payavel\Checkout\Models\Wallet::class => \App\Models\Wallet::class, // \Payavel\Checkout\Models\PaymentInstrument::class => \App\Models\PaymentInstrument::class, // \Payavel\Checkout\Models\Payment::class => \App\Models\Payment::class, + // \Payavel\Checkout\Models\Refund::class => \App\Models\Refund::class, + // \Payavel\Checkout\Models\Dispute::class => \App\Models\Dispute::class, // \Payavel\Checkout\Models\TransactionEvent::class => \App\Models\TransactionEvent::class, - // \Payavel\Checkout\Models\PaymentType::class => \App\Models\PaymentType::class, - // \Payavel\Checkout\Models\Wallet::class => \App\Models\Wallet::class, // ], ]; From 6ba3802286e004779d93329a83be7a02164c3a96 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Mon, 6 May 2024 08:23:23 -0600 Subject: [PATCH 17/36] Add config-service-database.stub --- src/CheckoutServiceProvider.php | 1 + stubs/config-service-database.stub | 68 ++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 stubs/config-service-database.stub diff --git a/src/CheckoutServiceProvider.php b/src/CheckoutServiceProvider.php index 1b03d43..193516e 100644 --- a/src/CheckoutServiceProvider.php +++ b/src/CheckoutServiceProvider.php @@ -42,6 +42,7 @@ protected function registerPublishableAssets() $this->publishes([ __DIR__ . '/../stubs/config-service.stub' => base_path('stubs/orchestration/checkout/config-service.stub'), + __DIR__ . '/../stubs/config-service-database.stub' => base_path('stubs/orchestration/checkout/config-service-database.stub'), __DIR__ . '/../stubs/service-requester.stub' => base_path('stubs/orchestration/checkout/service-requester.stub'), __DIR__ . '/../stubs/service-responder.stub' => base_path('stubs/orchestration/checkout/service-responder.stub'), __DIR__ . '/../stubs/service-request.stub' => base_path('stubs/orchestration/checkout/service-request.stub'), diff --git a/stubs/config-service-database.stub b/stubs/config-service-database.stub new file mode 100644 index 0000000..aa6032b --- /dev/null +++ b/stubs/config-service-database.stub @@ -0,0 +1,68 @@ + 'Checkout', + + /* + |-------------------------------------------------------------------------- + | Checkout Defaults + |-------------------------------------------------------------------------- + | + | This option defines the default checkout service config + | for your application. You should define your checkout + | provider of choice along with your primary account. + | + */ + 'defaults' => [ + 'driver' => '{{ driver }}', + 'provider' => '{{ provider }}', + 'account' => '{{ account }}', + ], + + /* + |-------------------------------------------------------------------------- + | Checkout Test Mode + |-------------------------------------------------------------------------- + | + | When set to true, the provider & account will be shared with the fake checkout + | request so you can mock your responses as you wish. This is very useful for + | local & testing environments where a sandbox is limited or non-existent. + | + */ + 'test_mode' => env('CHECKOUT_TEST_MODE', false), + + /* + |-------------------------------------------------------------------------- + | Checkout Testing + |-------------------------------------------------------------------------- + | + | This option allows you to define the location of the fake checkout + | request & response classes you would like to leverage when test_mode + | is set to true. Also, feel free to add any other settings here. + | + */ + 'test_gateway' => \App\Services\Checkout\FakeCheckoutRequest::class, + + /* + |-------------------------------------------------------------------------- + | Checkout Models + |-------------------------------------------------------------------------- + | + | You may override the checkout package models by specifying a model from your + | application. The checkout package will automatically inject the overridden + | model in it's place, so be sure to have covered all of its functionality. + | + */ + // 'models' => [ + // \Payavel\Checkout\Models\PaymentType::class => \App\Models\PaymentType::class, + // \Payavel\Checkout\Models\PaymentRail::class => \App\Models\PaymentRail::class, + // \Payavel\Checkout\Models\Wallet::class => \App\Models\Wallet::class, + // \Payavel\Checkout\Models\PaymentInstrument::class => \App\Models\PaymentInstrument::class, + // \Payavel\Checkout\Models\Payment::class => \App\Models\Payment::class, + // \Payavel\Checkout\Models\Refund::class => \App\Models\Refund::class, + // \Payavel\Checkout\Models\Dispute::class => \App\Models\Dispute::class, + // \Payavel\Checkout\Models\TransactionEvent::class => \App\Models\TransactionEvent::class, + // ], + +]; From 693293d5c357346bda2b2c946b77e5a4431ec0bb Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Tue, 7 May 2024 06:06:36 -0600 Subject: [PATCH 18/36] Fix PaymentFactory --- database/factories/PaymentFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/factories/PaymentFactory.php b/database/factories/PaymentFactory.php index 0cd5200..57b206d 100644 --- a/database/factories/PaymentFactory.php +++ b/database/factories/PaymentFactory.php @@ -44,7 +44,7 @@ public function configure() ? $payment->instrument->provider : Provider::whereHas( 'accounts', - fn ($query) => $query->where('payment_accounts.id', $payment->account_id) + fn ($query) => $query->where('accounts.id', $payment->account_id) )->inRandomOrder()->firstOr( fn () => Provider::factory()->create() ); @@ -57,7 +57,7 @@ public function configure() ? $payment->instrument->account : Account::whereHas( 'providers', - fn ($query) => $query->where('payment_providers.id', $payment->provider_id) + fn ($query) => $query->where('providers.id', $payment->provider_id) )->inRandomOrder() ->firstOr(function () use ($payment) { $account = Account::factory()->create(); From 16d975396dacfb5a499eb3d7df32ae738e4bc70a Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Tue, 7 May 2024 06:12:49 -0600 Subject: [PATCH 19/36] Fix typo in migration --- .../2024_01_01_000010_create_base_checkout_tables.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php index 08c754b..e6737d9 100644 --- a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php +++ b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php @@ -138,7 +138,7 @@ public function down() Schema::dropIfExists('payments'); Schema::dropIfExists('payment_instruments'); Schema::dropIfExists('wallets'); - Schema::dropDatabaseIfExists('payment_rails'); + Schema::dropIfExists('payment_rails'); Schema::dropIfExists('payment_types'); } }; From 7b7cfb6fd2a148c9908e50083ac63288b0227312 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Tue, 7 May 2024 06:17:11 -0600 Subject: [PATCH 20/36] Update comments in Dispute --- src/Models/Dispute.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Models/Dispute.php b/src/Models/Dispute.php index 3a1cb7e..ca029ec 100644 --- a/src/Models/Dispute.php +++ b/src/Models/Dispute.php @@ -46,7 +46,7 @@ protected static function getFactoryNamespace() } /** - * Get the payment that is being refunded. + * Get the payment that is being disputed. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ @@ -56,7 +56,7 @@ public function payment() } /** - * Get the refund's provider. + * Get the dispute's provider. * * @return \Payavel\Orchestration\Models\Provider */ @@ -66,7 +66,7 @@ public function getProviderAttribute() } /** - * Get the refund's account. + * Get the dispute's account. * * @return \Payavel\Orchestration\Models\Account */ From 4dd6aa5e97f61e655458bf2cc14cf963612deeee Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Tue, 7 May 2024 06:34:12 -0600 Subject: [PATCH 21/36] Fix comment to make more sense --- src/Traits/ConfiguresCheckoutGateway.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Traits/ConfiguresCheckoutGateway.php b/src/Traits/ConfiguresCheckoutGateway.php index d3d1218..38c9c17 100644 --- a/src/Traits/ConfiguresCheckoutGateway.php +++ b/src/Traits/ConfiguresCheckoutGateway.php @@ -14,7 +14,7 @@ trait ConfiguresCheckoutGateway private $checkoutGateway; /** - * Retrieve the payment instrument's configured gateway. + * Retrieve the checkout model's pre-configured gateway. * * @return \Payavel\Checkout\CheckoutGateway */ From 5d1a75186a42dd7c2eefddf2316eac41ea86cd83 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 8 May 2024 09:22:35 -0600 Subject: [PATCH 22/36] Fix PaymentType model --- database/factories/PaymentTypeFactory.php | 4 ++-- src/Models/PaymentType.php | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/database/factories/PaymentTypeFactory.php b/database/factories/PaymentTypeFactory.php index 0d9bd97..53ce9cb 100644 --- a/database/factories/PaymentTypeFactory.php +++ b/database/factories/PaymentTypeFactory.php @@ -61,10 +61,10 @@ class PaymentTypeFactory extends Factory */ public function definition() { - $name = Str::ucfirst($this->faker->unique()->lexify('????')); + $name = Str::ucfirst($this->faker->unique()->lexify(Str::repeat('?', rand(4, 8)))); return [ - 'id' => preg_replace('/[^a-z0-9]+/i', '_', Str::lower($name)), + 'id' => preg_replace('/[^a-z]+/i', '_', Str::lower($name)), 'name' => $name, ]; } diff --git a/src/Models/PaymentType.php b/src/Models/PaymentType.php index 8b345fb..e242f50 100644 --- a/src/Models/PaymentType.php +++ b/src/Models/PaymentType.php @@ -10,6 +10,20 @@ class PaymentType extends Model { use HasFactory; + /** + * Indicates if the model's ID is auto-incrementing. + * + * @var bool + */ + public $incrementing = false; + + /** + * The attributes that aren't mass assignable. + * + * @var string[]|bool + */ + protected $guarded = []; + /** * Custom factory namespace fallback. * From 04452e754e191e98107b6d55fff21b1d8772377c Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 8 May 2024 09:22:51 -0600 Subject: [PATCH 23/36] Fix WalletFactory --- database/factories/WalletFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/factories/WalletFactory.php b/database/factories/WalletFactory.php index 6b77739..440dbcf 100644 --- a/database/factories/WalletFactory.php +++ b/database/factories/WalletFactory.php @@ -39,7 +39,7 @@ public function configure() if (is_null($wallet->provider_id)) { $provider = Provider::whereHas( 'accounts', - fn ($query) => $query->where('payment_accounts.id', $wallet->account_id) + fn ($query) => $query->where('accounts.id', $wallet->account_id) )->inRandomOrder() ->firstOr( fn () => Provider::factory()->create() @@ -51,7 +51,7 @@ public function configure() if (is_null($wallet->account_id)) { $account = Account::whereHas( 'providers', - fn ($query) => $query->where('payment_providers.id', $wallet->provider_id) + fn ($query) => $query->where('providers.id', $wallet->provider_id) )->inRandomOrder() ->firstOr(function () use ($wallet) { $account = Account::factory()->create(); From a3d60dcfb54985a29be21a50402f265bf43b48a9 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 8 May 2024 09:23:05 -0600 Subject: [PATCH 24/36] Fix PaymentRail model --- src/Models/PaymentRail.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Models/PaymentRail.php b/src/Models/PaymentRail.php index 9cd8444..e5e3257 100644 --- a/src/Models/PaymentRail.php +++ b/src/Models/PaymentRail.php @@ -10,6 +10,13 @@ class PaymentRail extends Model { use HasFactory; + /** + * Indicates if the model's ID is auto-incrementing. + * + * @var bool + */ + public $incrementing = false; + /** * The attributes that aren't mass assignable. * From e4ac344649dd9df74076d9a91346b6a852de4a73 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 8 May 2024 09:25:56 -0600 Subject: [PATCH 25/36] Fix Payment & Wallet factories --- database/factories/PaymentFactory.php | 4 ++-- database/factories/WalletFactory.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/database/factories/PaymentFactory.php b/database/factories/PaymentFactory.php index 57b206d..d934cd0 100644 --- a/database/factories/PaymentFactory.php +++ b/database/factories/PaymentFactory.php @@ -60,9 +60,9 @@ public function configure() fn ($query) => $query->where('providers.id', $payment->provider_id) )->inRandomOrder() ->firstOr(function () use ($payment) { - $account = Account::factory()->create(); + $account = Account::factory()->create(['default_provider_id' => $payment->provider_id]); - $account->providers()->attach($payment->provider_id, ['is_default' => true]); + $account->providers()->attach($payment->provider_id); return $account; }); diff --git a/database/factories/WalletFactory.php b/database/factories/WalletFactory.php index 440dbcf..c51f29b 100644 --- a/database/factories/WalletFactory.php +++ b/database/factories/WalletFactory.php @@ -54,9 +54,9 @@ public function configure() fn ($query) => $query->where('providers.id', $wallet->provider_id) )->inRandomOrder() ->firstOr(function () use ($wallet) { - $account = Account::factory()->create(); + $account = Account::factory()->create(['default_provider_id' => $wallet->provider_id]); - $account->providers()->attach($wallet->provider_id, ['is_default' => true]); + $account->providers()->attach($wallet->provider_id); return $account; }); From f7724b35ab055de76c5268416339059806ca880a Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 8 May 2024 09:27:39 -0600 Subject: [PATCH 26/36] Add PaymentTypeTest --- tests/Models/TestPaymentInstrument.php | 22 ++++++++++++ tests/Models/TestPaymentRail.php | 22 ++++++++++++ tests/Unit/Models/PaymentTypeTest.php | 47 ++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 tests/Models/TestPaymentInstrument.php create mode 100644 tests/Models/TestPaymentRail.php create mode 100644 tests/Unit/Models/PaymentTypeTest.php diff --git a/tests/Models/TestPaymentInstrument.php b/tests/Models/TestPaymentInstrument.php new file mode 100644 index 0000000..725ffa8 --- /dev/null +++ b/tests/Models/TestPaymentInstrument.php @@ -0,0 +1,22 @@ +create(); + $this->assertEmpty($paymentType->rails); + + $paymentTypeWith2Rails = PaymentType::factory()->hasRails(2)->create(); + $this->assertCount(2, $paymentTypeWith2Rails->rails); + $this->assertContainsOnlyInstancesOf(PaymentRail::class, $paymentTypeWith2Rails->rails); + + ServiceConfig::set('checkout', 'models.' . PaymentRail::class, TestPaymentRail::class); + $paymentTypeWith3OverriddenRails = PaymentType::factory()->hasRails(3)->create(); + $this->assertCount(3, $paymentTypeWith3OverriddenRails->rails); + $this->assertContainsOnlyInstancesOf(TestPaymentRail::class, $paymentTypeWith3OverriddenRails->rails); + } + + #[Test] + public function retrieve_payment_type_instruments() + { + $paymentType = PaymentType::factory()->create(); + $this->assertEmpty($paymentType->instruments); + + $paymentTypeWith2Instruments = PaymentType::factory()->hasInstruments(2)->create(); + $this->assertCount(2, $paymentTypeWith2Instruments->instruments); + $this->assertContainsOnlyInstancesOf(PaymentInstrument::class, $paymentTypeWith2Instruments->instruments); + + ServiceConfig::set('checkout', 'models.' . PaymentInstrument::class, TestPaymentInstrument::class); + $paymentTypeWith3OverriddenInstruments = PaymentType::factory()->hasInstruments(3)->create(); + $this->assertCount(3, $paymentTypeWith3OverriddenInstruments->instruments); + $this->assertContainsOnlyInstancesOf(TestPaymentInstrument::class, $paymentTypeWith3OverriddenInstruments->instruments); + } +} From 513e468385734b24d67bed66247ae29f3c9caa8e Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 8 May 2024 09:55:07 -0600 Subject: [PATCH 27/36] Add PaymentRailTest --- tests/Models/TestPayment.php | 22 +++++++++ tests/Models/TestPaymentType.php | 22 +++++++++ tests/Unit/Models/PaymentRailTest.php | 67 +++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 tests/Models/TestPayment.php create mode 100644 tests/Models/TestPaymentType.php create mode 100644 tests/Unit/Models/PaymentRailTest.php diff --git a/tests/Models/TestPayment.php b/tests/Models/TestPayment.php new file mode 100644 index 0000000..8928481 --- /dev/null +++ b/tests/Models/TestPayment.php @@ -0,0 +1,22 @@ +create(); + $paymentType = PaymentType::factory()->create(); + + $paymentRail = PaymentRail::create([ + 'parent_type_id' => $parentPaymentType->id, + 'type_id' => $paymentType->id, + ]); + + $this->assertEquals("{$parentPaymentType->id}:{$paymentType->id}", $paymentRail->id); + } + + #[Test] + public function retrieve_payment_rail_parent_type() + { + $paymentRail = PaymentRail::factory()->create(); + $this->assertInstanceOf(PaymentType::class, $paymentRail->parentType); + + ServiceConfig::set('checkout', 'models.' . PaymentType::class, TestPaymentType::class); + $paymentRailWithOverriddenParentType = PaymentRail::factory()->create(); + $this->assertInstanceOf(TestPaymentType::class, $paymentRailWithOverriddenParentType->parentType); + } + + #[Test] + public function retrieve_payment_rail_type() + { + $paymentRail = PaymentRail::factory()->create(); + $this->assertInstanceOf(PaymentType::class, $paymentRail->type); + + ServiceConfig::set('checkout', 'models.' . PaymentType::class, TestPaymentType::class); + $paymentRailWithOverriddenType = PaymentRail::factory()->create(); + $this->assertInstanceOf(TestPaymentType::class, $paymentRailWithOverriddenType->type); + } + + #[Test] + public function retrieve_payment_rail_payments() + { + $paymentRail = PaymentRail::factory()->create(); + $this->assertEmpty($paymentRail->payments); + + $paymentRailWith2Payments = PaymentRail::factory()->hasPayments(2)->create(); + $this->assertCount(2, $paymentRailWith2Payments->payments); + $this->assertContainsOnlyInstancesOf(Payment::class, $paymentRailWith2Payments->payments); + + ServiceConfig::set('checkout', 'models.' . Payment::class, TestPayment::class); + $paymentRailWith3OverriddenPayments = PaymentRail::factory()->hasPayments(3)->create(); + $this->assertCount(3, $paymentRailWith3OverriddenPayments->payments); + $this->assertContainsOnlyInstancesOf(TestPayment::class, $paymentRailWith3OverriddenPayments->payments); + } +} From e17ccace3c443f00f42770702c8742cb90dda094 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Wed, 8 May 2024 10:01:27 -0600 Subject: [PATCH 28/36] Add another payment rail id test case --- tests/Unit/Models/PaymentRailTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Unit/Models/PaymentRailTest.php b/tests/Unit/Models/PaymentRailTest.php index 9532b87..d90a971 100644 --- a/tests/Unit/Models/PaymentRailTest.php +++ b/tests/Unit/Models/PaymentRailTest.php @@ -27,6 +27,19 @@ public function payment_rail_generates_id_before_committing() $this->assertEquals("{$parentPaymentType->id}:{$paymentType->id}", $paymentRail->id); } + #[Test] + public function payment_rail_generates_the_same_id_before_committing_when_parent_type_is_equal_to_type() + { + $paymentType = PaymentType::factory()->create(); + + $paymentRail = PaymentRail::create([ + 'parent_type_id' => $paymentType->id, + 'type_id' => $paymentType->id, + ]); + + $this->assertEquals($paymentType->id, $paymentRail->id); + } + #[Test] public function retrieve_payment_rail_parent_type() { From 5c93e66ed6b8ca69e17f0b02d1f1da6398a007ef Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Fri, 10 May 2024 09:01:19 -0600 Subject: [PATCH 29/36] Add WalletTest --- tests/Models/TestAccount.php | 22 ++++++++++ tests/Models/TestProvider.php | 22 ++++++++++ tests/Unit/Models/WalletTest.php | 69 ++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 tests/Models/TestAccount.php create mode 100644 tests/Models/TestProvider.php create mode 100644 tests/Unit/Models/WalletTest.php diff --git a/tests/Models/TestAccount.php b/tests/Models/TestAccount.php new file mode 100644 index 0000000..89433c1 --- /dev/null +++ b/tests/Models/TestAccount.php @@ -0,0 +1,22 @@ +create(); + $this->assertNull($wallet->billable); + + $billable = User::factory()->create(); + $walletWithBillable = Wallet::factory()->create(); + $walletWithBillable->billable()->associate($billable); + $this->assertInstanceOf(Billable::class, $walletWithBillable->billable); + } + + #[Test] + public function retrieve_wallet_provider() + { + $walletWithProvider = Wallet::factory()->create(); + $this->assertInstanceOf(Provider::class, $walletWithProvider->provider); + + ServiceConfig::set('checkout', 'models.' . Provider::class, TestProvider::class); + $walletWithOverriddenProvider = Wallet::factory()->create(); + $this->assertInstanceOF(TestProvider::class, $walletWithOverriddenProvider->provider); + } + + #[Test] + public function retrieve_wallet_account() + { + $walletWithAccount = Wallet::factory()->create(); + $this->assertInstanceOf(Account::class, $walletWithAccount->account); + + ServiceConfig::set('checkout', 'models.' . Account::class, TestAccount::class); + $walletWithOverriddenAccount = Wallet::factory()->create(); + $this->assertInstanceOF(TestAccount::class, $walletWithOverriddenAccount->account); + } + + #[Test] + public function retrieve_wallet_payment_instruments() + { + $wallet = Wallet::factory()->create(); + $this->assertEmpty($wallet->paymentInstruments); + + $walletWith2PaymentInstruments = Wallet::factory()->hasPaymentInstruments(2)->create(); + $this->assertCount(2, $walletWith2PaymentInstruments->paymentInstruments); + $this->assertContainsOnlyInstancesOf(PaymentInstrument::class, $walletWith2PaymentInstruments->paymentInstruments); + + ServiceConfig::set('checkout', 'models.' . PaymentInstrument::class, TestPaymentInstrument::class); + $walletWith3OverriddenPaymentInstruments = Wallet::factory()->hasPaymentInstruments(3)->create(); + $this->assertCount(3, $walletWith3OverriddenPaymentInstruments->paymentInstruments); + $this->assertContainsOnlyInstancesOf(TestPaymentInstrument::class, $walletWith3OverriddenPaymentInstruments->paymentInstruments); + } +} From 708695fee2075f068350182729599b1e4eb4b4c3 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Fri, 10 May 2024 23:36:18 -0600 Subject: [PATCH 30/36] Add PaymentInstrumentTest --- src/Models/PaymentInstrument.php | 2 +- tests/Models/TestWallet.php | 22 ++++++ tests/Unit/Models/PaymentInstrumentTest.php | 79 +++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tests/Models/TestWallet.php create mode 100644 tests/Unit/Models/PaymentInstrumentTest.php diff --git a/src/Models/PaymentInstrument.php b/src/Models/PaymentInstrument.php index 12fb25a..6fb95e8 100644 --- a/src/Models/PaymentInstrument.php +++ b/src/Models/PaymentInstrument.php @@ -95,7 +95,7 @@ public function type() */ public function payments() { - return $this->hasMany(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); + return $this->hasMany(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class), 'instrument_id'); } /** diff --git a/tests/Models/TestWallet.php b/tests/Models/TestWallet.php new file mode 100644 index 0000000..be7467c --- /dev/null +++ b/tests/Models/TestWallet.php @@ -0,0 +1,22 @@ +create(); + $this->assertInstanceOf(Provider::class, $paymentInstrumentWithProviderViaWallet->provider); + + ServiceConfig::set('checkout', 'models.' . Wallet::class, TestWallet::class); + $paymentInstrumentWithProviderViaOverriddenWallet = PaymentInstrument::factory()->create(); + $this->assertInstanceOf(Provider::class, $paymentInstrumentWithProviderViaOverriddenWallet->provider); + } + + #[Test] + public function retrieve_payment_instrument_account() + { + $paymentInstrumentWithAccountViaWallet = PaymentInstrument::factory()->create(); + $this->assertInstanceOf(Account::class, $paymentInstrumentWithAccountViaWallet->account); + + ServiceConfig::set('checkout', 'models.' . Wallet::class, TestWallet::class); + $paymentInstrumentWithAccountViaOverriddenWallet = PaymentInstrument::factory()->create(); + $this->assertInstanceOf(Account::class, $paymentInstrumentWithAccountViaOverriddenWallet->account); + } + + #[Test] + public function retrieve_payment_instrument_wallet() + { + $paymentInstrumentWithWallet = PaymentInstrument::factory()->create(); + $this->assertInstanceOf(Wallet::class, $paymentInstrumentWithWallet->wallet); + + ServiceConfig::set('checkout', 'models.' . Wallet::class, TestWallet::class); + $paymentInstrumentWithOverriddenWallet = PaymentInstrument::factory()->create(); + $this->assertInstanceOf(TestWallet::class, $paymentInstrumentWithOverriddenWallet->wallet); + } + + #[Test] + public function retrieve_payment_instrument_type() + { + $paymentInstrumentWithType = PaymentInstrument::factory()->create(); + $this->assertInstanceOf(PaymentType::class, $paymentInstrumentWithType->type); + + ServiceConfig::set('checkout', 'models.' . PaymentType::class, TestPaymentType::class); + $paymentInstrumentWithOverriddenType = PaymentInstrument::factory()->create(); + $this->assertInstanceOf(TestPaymentType::class, $paymentInstrumentWithOverriddenType->type); + } + + #[Test] + public function retrieve_payment_instrument_payments() + { + $paymentInstrument = PaymentInstrument::factory()->create(); + $this->assertEmpty($paymentInstrument->payments); + + $paymentInstrumentWith2Payments = PaymentInstrument::factory()->hasPayments(2)->create(); + $this->assertCount(2, $paymentInstrumentWith2Payments->payments); + $this->assertContainsOnlyInstancesOf(Payment::class, $paymentInstrumentWith2Payments->payments); + + ServiceConfig::set('checkout', 'models.' . Payment::class, TestPayment::class); + $paymentInstrumentWith3OverriddenPayments = PaymentInstrument::factory()->hasPayments(3)->create(); + $this->assertCount(3, $paymentInstrumentWith3OverriddenPayments->payments); + $this->assertContainsOnlyInstancesOf(TestPayment::class, $paymentInstrumentWith3OverriddenPayments->payments); + } +} From dd9d1a00347698acb0e801db17c7e4306fa97114 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Fri, 10 May 2024 23:51:35 -0600 Subject: [PATCH 31/36] Rename model tests --- ...ymentInstrumentTest.php => PaymentInstrumentModelTest.php} | 4 ++-- .../{Models/PaymentRailTest.php => PaymentRailModelTest.php} | 4 ++-- .../{Models/PaymentTypeTest.php => PaymentTypeModelTest.php} | 4 ++-- tests/Unit/{Models/WalletTest.php => WalletModelTest.php} | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) rename tests/Unit/{Models/PaymentInstrumentTest.php => PaymentInstrumentModelTest.php} (97%) rename tests/Unit/{Models/PaymentRailTest.php => PaymentRailModelTest.php} (97%) rename tests/Unit/{Models/PaymentTypeTest.php => PaymentTypeModelTest.php} (96%) rename tests/Unit/{Models/WalletTest.php => WalletModelTest.php} (97%) diff --git a/tests/Unit/Models/PaymentInstrumentTest.php b/tests/Unit/PaymentInstrumentModelTest.php similarity index 97% rename from tests/Unit/Models/PaymentInstrumentTest.php rename to tests/Unit/PaymentInstrumentModelTest.php index 663314a..96a7a45 100644 --- a/tests/Unit/Models/PaymentInstrumentTest.php +++ b/tests/Unit/PaymentInstrumentModelTest.php @@ -1,6 +1,6 @@ Date: Sat, 11 May 2024 00:23:28 -0600 Subject: [PATCH 32/36] Add PaymentModelTest --- tests/Models/TestTransactionEvent.php | 22 ++++++ tests/Unit/PaymentModelTest.php | 100 ++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 tests/Models/TestTransactionEvent.php create mode 100644 tests/Unit/PaymentModelTest.php diff --git a/tests/Models/TestTransactionEvent.php b/tests/Models/TestTransactionEvent.php new file mode 100644 index 0000000..911bb4f --- /dev/null +++ b/tests/Models/TestTransactionEvent.php @@ -0,0 +1,22 @@ +create(); + $this->assertInstanceOf(Provider::class, $paymentWithProvider->provider); + + ServiceConfig::set('checkout', 'models.' . Provider::class, TestProvider::class); + $paymentWithOverriddenProvider = Payment::factory()->create(); + $this->assertInstanceOf(TestProvider::class, $paymentWithOverriddenProvider->provider); + } + + #[Test] + public function retrieve_payment_account() + { + $paymentWithAccount = Payment::factory()->create(); + $this->assertInstanceOf(Account::class, $paymentWithAccount->account); + + ServiceConfig::set('checkout', 'models.' . Account::class, TestAccount::class); + $paymentWithOverriddenAccount = Payment::factory()->create(); + $this->assertInstanceOf(TestAccount::class, $paymentWithOverriddenAccount->account); + } + + #[Test] + public function retrieve_payment_rail() + { + $paymentWithRail = Payment::factory()->create(); + $this->assertInstanceOf(PaymentRail::class, $paymentWithRail->rail); + + ServiceConfig::set('checkout', 'models.' . PaymentRail::class, TestPaymentRail::class); + $paymentWithOverriddenRail = Payment::factory()->create(); + $this->assertInstanceOf(TestPaymentRail::class, $paymentWithOverriddenRail->rail); + } + + #[Test] + public function retrieve_payment_instrument() + { + $payment = Payment::factory()->create(); + $this->assertNull($payment->instrument); + + $paymentWithInstrument = Payment::factory()->forInstrument()->create(); + $this->assertInstanceOf(PaymentInstrument::class, $paymentWithInstrument->instrument); + + ServiceConfig::set('checkout', 'models.' . PaymentInstrument::class, TestPaymentInstrument::class); + $paymentWithOverriddenInstrument = Payment::factory()->forInstrument()->create(); + $this->assertInstanceOf(TestPaymentInstrument::class, $paymentWithOverriddenInstrument->instrument); + } + + #[Test] + public function retrieve_payment_events() + { + $payment = Payment::factory()->create(); + $this->assertEmpty($payment->events); + + $paymentWith2Events = Payment::factory()->hasEvents(2)->create(); + $this->assertCount(2, $paymentWith2Events->events); + $this->assertContainsOnlyInstancesOf(TransactionEvent::class, $paymentWith2Events->events); + + ServiceConfig::set('checkout', 'models.' . TransactionEvent::class, TestTransactionEvent::class); + $paymentWith3OverriddenEvents = Payment::factory()->hasEvents(3)->create(); + $this->assertCount(3, $paymentWith3OverriddenEvents->events); + $this->assertContainsOnlyInstancesOf(TestTransactionEvent::class, $paymentWith3OverriddenEvents->events); + } + + #[Test] + public function retrieve_payment_transaction_events() + { + $payment = Payment::factory()->create(); + $this->assertEmpty($payment->transactionEvents); + + $paymentWith2TransactionEvents = Payment::factory()->hasTransactionEvents(2)->create(); + $this->assertCount(2, $paymentWith2TransactionEvents->transactionEvents); + $this->assertContainsOnlyInstancesOf(TransactionEvent::class, $paymentWith2TransactionEvents->transactionEvents); + + ServiceConfig::set('checkout', 'models.' . TransactionEvent::class, TestTransactionEvent::class); + $paymentWith3OverriddenTransactionEvents = Payment::factory()->hasTransactionEvents(3)->create(); + $this->assertCount(3, $paymentWith3OverriddenTransactionEvents->transactionEvents); + $this->assertContainsOnlyInstancesOf(TestTransactionEvent::class, $paymentWith3OverriddenTransactionEvents->transactionEvents); + } +} From 1560b963ff132a65fafb1760bd5fbdb7b295b863 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sat, 11 May 2024 00:47:00 -0600 Subject: [PATCH 33/36] Add RefundModelTest --- src/Models/Refund.php | 20 +++++----- tests/Unit/RefundModelTest.php | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 tests/Unit/RefundModelTest.php diff --git a/src/Models/Refund.php b/src/Models/Refund.php index 104d03a..9c67a14 100644 --- a/src/Models/Refund.php +++ b/src/Models/Refund.php @@ -45,16 +45,6 @@ protected static function getFactoryNamespace() return 'Payavel\\Checkout\\Database\\Factories'; } - /** - * Get the payment that is being refunded. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function payment() - { - return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); - } - /** * Get the refund's provider. * @@ -75,6 +65,16 @@ public function getAccountAttribute() return $this->payment->account; } + /** + * Get the payment that is being refunded. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function payment() + { + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); + } + /** * Get the transaction specific events. * diff --git a/tests/Unit/RefundModelTest.php b/tests/Unit/RefundModelTest.php new file mode 100644 index 0000000..6cf03de --- /dev/null +++ b/tests/Unit/RefundModelTest.php @@ -0,0 +1,68 @@ +create(); + $this->assertInstanceOf(Provider::class, $refundWithProvider->provider); + + ServiceConfig::set('checkout', 'models.' . Provider::class, TestProvider::class); + $refundWithOverriddenProvider = Refund::factory()->create(); + $this->assertInstanceOf(TestProvider::class, $refundWithOverriddenProvider->provider); + } + + #[Test] + public function retrieve_refund_account() + { + $refundWithAccount = Refund::factory()->create(); + $this->assertInstanceOf(Account::class, $refundWithAccount->account); + + ServiceConfig::set('checkout', 'models.' . Account::class, TestAccount::class); + $refundWithOverriddenAccount = Refund::factory()->create(); + $this->assertInstanceOf(TestAccount::class, $refundWithOverriddenAccount->account); + } + + #[Test] + public function retrieve_refund_payment() + { + $refundWithPayment = Refund::factory()->create(); + $this->assertInstanceOf(Payment::class, $refundWithPayment->payment); + + ServiceConfig::set('checkout', 'models.' . Payment::class, TestPayment::class); + $refundWithOverriddenPayment = Refund::factory()->create(); + $this->assertInstanceOf(TestPayment::class, $refundWithOverriddenPayment->payment); + } + + #[Test] + public function retrieve_refund_transaction_events() + { + $refund = Refund::factory()->create(); + $this->assertEmpty($refund->transactionEvents); + + $refundWith2TransactionEvents = Refund::factory()->hasTransactionEvents(2)->create(); + $this->assertCount(2, $refundWith2TransactionEvents->transactionEvents); + $this->assertContainsOnlyInstancesOf(TransactionEvent::class, $refundWith2TransactionEvents->transactionEvents); + + ServiceConfig::set('checkout', 'models.' . TransactionEvent::class, TestTransactionEvent::class); + $refundWith3OverriddenTransactionEvents = Refund::factory()->hasTransactionEvents(3)->create(); + $this->assertCount(3, $refundWith3OverriddenTransactionEvents->transactionEvents); + $this->assertContainsOnlyInstancesOf(TestTransactionEvent::class, $refundWith3OverriddenTransactionEvents->transactionEvents); + } +} From 38f9a345bd8df4810ca3438cc43a971d04ed8ddd Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Sat, 11 May 2024 07:51:17 -0600 Subject: [PATCH 34/36] Add DisputeModelTest --- src/Models/Dispute.php | 20 +++++----- tests/Unit/DisputeModelTest.php | 68 +++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 tests/Unit/DisputeModelTest.php diff --git a/src/Models/Dispute.php b/src/Models/Dispute.php index ca029ec..ffd3b05 100644 --- a/src/Models/Dispute.php +++ b/src/Models/Dispute.php @@ -45,16 +45,6 @@ protected static function getFactoryNamespace() return 'Payavel\\Checkout\\Database\\Factories'; } - /** - * Get the payment that is being disputed. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function payment() - { - return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); - } - /** * Get the dispute's provider. * @@ -75,6 +65,16 @@ public function getAccountAttribute() return $this->payment->account; } + /** + * Get the payment that is being disputed. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function payment() + { + return $this->belongsTo(ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class)); + } + /** * Get the transaction specific events. * diff --git a/tests/Unit/DisputeModelTest.php b/tests/Unit/DisputeModelTest.php new file mode 100644 index 0000000..501d0fb --- /dev/null +++ b/tests/Unit/DisputeModelTest.php @@ -0,0 +1,68 @@ +create(); + $this->assertInstanceOf(Provider::class, $disputeWithProvider->provider); + + ServiceConfig::set('checkout', 'models.' . Provider::class, TestProvider::class); + $disputeWithOverriddenProvider = Dispute::factory()->create(); + $this->assertInstanceOf(TestProvider::class, $disputeWithOverriddenProvider->provider); + } + + #[Test] + public function retrieve_dispute_account() + { + $disputeWithAccount = Dispute::factory()->create(); + $this->assertInstanceOf(Account::class, $disputeWithAccount->account); + + ServiceConfig::set('checkout', 'models.' . Account::class, TestAccount::class); + $disputeWithOverriddenAccount = Dispute::factory()->create(); + $this->assertInstanceOf(TestAccount::class, $disputeWithOverriddenAccount->account); + } + + #[Test] + public function retrieve_dispute_payment() + { + $disputeWithPayment = Dispute::factory()->create(); + $this->assertInstanceOf(Payment::class, $disputeWithPayment->payment); + + ServiceConfig::set('checkout', 'models.' . Payment::class, TestPayment::class); + $disputeWithOverriddenPayment = Dispute::factory()->create(); + $this->assertInstanceOf(TestPayment::class, $disputeWithOverriddenPayment->payment); + } + + #[Test] + public function retrieve_dispute_transaction_events() + { + $dispute = Dispute::factory()->create(); + $this->assertEmpty($dispute->transactionEvents); + + $disputeWith2TransactionEvents = Dispute::factory()->hasTransactionEvents(2)->create(); + $this->assertCount(2, $disputeWith2TransactionEvents->transactionEvents); + $this->assertContainsOnlyInstancesOf(TransactionEvent::class, $disputeWith2TransactionEvents->transactionEvents); + + ServiceConfig::set('checkout', 'models.' . TransactionEvent::class, TestTransactionEvent::class); + $disputeWith3OverriddenTransactionEvents = Dispute::factory()->hasTransactionEvents(3)->create(); + $this->assertCount(3, $disputeWith3OverriddenTransactionEvents->transactionEvents); + $this->assertContainsOnlyInstancesOf(TestTransactionEvent::class, $disputeWith3OverriddenTransactionEvents->transactionEvents); + } +} From 9f87a35f912714e5220a1d037339405fefdc05f0 Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Thu, 16 May 2024 05:51:01 -0600 Subject: [PATCH 35/36] Add TransactionEventModelTest --- .../factories/TransactionEventFactory.php | 21 ++++---- ..._01_000010_create_base_checkout_tables.php | 2 +- src/CheckoutServiceProvider.php | 11 ++++ tests/Models/TestDispute.php | 22 ++++++++ tests/Models/TestRefund.php | 23 +++++++++ tests/Unit/TransactionEventModelTest.php | 50 +++++++++++++++++++ 6 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 tests/Models/TestDispute.php create mode 100644 tests/Models/TestRefund.php create mode 100644 tests/Unit/TransactionEventModelTest.php diff --git a/database/factories/TransactionEventFactory.php b/database/factories/TransactionEventFactory.php index c968f61..a4e2ad2 100644 --- a/database/factories/TransactionEventFactory.php +++ b/database/factories/TransactionEventFactory.php @@ -8,6 +8,7 @@ use Payavel\Checkout\CheckoutStatus; use Payavel\Checkout\Models\Dispute; use Payavel\Checkout\Models\Refund; +use Payavel\Orchestration\Support\ServiceConfig; class TransactionEventFactory extends Factory { @@ -37,26 +38,26 @@ public function definition() */ public function configure() { + $this->model = ServiceConfig::get('checkout', 'models.' . $this->model, $this->model); + return $this->afterMaking(function (TransactionEvent $transactionEvent) { if (is_null($transactionEvent->payment_id)) { $transactionEvent->payment_id = Payment::factory()->create()->id; } - if (is_null($transactionEvent->transactionable_id)) { - $transactionEvent->transactionable_id = $transactionEvent->payment_id; - $transactionEvent->transactionable_type = Payment::class; - } - if (is_null($transactionEvent->amount)) { - $transactionEvent->amount = $transactionEvent->transactionable->amount; + $transactionEvent->amount = $transactionEvent->transactionable->amount ?? $transactionEvent->payment->amount; } if (is_null($transactionEvent->status_code)) { $transactionEvent->status_code = [ - Payment::class => CheckoutStatus::AUTHORIZED, - Refund::class => CheckoutStatus::REFUNDED, - Dispute::class => CheckoutStatus::CHARGEBACK, - ][$transactionEvent->transactionable_type]; + ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class) => CheckoutStatus::AUTHORIZED, + ServiceConfig::get('checkout', 'models.' . Refund::class, Refund::class) => CheckoutStatus::REFUNDED, + ServiceConfig::get('checkout', 'models.' . Dispute::class, Dispute::class) => CheckoutStatus::CHARGEBACK, + ][ + ServiceConfig::get('checkout', 'models.' . $transactionEvent->transactionable_type, $transactionEvent->transactionable_type) ?? + ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class) + ]; } }); } diff --git a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php index e6737d9..f1b5088 100644 --- a/database/migrations/2024_01_01_000010_create_base_checkout_tables.php +++ b/database/migrations/2024_01_01_000010_create_base_checkout_tables.php @@ -112,7 +112,7 @@ public function up() Schema::create('transaction_events', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('payment_id'); - $table->morphs('transactionable'); + $table->nullableMorphs('transactionable'); $table->string('reference'); $table->unsignedInteger('status_code'); $table->unsignedInteger('amount'); diff --git a/src/CheckoutServiceProvider.php b/src/CheckoutServiceProvider.php index 193516e..9daa762 100644 --- a/src/CheckoutServiceProvider.php +++ b/src/CheckoutServiceProvider.php @@ -2,9 +2,14 @@ namespace Payavel\Checkout; +use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\ServiceProvider; use Payavel\Checkout\Console\Commands\CheckoutInstall; use Payavel\Checkout\Console\Commands\CheckoutProvider; +use Payavel\Checkout\Models\Dispute; +use Payavel\Checkout\Models\Payment; +use Payavel\Checkout\Models\Refund; +use Payavel\Orchestration\Support\ServiceConfig; class CheckoutServiceProvider extends ServiceProvider { @@ -19,6 +24,12 @@ public function boot() $this->registerCommands(); $this->registerMigrations(); + + Relation::morphMap([ + Payment::class => fn () => ServiceConfig::get('checkout', 'models.' . Payment::class, Payment::class), + Refund::class => fn () => ServiceConfig::get('checkout', 'models.' . Refund::class, Refund::class), + Dispute::class => fn () => ServiceConfig::get('checkout', 'models.' . Dispute::class, Dispute::class), + ]); } public function register() diff --git a/tests/Models/TestDispute.php b/tests/Models/TestDispute.php new file mode 100644 index 0000000..c16fd5f --- /dev/null +++ b/tests/Models/TestDispute.php @@ -0,0 +1,22 @@ +create(); + $this->assertInstanceOf(Payment::class, $transactionEventWithPayment->payment); + + ServiceConfig::set('checkout', 'models.' . Payment::class, TestPayment::class); + $transactionEventWithOverriddenPayment = TransactionEvent::factory()->create(); + $this->assertInstanceOf(TestPayment::class, $transactionEventWithOverriddenPayment->payment); + } + + #[Test] + public function retrieve_transaction_event_transactionable() + { + $transactionEvent = TransactionEvent::factory()->create(); + $this->assertNull($transactionEvent->transactionable); + + $transactionables = [ + Payment::class => TestPayment::class, + Refund::class => TestRefund::class, + Dispute::class => TestDispute::class, + ]; + + $randomTransactionable = $this->faker->randomElement(array_keys($transactionables)); + $transactionEventWithTransactionable = TransactionEvent::factory()->for($randomTransactionable::factory(), 'transactionable')->create(); + $this->assertInstanceOf($randomTransactionable, $transactionEventWithTransactionable->transactionable); + + $randomTransactionable = $this->faker->randomElement(array_keys($transactionables)); + ServiceConfig::set('checkout', 'models.' . $randomTransactionable, $transactionables[$randomTransactionable]); + $transactionEventWithOverriddenTransactionable = TransactionEvent::factory()->for($transactionables[$randomTransactionable]::factory(), 'transactionable')->create(); + $this->assertInstanceOf($transactionables[$randomTransactionable], $transactionEventWithOverriddenTransactionable->transactionable); + } +} From cb6c34ef2170ff1ffe91fa92ce844ccf9cea17de Mon Sep 17 00:00:00 2001 From: Robert Kujawa Date: Thu, 16 May 2024 06:02:40 -0600 Subject: [PATCH 36/36] getActualClassNameForMorph --- src/Models/TransactionEvent.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Models/TransactionEvent.php b/src/Models/TransactionEvent.php index ca93308..fafbe07 100644 --- a/src/Models/TransactionEvent.php +++ b/src/Models/TransactionEvent.php @@ -3,6 +3,8 @@ namespace Payavel\Checkout\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Support\Arr; use Payavel\Orchestration\Support\ServiceConfig; use Payavel\Orchestration\Traits\HasFactory; @@ -64,4 +66,21 @@ public function transactionable() { return $this->morphTo(); } + + /** + * Retrieve the actual class name for a given morph class. + * + * @param string $class + * @return string + */ + public static function getActualClassNameForMorph($class) + { + $value = Arr::get(Relation::morphMap() ?: [], $class, $class); + + if (is_callable($value)) { + return $value(); + } + + return $value; + } }