Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions config/payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,20 @@
'webhook_secret' => ''
]
],

/**
* Senegal payment gateways configuration
*/
'senegal' => [
'orange' => [
'client_key' => '',
'client_secret' => '',
'webhook_secret' => ''
],

'wave' => [
'api_key' => '', // Your Wave API key (starts with wave_sn_prod_ or wave_sn_sandbox_)
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 66 mentions Wave API keys starting with 'wave_sn_prod_' or 'wave_sn_sandbox_', where 'sn' stands for Senegal. However, this same comment also appears in the Ivory Coast configuration (line 44, not changed in this PR). If Wave uses the same API across countries, consider clarifying the comment to indicate this. If Ivory Coast should use different key prefixes (e.g., wave_ci_), the comment should be updated accordingly.

Copilot uses AI. Check for mistakes.
'webhook_secret' => ''
],
],
];
10 changes: 5 additions & 5 deletions docs/en.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ For advanced use cases, you can use providers directly:
### Orange Money Direct Usage

```php
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyGateway;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyGateway;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;

$config = [
'client_key' => 'YOUR_CLIENT_KEY',
Expand Down Expand Up @@ -332,9 +332,9 @@ $status = $gateway->verify([
### MTN Mobile Money Direct Usage

```php
use Bow\Payment\IvoryCost\MTNMobileMoney\MTNMobileMoneyGateway;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoTokenGenerator;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MTNMobileMoneyGateway;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoTokenGenerator;

