diff --git a/config/payment.php b/config/payment.php index 2195533..d175aff 100644 --- a/config/payment.php +++ b/config/payment.php @@ -1,5 +1,7 @@ 'orange_ci', + 'default' => [ + 'gateway' => Payment::ORANGE, + 'country' => 'ci', + ], /** * List of available gateway */ - 'gateways' => [ - 'orange_ci' => [ + 'ivoiry_cost' => [ + 'orange' => [ + 'client_key' => '', + 'client_secret' => '', + 'webhook_secret' => '' + ], + + 'mtn' => [ + 'client_key' => '', + 'client_secret' => '', + 'webhook_secret' => '' + ], + + 'moov' => [ 'client_key' => '', - 'merchant_key' => '' + 'client_secret' => '', + 'webhook_secret' => '' ], - 'mtn_ci' => [ + 'wave' => [ 'client_key' => '', - 'merchant_key' => '' + 'client_secret' => '', + 'webhook_secret' => '' ], - 'moov_ci' => [ + 'djamo' => [ 'client_key' => '', - 'merchant_key' => '' + 'client_secret' => '', + 'webhook_secret' => '' ] - ] + ], ]; diff --git a/src/Bowcasher.php b/src/Bowcasher.php deleted file mode 100644 index 936305e..0000000 --- a/src/Bowcasher.php +++ /dev/null @@ -1,40 +0,0 @@ -environment = PaymentManagerContract::PRODUCTION; - } - - /** - * Switch to development mode - * - * @return string - */ - public function switchToDevelopment() - { - $this->environment = PaymentManagerContract::DEVELOPMENT; - } - - /** - * Get the payment environment - * - * @param string $environment - * @return string - */ - public function getEnvironment() - { - return $this->environment; - } -} diff --git a/src/Common/ProcessorGatewayInterface.php b/src/Common/ProcessorGatewayInterface.php new file mode 100644 index 0000000..bcff06b --- /dev/null +++ b/src/Common/ProcessorGatewayInterface.php @@ -0,0 +1,34 @@ +subscription_key = $subscription_key; - $this->basic_auth = $basic_auth; + public function __construct( + private string $subscription_key, + private string $basic_auth + ) { } /** @@ -55,9 +48,9 @@ public function getBasicAuthorizationKey() * * @return bool */ - public function production() + public function production(): bool { - return $this->environment = 'production'; + return $this->environment == 'production'; } /** @@ -65,7 +58,7 @@ public function production() * * @return bool */ - public function sandbox() + public function sandbox(): bool { return $this->environment == 'sandbox'; } @@ -95,7 +88,7 @@ public function switchToProduction() * * @return string */ - public function getBaseUri() + public function getBaseUri(): string { if ($this->sandbox()) { $base_uri = 'https://sandbox.momodeveloper.mtn.com/v1_0/'; @@ -111,7 +104,7 @@ public function getBaseUri() * * @return array */ - public function getAuthorization() + public function getAuthorization(): array { return [ 'Authorization' => 'Basic ' . $this->basic_auth, diff --git a/src/MTNMobileMoney/MonoTokenGenerator.php b/src/IvoryCost/MTNMobileMoney/MonoTokenGenerator.php similarity index 75% rename from src/MTNMobileMoney/MonoTokenGenerator.php rename to src/IvoryCost/MTNMobileMoney/MonoTokenGenerator.php index 6144c7f..db711e1 100644 --- a/src/MTNMobileMoney/MonoTokenGenerator.php +++ b/src/IvoryCost/MTNMobileMoney/MonoTokenGenerator.php @@ -14,33 +14,15 @@ class MomoEnvironment */ private $http; - /** - * The environment system - * - * @var MomoEnvironment - */ - private $environment; - - /** - * The name of payment action interface - * - * @var string - */ - private $interface_name; - /** * MomoEnvironment constructor * * @param MomoEnvironment $environment * @return mixed */ - public function __construct(MomoEnvironment $environment, $interface_name = 'collection') + public function __construct(private MomoEnvironment $environment, private string $interface_name = 'collection') { - $this->environment = $environment; - $this->http = new HttpClient(['base_uri' => $this->environment->getBaseUri()]); - - $this->interface_name = $interface_name; } /** diff --git a/src/MoovFlooz/.gitkeep b/src/IvoryCost/MoovFlooz/.gitkeep similarity index 100% rename from src/MoovFlooz/.gitkeep rename to src/IvoryCost/MoovFlooz/.gitkeep diff --git a/src/IvoryCost/OrangeMoney/OrangeMoneyGateway.php b/src/IvoryCost/OrangeMoney/OrangeMoneyGateway.php new file mode 100644 index 0000000..a669de6 --- /dev/null +++ b/src/IvoryCost/OrangeMoney/OrangeMoneyGateway.php @@ -0,0 +1,92 @@ +getTokenGenerator(); + + $payment = new OrangeMoneyPayment( + $token_generator->getToken(), + $this->config['client_secret'], + ); + + // Set the right production endpoint + $payment->setPaymentEndpoint('/orange-money-webpay/v1/webpayment'); + + $payment->setNotifyUrl($args['notif_url']); + $payment->setCancelUrl($args['cancel_url']); + $payment->setReturnUrl($args['return_url']); + + $amount = $args['amount']; + $reference = $args['reference']; + + $orange = $payment->prepare($amount, $reference); + + $payment_information = $orange->getPaymentInformation(); + + // Redirect to payment plateforme + $orange->pay(); + } + + /** + * Verify payment + * + * @param array ...$args + * @return ProcessorTransactionStatusInterface + */ + public function verify(...$args) + { + $token_generator = $this->getTokenGenerator(); + + // Transaction status + $transaction = new OrangeMoneyTransaction($token_generator->getToken()); + + // Set the production url + $transaction->setTransactionStatusEndpoint('/orange-money-webpay/v1/transactionstatus'); + + $amount = $args['amount']; + $order_id = $args['order_id']; + $pay_token = $args['pay_token']; + + // Check the transaction status + return $transaction->check($amount, $order_id, $pay_token); + } + + /** + * Create the Token Generator instance + * + * @return OrangeMoneyTokenGenerator + */ + private function getTokenGenerator() + { + $token_generator = new OrangeMoneyTokenGenerator($this->config['client_key']); + + // Set the right production endpoint + $token_generator->setTokenGeneratorEndpoint('/oauth/v2/token'); + + return $token_generator; + } +} diff --git a/src/OrangeMoney/OrangeMoneyPayment.php b/src/IvoryCost/OrangeMoney/OrangeMoneyPayment.php similarity index 81% rename from src/OrangeMoney/OrangeMoneyPayment.php rename to src/IvoryCost/OrangeMoney/OrangeMoneyPayment.php index f8f1a5b..e75cad1 100644 --- a/src/OrangeMoney/OrangeMoneyPayment.php +++ b/src/IvoryCost/OrangeMoney/OrangeMoneyPayment.php @@ -1,9 +1,9 @@ token = $token; - $this->http = new HttpClient(['base_uri' => 'https://api.orange.com']); - - $this->merchant_key = $merchant_key; - - $this->currency = $currency; } /** * Make payment * * @param int|double $amount - * @param string $order_id * @param string $reference * @return OrangeMoney */ - public function prepare($amount, string $order_id, string $reference) + public function prepare($amount, string $reference) { $response = $this->http->post($this->pay_url, [ - 'json' => $this->buildRequestData($amount, $reference, $order_id), + 'json' => $this->buildRequestData($amount, $reference), 'headers' => [ 'Authorization' => (string) $this->token, 'Accept' => 'application/json', @@ -97,7 +76,7 @@ public function prepare($amount, string $order_id, string $reference) // Parse Json data $data = json_decode($response->getBody()->getContents(), true); - return new OrangeMoney( + return new OrangeMoneyResponse( $data['payment_url'], $data['pay_token'], $data['notif_token'] @@ -181,16 +160,15 @@ public function setMerchantId(string $merchant_key) * * @param int|double $amount * @param string $reference - * @param string $order_id * @return array */ - protected function buildRequestData($amount, string $reference, string $order_id) + protected function buildRequestData($amount, string $reference) { return [ "merchant_key" => $this->merchant_key, "currency" => $this->currency, - "order_id" => $order_id, "amount" => $amount, + 'order_id' => $reference, "return_url" => $this->return_url, "cancel_url" => $this->cancel_url, "notif_url" => $this->notif_url, diff --git a/src/OrangeMoney/OrangeMoney.php b/src/IvoryCost/OrangeMoney/OrangeMoneyResponse.php similarity index 75% rename from src/OrangeMoney/OrangeMoney.php rename to src/IvoryCost/OrangeMoney/OrangeMoneyResponse.php index 703c4bc..c6aacd4 100644 --- a/src/OrangeMoney/OrangeMoney.php +++ b/src/IvoryCost/OrangeMoney/OrangeMoneyResponse.php @@ -1,8 +1,8 @@ pay_token = $pay_token; - - $this->payment_url = $payment_url; - - $this->notif_token = $notif_token; + public function __construct( + private ?string $payment_url, + private ?string $pay_token, + private ?string $notif_token + ) { } - + /** * Redirect client to make payment * @@ -44,7 +42,7 @@ public function getPaymentInformation() "notif_token" => $this->notif_token ]; } - + /** * __toString * diff --git a/src/Common/PaymentToken.php b/src/IvoryCost/OrangeMoney/OrangeMoneyToken.php similarity index 85% rename from src/Common/PaymentToken.php rename to src/IvoryCost/OrangeMoney/OrangeMoneyToken.php index 0b71e57..7c22809 100644 --- a/src/Common/PaymentToken.php +++ b/src/IvoryCost/OrangeMoney/OrangeMoneyToken.php @@ -1,8 +1,8 @@ token_type . ' ' . $this->access_token; } @@ -65,7 +65,7 @@ public function __toString() * * @return string */ - public function getAccessToken() + public function getAccessToken(): string { return $this->access_token; } @@ -75,7 +75,7 @@ public function getAccessToken() * * @return string */ - public function getType() + public function getType(): string { return $this->token_type; } @@ -85,7 +85,7 @@ public function getType() * * @return int */ - public function getExpiresIn() + public function getExpiresIn(): int { return $this->expires_in; } @@ -95,7 +95,7 @@ public function getExpiresIn() * * @return string */ - public function hasExpired() + public function hasExpired(): bool { return $this->expires_really_in - time() <= 0; } diff --git a/src/OrangeMoney/OrangeMoneyTokenGenerator.php b/src/IvoryCost/OrangeMoney/OrangeMoneyTokenGenerator.php similarity index 89% rename from src/OrangeMoney/OrangeMoneyTokenGenerator.php rename to src/IvoryCost/OrangeMoney/OrangeMoneyTokenGenerator.php index 524c58e..1baaf06 100644 --- a/src/OrangeMoney/OrangeMoneyTokenGenerator.php +++ b/src/IvoryCost/OrangeMoney/OrangeMoneyTokenGenerator.php @@ -1,12 +1,11 @@ getBody()->getContents(); $token = json_decode($content); - + return new OrangeMoneyToken( $token->access_token, $token->token_type, diff --git a/src/OrangeMoney/OrangeMoneyTransaction.php b/src/IvoryCost/OrangeMoney/OrangeMoneyTransaction.php similarity index 93% rename from src/OrangeMoney/OrangeMoneyTransaction.php rename to src/IvoryCost/OrangeMoney/OrangeMoneyTransaction.php index e58b01f..dd6bd30 100644 --- a/src/OrangeMoney/OrangeMoneyTransaction.php +++ b/src/IvoryCost/OrangeMoney/OrangeMoneyTransaction.php @@ -1,9 +1,9 @@ check($amount, $order_id, $pay_token); - return $status->fail(); + return $status->isFail(); } /** @@ -104,7 +104,7 @@ public function checkIfHasPending($amount, string $order_id, string $pay_token) { $status = $this->check($amount, $order_id, $pay_token); - return $status->pending(); + return $status->isPending(); } /** @@ -118,7 +118,7 @@ public function checkIfHasSuccess($amount, string $order_id, string $pay_token) { $status = $this->check($amount, $order_id, $pay_token); - return $status->success(); + return $status->isSuccess(); } /** diff --git a/src/OrangeMoney/OrangeMoneyTransactionStatus.php b/src/IvoryCost/OrangeMoney/OrangeMoneyTransactionStatus.php similarity index 72% rename from src/OrangeMoney/OrangeMoneyTransactionStatus.php rename to src/IvoryCost/OrangeMoney/OrangeMoneyTransactionStatus.php index a808ff8..e2ede79 100644 --- a/src/OrangeMoney/OrangeMoneyTransactionStatus.php +++ b/src/IvoryCost/OrangeMoney/OrangeMoneyTransactionStatus.php @@ -1,10 +1,10 @@ notif_token = $notif_token; } - /** - * Get the notification token - * - * @return string - */ - public function getNotificationToken() - { - return $this->notif_token; - } - /** * Define if transaction fail * * @return bool */ - public function fail() + public function isFail() { return $this->status == 'FAIL'; } @@ -58,7 +48,7 @@ public function fail() * * @return bool */ - public function initiated() + public function isInitiated() { return $this->status == 'INITIATED'; } @@ -68,7 +58,7 @@ public function initiated() * * @return bool */ - public function expired() + public function isExpired() { return $this->status == 'EXPIRED'; } @@ -78,7 +68,7 @@ public function expired() * * @return bool */ - public function success() + public function isSuccess() { return $this->status == 'SUCCESS'; } @@ -88,7 +78,7 @@ public function success() * * @return bool */ - public function pending() + public function isPending() { return $this->status == 'PENDING'; } diff --git a/src/Stripe/.gitkeep b/src/IvoryCost/Wave/.gitkeep similarity index 100% rename from src/Stripe/.gitkeep rename to src/IvoryCost/Wave/.gitkeep diff --git a/src/OrangeMoney/BowcasherOrangeMoneyService.php b/src/OrangeMoney/BowcasherOrangeMoneyService.php deleted file mode 100644 index b0cfc7f..0000000 --- a/src/OrangeMoney/BowcasherOrangeMoneyService.php +++ /dev/null @@ -1,105 +0,0 @@ -config = $config; - } - - /** - * Make payment - * - * @return void - */ - public function pay(...$args) - { - $token_generator = $this->getTokenGenerator(); - - $payment = new OrangeMoneyPayment( - $token_generator->getToken(), - $this->config['merchant_key'] - ); - - // Set the right production endpoint - if ($this->getEnvironment() == PaymentManagerContract::PRODUCTION) { - $payment->setPaymentEndpoint('/orange-money-webpay/v1/webpayment'); - } - - $payment->setNotifyUrl($args['notif_url']); - $payment->setCancelUrl($args['cancel_url']); - $payment->setReturnUrl($args['return_url']); - - $amount = $args['amount']; - $order_id = $args['order_id']; - $reference = $args['reference']; - - $orange = $payment->prepare($amount, $order_id, $reference); - $payment_information = $orange->getPaymentInformation(); - - // Redirect to payment plateforme - $orange->pay(); - } - - /** - * Verify payment - * - * @param array ...$args - * @return TransactionStatusContract - */ - public function verify(...$args) - { - $token_generator = $this->getTokenGenerator(); - // Transaction status - $transaction = new OrangeMoneyTransaction($token_generator->getToken()); - - // Set the production url - if ($this->getEnvironment() == PaymentManagerContract::PRODUCTION) { - $transaction->setTransactionStatusEndpoint('/orange-money-webpay/v1/transactionstatus'); - } - - $amount = $args['amount']; - $order_id = $args['order_id']; - $reference = $args['reference']; - - // Check the transaction status - return $transaction->check($amount, $order_id, $reference); - } - - /** - * Create the Token Generator instance - * - * @return OrangeMoneyTokenGenerator - */ - private function getTokenGenerator() - { - $token_generator = new OrangeMoneyTokenGenerator($this->config['client_key']); - - // Set the right production endpoint - if ($this->getEnvironment() == PaymentManagerContract::PRODUCTION) { - $token_generator->setTokenGeneratorEndpoint('/oauth/v2/token'); - } - - return $token_generator; - } -} - \ No newline at end of file diff --git a/src/Payment.php b/src/Payment.php new file mode 100644 index 0000000..b70d628 --- /dev/null +++ b/src/Payment.php @@ -0,0 +1,202 @@ + + */ + public const CI_PROVIDER = [ + Payment::ORANGE => \Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyGateway::class, + Payment::MOOV => null, + Payment::WAVE => null, + Payment::MTN => null, + Payment::DJAMO => null, + ]; + + /** + * The payment manager instance + * + * @var ProcessorGatewayInterface + */ + private static $providerGateway; + + /** + * The payment instance + * + * @var Payment + */ + private static $instance; + + /** + * ForPayment constructor + * + * @param array $config + * @return mixed + */ + public function __construct(private array $config) + { + $default = $this->config['default']; + $country = $default['country'] ?? 'ci'; + $defaultProvider = $default['gateway'] ?? Payment::ORANGE; + + $this->resolveGateway($country, $defaultProvider); + } + + /** + * Resolve the payment gateway + * + * @param string $country + * @param string $provider + * @return void + */ + private function resolveGateway(string $country, string $provider) + { + switch ($country) { + case self::CI: + $provider = self::CI_PROVIDER[$provider] ?? null; + if ($provider === null) { + throw new \InvalidArgumentException("The payment gateway [{$provider}] is not supported in country [{$country}]."); + } + $config = $this->resolveConfig('ivoiry_cost', $provider); + static::$providerGateway = new $provider($config); + break; + // Other gateways can be added here + default: + throw new \InvalidArgumentException("The payment gateway [{$provider}] is not supported."); + } + } + + /** + * Resolve configuration for a specific country and provider + * + * @param string $country + * @param string $provider + * @return array|null + */ + public function resolveConfig(string $country, string $provider) + { + return $this->config[$country][$provider] ?? []; + } + + /** + * Make configuration + * + * @return PaymentManagerContract + */ + public static function configure(array $configuration) + { + static::$instance = new Payment($configuration); + + return static::$instance; + } + + /** + * Switch payment provider + * + * @param string $country + * @param string $provider + * @return void + */ + public function withProvider(string $country, string $provider): void + { + $this->resolveGateway($country, $provider); + } + + /** + * Make payment + * + * @return mixed + */ + public function payment(...$args) + { + return static::$providerGateway->payment(...$args); + } + + /** + * Make transfer + * + * @return mixed + */ + public function transfer(...$args) + { + return static::$providerGateway->transfer(...$args); + } + + /** + * Get balance + * + * @return mixed + */ + public function balance(...$args) + { + return static::$providerGateway->balance(...$args); + } + + /** + * Verify payment + * + * @return void + */ + public function verify() + { + return static::$providerGateway->verify(); + } + + /** + * __callStatic + * + * @param string $methodName + * @param array $methodArguments + * @return mixed + */ + public static function __callStatic($methodName, $methodArguments) + { + if (method_exists(static::$instance, $methodName)) { + return call_user_func_array([static::$instance, $methodName], $methodArguments); + } + } +} diff --git a/src/BowcasherConfirguration.php b/src/PaymentConfirguration.php similarity index 69% rename from src/BowcasherConfirguration.php rename to src/PaymentConfirguration.php index 55bb620..2ddf62d 100644 --- a/src/BowcasherConfirguration.php +++ b/src/PaymentConfirguration.php @@ -5,14 +5,14 @@ use Bow\Configuration\Configuration; use Bow\Configuration\Loader as Config; -class BowcasherConfiguration extends Configuration +class PaymentConfiguration extends Configuration { /** * Create payment configuration * * @param Config $config */ - public function create(Config $config) + public function create(Config $config): void { $payment = require __DIR__.'/../config/payment'; @@ -21,7 +21,7 @@ public function create(Config $config) $config['payment'] = $payment; $this->container->make('payment', function ($config) { - return Bowcasher::configure($config['payment']); + return Payment::configure($config['payment']); }); } @@ -30,8 +30,8 @@ public function create(Config $config) * * @return mixed */ - public function run() + public function run(): void { - return $this->container->make('payment'); + $this->container->make('payment'); } } diff --git a/src/PaymentNotificationController.php b/src/PaymentNotificationController.php deleted file mode 100644 index 6a28234..0000000 --- a/src/PaymentNotificationController.php +++ /dev/null @@ -1,34 +0,0 @@ -user = config('payment.model'); - } - - /** - * Process payment notification here - * - * @param Request $request - * @return mixed - */ - public function handle(Request $request) - { - $user_id = $request->get('user_id'); - - $user = $this->user->find($user_id); - - $user->payment(); - } -} diff --git a/src/UserPayment.php b/src/UserPayment.php index 9f02cce..60bbd73 100644 --- a/src/UserPayment.php +++ b/src/UserPayment.php @@ -4,13 +4,30 @@ trait UserPayment { + public function withPaymentProvider(string $country, string $provider): self + { + Payment::withProvider($country, $provider); + + return $this; + } + + /** + * Make user payment + * + * @return mixed + */ + public function payment($amount, $reference) + { + return Payment::payment($amount, $reference); + } + /** * Make user payment * * @return mixed */ - public function payment($amount, $order_id, $reference) + public function transfer($amount, $reference) { - return Bowcasher::pay($amount, $order_id, $reference); + return Payment::transfer($amount, $reference); } }