diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..acb4a5e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Easily store payments and handle payment gateways in Laravel + +This package provides traits and interfaces that will let you easily create and store payments, as well as provide you with a streamlined interface to interact with payment gateways. + +--- + +Oops! Looks like we haven't added anything here yet. \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..acb4a5e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,7 @@ +# Easily store payments and handle payment gateways in Laravel + +This package provides traits and interfaces that will let you easily create and store payments, as well as provide you with a streamlined interface to interact with payment gateways. + +--- + +Oops! Looks like we haven't added anything here yet. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d37f343 --- /dev/null +++ b/README.md @@ -0,0 +1,182 @@ +# Easily store payments and handle payment gateways in Laravel + +This package provides traits and interfaces that will let you easily create and store payments, as well as provide you with a streamlined interface to interact with payment gateways. + +--- + +## Installation + +You can install the package via composer: +``` bash +composer require litvinjuan/laravel-payments +``` + +If you are using a `Laravel version below 5.5`, you need to add the following to your `config/app.php` file: +```php +'providers' => [ + litvinjuan\LaravelPayments\LaravelPaymentsServiceProvider::class, +] +``` + +Next, you need to publish the config and migration files. Run the following command in your project's root: +``` bash +php artisan vendor:publish --provider="litvinjuan\LaravelPayments\LaravelPaymentsServiceProvider" +``` + +Last, run the migrations so that your payments table is created: +``` bash +php artisan migrate +``` + + +## Usage + +You will have to create a Model that implements the `Payable` interface and the `HasPayment` trait. This is the model your users will be paying for (ej. Order, Product). + +The `Payable` interface has 3 methods you'll need to implement yourself: `getPayablePrice()` should return the total price that should be paid, `getPayableDescription()` should return the payment description that should be used in the bank statement and for future reference, `payer()` should return a reference to whoever should make the payment. + +Here's an example: +```php +total; + } + + public function getPayableDescription(): string + { + return 'This is a dummy bank statement'; + } + + public function payer(): Payer + { + return $this->buyer; + } +} +``` + +--- + +You will also need to create a Model that implements the `Payer` interface and the `CanPay` trait. This is the model that represents whoever will be paying (tip: this is generally your User model). + +The `Payer` interface has 1 method you'll need to implement yourself: `getPayerEmail()` should return the payer's email address. + +Here's an example: +```php +email; + } +} + +``` + +Whenever you need to make a purchase, create your Payable model as you normally would. +```php +$order = new Order(); +$order->total = new Money(2900, 'USD'); +$order->save(); +``` + +Once you have your Payable instance, you can call the `createPayment` method. +```php +$payment = order->createPayment(); +``` + +To interact with gateways, you first need to get a Gateway instance: +```php +$gateway = GatewayFactory::make($payment); +``` +This will return a Gateway instance based on the payment's gateway_name attribute. + +Then we can check that the gateway supports the call we are trying to make: +```php +if (! $gateway->supportsPurchase()) { + throw InvalidRequestException::notSupported(); +} + +if (! $gateway->supportsRefund()) { + throw InvalidRequestException::notSupported(); +} + +// ... +// See full list of calls below +``` + +The following 10 calls are currently supported: +```php +* Authorize // Authorize an amount on the customer's card +* CompleteAuthorize // Handle return from off-site authorization +* Capture // Capture a previously authorized amount +* Purchase // Automatically authorize and purchase an amount on the customer's card +* CompletePurchase // Handle return from off-site authorization +* GetPayment // Get information about a specific payment +* PaymentNotification // Process a received payment notification +* Refund // Refund a previously charged amount to the customer's card +* Void // Void a payment +* ValidatePayment // Validates whether a payment was successful or not +``` +**Note:** It is recommended that you use the `ValidatePayment` call before approving your customer's purchase. + +**Note:** Individual gateways might not support every call, and thus you should always check the corresponding supports() method. + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. + +## Security + +If you discover any security related issues, please email litvinjuan@gmail.com instead of using the issue tracker. + +## Credits + +- [Juan Litvin](https://juanlitvin.com) + +## Support us + +Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource). + +Does your business depend on our contributions? Reach out and support us on [Patreon](https://www.patreon.com/spatie). +All pledges will be dedicated to allocating workforce on maintenance and new awesome stuff. + +## License + +The MIT License (MIT). Please see the [License File](LICENSE.md) for more information. \ No newline at end of file diff --git a/src/Handlers/ValidatePaymentPaymentHandler.php b/src/Handlers/ValidatePaymentPaymentHandler.php deleted file mode 100644 index 6310b5a..0000000 --- a/src/Handlers/ValidatePaymentPaymentHandler.php +++ /dev/null @@ -1,48 +0,0 @@ -state->is(PaymentState::PURCHASED)) { - return false; - } - - if (! $payment->paid) { - return false; - } - - if (! $payment->paid->equals($payment->price)) { - return false; - } - - // Create Gateway from Factory - $gateway = GatewayFactory::make($payment); - - // Verify the gateway supports this method - if (! $gateway->supportsValidatePayment()) { - throw InvalidRequestException::notSupported(); - } - - // Create and send the request - $response = $gateway->validatePayment()->payment($payment)->send(); - - return $response->validated(); - } - -} diff --git a/src/Payments/Payment.php b/src/Payments/Payment.php index ab9c42f..df9d850 100644 --- a/src/Payments/Payment.php +++ b/src/Payments/Payment.php @@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\SoftDeletes; use Konekt\Enum\Eloquent\CastsEnums; -use litvinjuan\LaravelPayments\Handlers\ValidatePaymentPaymentHandler; use Money\Money; /** @@ -96,18 +95,6 @@ public function setGateway(string $gateway) $this->save(); } - /** - * @return bool - */ - public function validate() - { - try { - return (new ValidatePaymentPaymentHandler())->handle($this); - } catch (Exception $e) { - return false; - } - } - /** * @param $key * @param $value diff --git a/src/Requests/AbstractValidatePaymentRequest.php b/src/Requests/AbstractValidatePaymentRequest.php index af863a6..437670a 100644 --- a/src/Requests/AbstractValidatePaymentRequest.php +++ b/src/Requests/AbstractValidatePaymentRequest.php @@ -5,6 +5,7 @@ use Exception; use litvinjuan\LaravelPayments\Exceptions\InvalidRequestException; use litvinjuan\LaravelPayments\Payments\Payment; +use litvinjuan\LaravelPayments\Payments\PaymentState; use litvinjuan\LaravelPayments\Responses\AbstractValidatePaymentResponse; abstract class AbstractValidatePaymentRequest extends AbstractRequest @@ -44,13 +45,26 @@ public function withParameters(array $params) } /** - * @return AbstractValidatePaymentResponse + * @return bool * @throws InvalidRequestException */ public final function send() { + if (! $this->payment->state->is(PaymentState::PURCHASED)) { + return false; + } + + if (! $this->payment->paid) { + return false; + } + + if (! $this->payment->paid->equals($this->payment->price)) { + return false; + } + /** @var AbstractValidatePaymentResponse $response */ $response = parent::send(); - return $response; + + return $response->validated(); } } \ No newline at end of file