$config = [
'subscription_key' => 'YOUR_SUBSCRIPTION_KEY',
Expand Down
10 changes: 5 additions & 5 deletions docs/fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ Pour des cas d'utilisation avancés, vous pouvez utiliser les fournisseurs direc
### Utilisation Directe d'Orange Money

```php
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyGateway;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyGateway;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;

$config = [
'client_key' => 'VOTRE_CLIENT_KEY',
Expand Down Expand Up @@ -332,9 +332,9 @@ $status = $gateway->verify([
### Utilisation Directe de MTN Mobile Money

```php
use Bow\Payment\IvoryCost\MTNMobileMoney\MTNMobileMoneyGateway;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoTokenGenerator;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MTNMobileMoneyGateway;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoTokenGenerator;

$config = [
'subscription_key' => 'VOTRE_SUBSCRIPTION_KEY',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\Djamo;
namespace Bow\Payment\Gateway\IvoryCost\Djamo;

use Bow\Payment\Common\ProcessorGatewayInterface;
use Bow\Payment\Exceptions\PaymentRequestException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php

namespace Bow\Payment\IvoryCost\MTNMobileMoney\Collection;
namespace Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\Collection;

use Bow\Payment\Common\Utils;
use GuzzleHttp\Client as HttpClient;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoToken;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoToken;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Exceptions\PaymentRequestException;

class MomoPayment
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\MTNMobileMoney\Collection;
namespace Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\Collection;

use Bow\Payment\Common\ProcessorStatusInterface;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?php

namespace Bow\Payment\IvoryCost\MTNMobileMoney\Collection;
namespace Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\Collection;

use GuzzleHttp\Client as HttpClient;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoToken;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoToken;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Exceptions\TransactionVerificationException;

class MomoTransaction
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<?php

namespace Bow\Payment\IvoryCost\MTNMobileMoney;
namespace Bow\Payment\Gateway\IvoryCost\MTNMobileMoney;

use Bow\Payment\Common\ProcessorGatewayInterface;
use Bow\Payment\IvoryCost\MTNMobileMoney\Collection\MomoPayment;
use Bow\Payment\IvoryCost\MTNMobileMoney\Collection\MomoTransaction;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoTokenGenerator;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\Collection\MomoPayment;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\Collection\MomoTransaction;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoTokenGenerator;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoEnvironment;

class MTNMobileMoneyGateway implements ProcessorGatewayInterface
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\MTNMobileMoney;
namespace Bow\Payment\Gateway\IvoryCost\MTNMobileMoney;

class MomoEnvironment
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\MTNMobileMoney;
namespace Bow\Payment\Gateway\IvoryCost\MTNMobileMoney;

class MomoToken
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?php

namespace Bow\Payment\IvoryCost\MTNMobileMoney;
namespace Bow\Payment\Gateway\IvoryCost\MTNMobileMoney;

use GuzzleHttp\Client as HttpClient;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoToken;
use Bow\Payment\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoToken;
use Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MomoEnvironment;
use Bow\Payment\Exceptions\TokenGenerationException;

class MomoTokenGenerator
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\MoovFlooz;
namespace Bow\Payment\Gateway\IvoryCost\MoovFlooz;

use Bow\Payment\Common\ProcessorGatewayInterface;
use Bow\Payment\Exceptions\PaymentRequestException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<?php

namespace Bow\Payment\IvoryCost\OrangeMoney;
namespace Bow\Payment\Gateway\IvoryCost\OrangeMoney;

use Bow\Payment\Common\ProcessorGatewayInterface;
use Bow\Payment\Common\ProcessorTransactionStatusInterface;
use Bow\Payment\Exceptions\PaymentRequestException;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyPayment;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyTransaction;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyPayment;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyTransaction;

class OrangeMoneyGateway implements ProcessorGatewayInterface
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?php

namespace Bow\Payment\IvoryCost\OrangeMoney;
namespace Bow\Payment\Gateway\IvoryCost\OrangeMoney;

use \GuzzleHttp\Client as HttpClient;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyToken;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyToken;

class OrangeMoneyPayment
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\OrangeMoney;
namespace Bow\Payment\Gateway\IvoryCost\OrangeMoney;

class OrangeMoneyResponse
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\OrangeMoney;
namespace Bow\Payment\Gateway\IvoryCost\OrangeMoney;

class OrangeMoneyToken
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?php

namespace Bow\Payment\IvoryCost\OrangeMoney;
namespace Bow\Payment\Gateway\IvoryCost\OrangeMoney;

use \GuzzleHttp\Client as HttpClient;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyToken;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyToken;

class OrangeMoneyTokenGenerator
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?php

namespace Bow\Payment\IvoryCost\OrangeMoney;
namespace Bow\Payment\Gateway\IvoryCost\OrangeMoney;

use \GuzzleHttp\Client as HttpClient;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyToken;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyToken;

class OrangeMoneyTransaction
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\OrangeMoney;
namespace Bow\Payment\Gateway\IvoryCost\OrangeMoney;

use Bow\Payment\Common\ProcessorStatusInterface;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\Wave;
namespace Bow\Payment\Gateway\IvoryCost\Wave;

/**
* Wave Checkout Session
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\Wave;
namespace Bow\Payment\Gateway\IvoryCost\Wave;

use GuzzleHttp\Client as HttpClient;
use Bow\Payment\Exceptions\PaymentRequestException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\Wave;
namespace Bow\Payment\Gateway\IvoryCost\Wave;

use Bow\Payment\Common\ProcessorGatewayInterface;
use Bow\Payment\Exceptions\PaymentRequestException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Bow\Payment\IvoryCost\Wave;
namespace Bow\Payment\Gateway\IvoryCost\Wave;

use Bow\Payment\Common\ProcessorStatusInterface;

Expand Down
19 changes: 19 additions & 0 deletions src/Gateway/Senegal/OrangeMoney/OrangeMoneyGateway.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Bow\Payment\Gateway\Senegal\OrangeMoney;

use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyGateway as BaseOrangeMoneyGateway;

/**
* Orange Money Gateway for Senegal
* Orange Money operates across multiple countries
* This class extends the base Orange Money implementation
*
* The API endpoints and authentication methods are the same
* but may use different credentials and regional configurations
*/
class OrangeMoneyGateway extends BaseOrangeMoneyGateway
{
// Inherits all functionality from the base Orange Money gateway
// Orange Money API is the same for Senegal and Ivory Coast
}
18 changes: 18 additions & 0 deletions src/Gateway/Senegal/Wave/WaveGateway.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Bow\Payment\Gateway\Senegal\Wave;

use Bow\Payment\Gateway\IvoryCost\Wave\WaveGateway as BaseWaveGateway;

/**
* Wave Gateway for Senegal
* Wave operates across multiple countries with the same API
* This class extends the base Wave implementation
*
* @link https://docs.wave.com/checkout
*/
class WaveGateway extends BaseWaveGateway
{
// Inherits all functionality from the base Wave gateway
// Wave API is the same for Senegal and Ivory Coast
}
36 changes: 31 additions & 5 deletions src/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class Payment implements ProcessorGatewayInterface
*/
public const CI = 'ivory_coast';

/**
* Senegal country identifier
* ISO 3166-1 alpha-2 country code for Senegal
*/
public const SN = 'senegal';
Comment on lines +45 to +49
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "ISO 3166-1 alpha-2 country code for Senegal", but the constant value is 'senegal' (a descriptive string), not 'SN' (the actual ISO code). While the constant name SN represents the ISO code, the comment could be misleading. Consider clarifying the comment to: "Senegal country identifier (constant name follows ISO 3166-1 alpha-2: SN)" to match the pattern used elsewhere in the codebase.

Copilot uses AI. Check for mistakes.

/**
* Ivory Coast payment provider mapping
* Maps payment provider identifiers to their respective service classes
Expand All @@ -50,11 +56,23 @@ class Payment implements ProcessorGatewayInterface
* @var array<string, class-string>
*/
public const CI_PROVIDER = [
Payment::ORANGE => \Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyGateway::class,
Payment::MTN => \Bow\Payment\IvoryCost\MTNMobileMoney\MTNMobileMoneyGateway::class,
Payment::MOOV => \Bow\Payment\IvoryCost\MoovFlooz\MoovFloozGateway::class,
Payment::WAVE => \Bow\Payment\IvoryCost\Wave\WaveGateway::class,
Payment::DJAMO => \Bow\Payment\IvoryCost\Djamo\DjamoGateway::class,
Payment::ORANGE => \Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyGateway::class,
Payment::MTN => \Bow\Payment\Gateway\IvoryCost\MTNMobileMoney\MTNMobileMoneyGateway::class,
Payment::MOOV => \Bow\Payment\Gateway\IvoryCost\MoovFlooz\MoovFloozGateway::class,
Payment::WAVE => \Bow\Payment\Gateway\IvoryCost\Wave\WaveGateway::class,
Payment::DJAMO => \Bow\Payment\Gateway\IvoryCost\Djamo\DjamoGateway::class,
];

/**
* Senegal payment provider mapping
* Maps payment provider identifiers to their respective service classes
* for payment processing in Senegal (SN)
*
* @var array<string, class-string>
*/
public const SN_PROVIDER = [
Payment::ORANGE => \Bow\Payment\Gateway\Senegal\OrangeMoney\OrangeMoneyGateway::class,
Payment::WAVE => \Bow\Payment\Gateway\Senegal\Wave\WaveGateway::class,
];

/**
Expand Down Expand Up @@ -104,6 +122,14 @@ private function resolveGateway(string $country, string $provider)
$config = $this->resolveConfig('ivory_coast', $provider);
static::$providerGateway = new $provider($config);
break;
case self::SN:
$provider = self::SN_PROVIDER[$provider] ?? null;
if ($provider === null) {
throw new \InvalidArgumentException("The payment gateway [{$provider}] is not supported in country [{$country}].");
Comment on lines +126 to +128
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message on line 128 will not display the original provider name correctly. The variable $provider is reassigned on line 126 to either a gateway class or null. When null, the error message will show an empty string instead of the original provider identifier (e.g., 'orange', 'wave') that the user attempted to use. Store the original provider value before the reassignment to ensure the error message is informative.

Copilot uses AI. Check for mistakes.
}
$config = $this->resolveConfig('senegal', $provider);
static::$providerGateway = new $provider($config);
break;
Comment on lines +125 to +132
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Senegal payment support lacks test coverage. The repository has comprehensive tests for Ivory Coast payment providers (see tests/PaymentTest.php and tests/OrangeMoneyTest.php). Consider adding similar tests for Senegal, including tests for Payment::SN constant, Payment::SN_PROVIDER mapping, and the gateway resolution logic for Senegal.

Copilot uses AI. Check for mistakes.
// Other gateways can be added here
default:
throw new \InvalidArgumentException("The payment gateway [{$provider}] is not supported.");
Expand Down
6 changes: 3 additions & 3 deletions tests/OrangeMoneyTest.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php

use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyPayment;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyToken;
use Bow\Payment\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyPayment;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyToken;
use Bow\Payment\Gateway\IvoryCost\OrangeMoney\OrangeMoneyTokenGenerator;

class OrangeMoneyTest extends \PHPUnit\Framework\TestCase
{
Expand Down
Loading