Client::purchaseAirtime()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 7
rs 10
cc 1
nc 1
nop 4
1
<?php
2
3
namespace HenryEjemuta\Clubkash;
4
5
use GuzzleHttp\Client as GuzzleClient;
6
7
class Client
8
{
9
    private const BASE_URL = 'https://www.nellobytesystems.com/';
10
    
11
    /**
12
     * @var string
13
     */
14
    private $userID;
15
    private $apiKey;
16
    private $httpClient;
17
18
    /**
19
     * @var string|null
20
     */
21
    private $token;
22
23
    /**
24
     * Client constructor.
25
     *
26
     * @param string $userID
27
     * @param string $apiKey
28
     * @param array $config
29
     */
30
    public function __construct(string $userID, string $apiKey, array $config = [])
31
    {
32
        $this->userID = $userID;
33
        $this->apiKey = $apiKey;
34
        $this->token = $config['token'] ?? null; // Allow passing token in config
35
36
        $baseUrl = $config['base_url'] ?? self::BASE_URL;
37
        // Ensure base URL ends with a slash
38
        if (substr($baseUrl, -1) !== '/') {
39
            $baseUrl .= '/';
40
        }
41
42
        $timeout = $config['timeout'] ?? 30;
43
        
44
        $guzzleConfig = [
45
            'base_uri' => $baseUrl,
46
            'timeout' => $timeout,
47
            'headers' => [
48
                'Accept' => 'application/json',
49
            ],
50
        ];
51
        
52
        if (isset($config['handler'])) {
53
            $guzzleConfig['handler'] = $config['handler'];
54
        }
55
56
        $this->httpClient = new GuzzleClient($guzzleConfig);
57
    }
58
59
    /**
60
     * Authenticate and generate a new token.
61
     * Note: Token expires after 7 days.
62
     *
63
     * @return array
64
     * @throws ClubkashException
65
     */
66
    public function authenticate(): array
67
    {
68
        // Placeholder for authentication endpoint
69
        $response = $this->request('GET', 'APIToken.asp', [
70
             'username' => $this->userID,
71
             'apikey' => $this->apiKey
72
        ]);
73
74
        if (isset($response['token'])) {
75
            $this->token = $response['token'];
76
        }
77
78
        return $response;
79
    }
80
81
    /**
82
     * Make a request to the API.
83
     * 
84
     * @param string $method
85
     * @param string $endpoint
86
     * @param array $params
87
     * @return array
88
     * @throws ClubkashException
89
     */
90
    private function request(string $method, string $endpoint, array $params = []): array
91
    {
92
        $options = [];
93
94
        // Use token if available, otherwise fallback to UserID/APIKey
95
        if ($this->token) {
96
             $options['headers']['Authorization'] = 'Bearer ' . $this->token;
97
        } else {
98
             $params['UserID'] = $this->userID;
99
             $params['APIKey'] = $this->apiKey;
100
        }
101
102
        if (strtoupper($method) === 'GET') {
103
            $options['query'] = $params;
104
        } else {
105
            $options['query'] = $params;
106
        }
107
108
        try {
109
            $response = $this->httpClient->request($method, $endpoint, $options);
110
            $content = $response->getBody()->getContents();
111
            $data = json_decode($content, true);
112
113
            if (json_last_error() !== JSON_ERROR_NONE) {
114
                throw new ClubkashException('Failed to decode JSON response: ' . $content);
115
            }
116
117
            return $data;
118
119
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
120
            throw new ClubkashException('API Request Failed: ' . $e->getMessage(), $e->getCode(), $e);
121
        }
122
    }
123
124
    /**
125
     * Get wallet balance.
126
     *
127
     * @return array
128
     * @throws ClubkashException
129
     */
130
    public function getWalletBalance(): array
131
    {
132
        return $this->request('GET', 'APIWalletBalanceV1.asp');
133
    }
134
135
    /**
136
     * Purchase Airtime.
137
     *
138
     * @param string $mobileNetwork Network Code (01=MTN, 02=GLO, 03=9Mobile, 04=Airtel)
139
     * @param float $amount Amount to top up
140
     * @param string $mobileNumber Phone number
141
     * @param string|null $requestID Unique Request ID (optional, generated if null)
142
     * @return array
143
     * @throws ClubkashException
144
     */
145
    public function purchaseAirtime(string $mobileNetwork, float $amount, string $mobileNumber, string $requestID = null): array
146
    {
147
        return $this->request('GET', 'APIAirtimeV1.asp', [
148
            'MobileNetwork' => $mobileNetwork,
149
            'Amount' => $amount,
150
            'MobileNumber' => $mobileNumber,
151
            'RequestID' => $requestID ?? $this->generateRequestID(),
152
        ]);
153
    }
154
155
    /**
156
     * Purchase Data Bundle.
157
     *
158
     * @param string $mobileNetwork Network Code (01=MTN, 02=GLO, 03=9Mobile, 04=Airtel)
159
     * @param string $dataPlan Data Plan Code
160
     * @param string $mobileNumber Phone number
161
     * @param string|null $requestID Unique Request ID (optional, generated if null)
162
     * @return array
163
     * @throws ClubkashException
164
     */
165
    public function purchaseData(string $mobileNetwork, string $dataPlan, string $mobileNumber, string $requestID = null): array
166
    {
167
        return $this->request('GET', 'APIDatabundleV1.asp', [
168
            'MobileNetwork' => $mobileNetwork,
169
            'DataPlan' => $dataPlan,
170
            'MobileNumber' => $mobileNumber,
171
            'RequestID' => $requestID ?? $this->generateRequestID(),
172
        ]);
173
    }
174
175
    /**
176
     * Purchase Cable TV Subscription.
177
     *
178
     * @param string $cableTV Provider (dstv, gotv, startimes)
179
     * @param string $package Package Code
180
     * @param string $smartCardNo SmartCard/IUC Number
181
     * @param string $phoneNo Phone number used for the subscription
182
     * @param string|null $requestID Unique Request ID (optional, generated if null)
183
     * @return array
184
     * @throws ClubkashException
185
     */
186
    public function purchaseCableTV(string $cableTV, string $package, string $smartCardNo, string $phoneNo, string $requestID = null): array
187
    {
188
        return $this->request('GET', 'APICableTVV1.asp', [
189
            'CableTV' => $cableTV,
190
            'Package' => $package,
191
            'SmartCardNo' => $smartCardNo,
192
            'PhoneNo' => $phoneNo,
193
            'RequestID' => $requestID ?? $this->generateRequestID(),
194
        ]);
195
    }
196
197
    /**
198
     * Purchase Electricity Token.
199
     *
200
     * @param string $electricCompany Company Code (01=Eko, 02=Ikeja, etc.)
201
     * @param string $meterNo Meter Number
202
     * @param string $meterType Meter Type (01=Prepaid, 02=Postpaid)
203
     * @param float $amount Amount
204
     * @param string $phoneNo Phone number
205
     * @param string|null $requestID Unique Request ID (optional, generated if null)
206
     * @return array
207
     * @throws ClubkashException
208
     */
209
    public function purchaseElectricity(string $electricCompany, string $meterNo, string $meterType, float $amount, string $phoneNo, string $requestID = null): array
210
    {
211
        return $this->request('GET', 'APIElectricityV1.asp', [
212
            'ElectricCompany' => $electricCompany,
213
            'MeterNo' => $meterNo,
214
            'MeterType' => $meterType,
215
            'Amount' => $amount,
216
            'PhoneNo' => $phoneNo,
217
            'RequestID' => $requestID ?? $this->generateRequestID(),
218
        ]);
219
    }
220
221
    /**
222
     * Generate a unique request ID.
223
     *
224
     * @return string
225
     */
226
    private function generateRequestID(): string
227
    {
228
        return uniqid('', true);
229
    }
230
}
231