diff --git a/src/EventHandlers/FawryEventHandler.php b/src/EventHandlers/FawryEventHandler.php new file mode 100644 index 0000000..a4a40d5 --- /dev/null +++ b/src/EventHandlers/FawryEventHandler.php @@ -0,0 +1,68 @@ +<?php + +namespace Flutterwave\EventHandlers; + +use Flutterwave\Contract\ConfigInterface; + +class FawryEventHandler implements EventHandlerInterface +{ + use EventTracker; + + private static ConfigInterface $config; + public function __construct($config) + { + self::$config = $config; + } + + public function onSuccessful($transactionData): void + { + // TODO: Implement onSuccessful() method. + } + + public function onFailure($transactionData): void + { + // TODO: Implement onFailure() method. + } + + public function onRequery($transactionReference): void + { + // TODO: Implement onRequery() method. + } + + public function onRequeryError($requeryResponse): void + { + // TODO: Implement onRequeryError() method. + } + + public function onCancel($transactionReference): void + { + // TODO: Implement onCancel() method. + } + + public function onTimeout($transactionReference, $data): void + { + // TODO: Implement onTimeout() method. + } + + public function onAuthorization(\stdClass $response, ?array $resource = null): array + { + if (property_exists($response, 'data')) { + $transactionId = $response->data->id; + $tx_ref = $response->data->tx_ref; + $data['data_to_save'] = [ + 'transactionId' => $transactionId, + 'tx_ref' => $tx_ref, + ]; + $data['mode'] = $response->data->meta->authorization->mode; + } + + $data['dev_instruction'] = 'Redirect the user to the auth link for validation. verfiy via the verify endpoint.'; + + if (is_array($resource) && ! empty($resource)) { + $logger = $resource['logger']; + $logger->notice('Fawry Method Event::Fawry Authorization Mode: ' . $data['mode'] ?? 'fawry_pay'); + } + + return $data; + } +} \ No newline at end of file diff --git a/src/Service/Fawry.php b/src/Service/Fawry.php new file mode 100644 index 0000000..0eaad3f --- /dev/null +++ b/src/Service/Fawry.php @@ -0,0 +1,81 @@ +<?php + +namespace Flutterwave\Service; + +use Flutterwave\Contract\ConfigInterface; +use Flutterwave\Contract\Payment; +use Flutterwave\EventHandlers\GooglePayEventHandler; +use Flutterwave\Entities\Payload; +use Flutterwave\Traits\Group\Charge; +use GuzzleHttp\Exception\GuzzleException; +use Psr\Http\Client\ClientExceptionInterface; +use stdClass; + +class Fawry extends Service implements Payment +{ + use Charge; + + public const TYPE = 'fawry_pay'; + private GooglePayEventHandler $eventHandler; + + public function __construct(?ConfigInterface $config = null) + { + parent::__construct($config); + $endpoint = $this->getEndpoint(); + $this->url = $this->baseUrl . '/' . $endpoint . '?type='; + $this->eventHandler = new GooglePayEventHandler($config); + } + + /** + * @return array + * + * @throws GuzzleException + */ + public function initiate(Payload $payload): array + { + return $this->charge($payload); + } + + /** + * @param Payload $payload + * @return array + * + * @throws ClientExceptionInterface + */ + public function charge(Payload $payload): array + { + $this->logger->notice('Google Service::Started Charging Process ...'); + + $payload = $payload->toArray(); + + if($payload['currency'] !== 'EGP') { + throw new \InvalidArgumentException("Invalid currency. This transaction is only allowed for EGP"); + } + + //request payload + $body = $payload; + + unset($body['country']); + unset($body['address']); + + $this->eventHandler::startRecording(); + $request = $this->request($body, 'POST', self::TYPE); + $this->eventHandler::setResponseTime(); + return $this->handleAuthState($request, $body); + } + + public function save(callable $callback): void + { + // TODO: Implement save() method. + } + + /** + * @param array $payload + * + * @return array + */ + private function handleAuthState(stdClass $response, array $payload): array + { + return $this->eventHandler->onAuthorization($response, ['logger' => $this->logger]); + } +} \ No newline at end of file diff --git a/src/Util/Currency.php b/src/Util/Currency.php index 23eb0f3..06d7aa3 100644 --- a/src/Util/Currency.php +++ b/src/Util/Currency.php @@ -18,4 +18,5 @@ class Currency public const RWF = 'RWF'; public const XAF = 'XAF'; public const XOF = 'XOF'; + public const EGP = 'EGP'; } diff --git a/src/Util/methods.php b/src/Util/methods.php index 8ef122d..3e5fd20 100644 --- a/src/Util/methods.php +++ b/src/Util/methods.php @@ -18,6 +18,7 @@ use Flutterwave\Service\Ussd; use Flutterwave\Service\GooglePay; use Flutterwave\Service\Enaira; +use Flutterwave\Service\Fawry; //use Flutterwave\Service\PayPal; //use Flutterwave\Service\Remita; @@ -39,7 +40,8 @@ 'transfer' => Transfer::class, 'ussd' => Ussd::class, 'google' => GooglePay::class, - 'enaira' => Enaira::class + 'enaira' => Enaira::class, + 'fawry' => Fawry::class // "paypal" => PayPal::class, // "remita" => Remita::class, // "voucher" => VoucherPayment::class, diff --git a/tests/Unit/Service/FawryTest.php b/tests/Unit/Service/FawryTest.php new file mode 100644 index 0000000..6f68a67 --- /dev/null +++ b/tests/Unit/Service/FawryTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Unit\Service; + +use PHPUnit\Framework\TestCase; +use Flutterwave\Flutterwave; +use Flutterwave\Util\AuthMode; +use Flutterwave\Util\Currency; + +class FawryTest extends TestCase +{ + protected function setUp(): void + { + \Flutterwave\Flutterwave::bootstrap(); + } + + public function testAuthModeReturnRedirect() + { + $data = [ + "amount" => 2000, + "currency" => Currency::EGP, + "tx_ref" => uniqid().time(), + "redirectUrl" => "https://example.com" + ]; + + $payment = \Flutterwave\Flutterwave::create("fawry"); + $customerObj = $payment->customer->create([ + "full_name" => "Olaobaju Jesulayomi Abraham", + "email" => "vicomma@gmail.com", + "phone" => "+2349060085861" + ]); + + $data['customer'] = $customerObj; + $payload = $payment->payload->create($data); + $result = $payment->initiate($payload); + + $this->assertSame('fawry_pay', $result['mode']); + } + +} \ No newline at end of file