Mpesa::processConfirmation()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 7
ccs 0
cts 5
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Samerior\MobileMoney\Mpesa\Repositories;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Facades\Log;
7
use Samerior\MobileMoney\Mpesa\Database\Entities\MpesaB2cResultParameter;
8
use Samerior\MobileMoney\Mpesa\Database\Entities\MpesaBulkPaymentRequest;
9
use Samerior\MobileMoney\Mpesa\Database\Entities\MpesaBulkPaymentResponse;
10
use Samerior\MobileMoney\Mpesa\Database\Entities\MpesaC2bCallback;
11
use Samerior\MobileMoney\Mpesa\Database\Entities\MpesaStkCallback;
12
use Samerior\MobileMoney\Mpesa\Database\Entities\MpesaStkRequest;
13
use Samerior\MobileMoney\Mpesa\Events\B2cPaymentFailedEvent;
14
use Samerior\MobileMoney\Mpesa\Events\B2cPaymentSuccessEvent;
15
use Samerior\MobileMoney\Mpesa\Events\C2bConfirmationEvent;
16
use Samerior\MobileMoney\Mpesa\Events\StkPushPaymentFailedEvent;
17
use Samerior\MobileMoney\Mpesa\Events\StkPushPaymentSuccessEvent;
18
use Gahlawat\Slack\Facade\Slack;
19
use Illuminate\Support\Facades\Auth;
20
21
/**
22
 * Class Mpesa
23
 * @package Samerior\MobileMoney\Repositories
24
 */
25
class Mpesa
26
{
27
    /**
28
     * @param string $json
29
     * @return $this|array|\Illuminate\Database\Eloquent\Model
30
     */
31
    public function processStkPushCallback($json)
32
    {
33
        $object = json_decode($json);
34
        $data = $object->stkCallback;
35
        $real_data = [
36
            'MerchantRequestID' => $data->MerchantRequestID,
37
            'CheckoutRequestID' => $data->CheckoutRequestID,
38
            'ResultCode' => $data->ResultCode,
39
            'ResultDesc' => $data->ResultDesc,
40
        ];
41
        if ($data->ResultCode == 0) {
42
            $_payload = $data->CallbackMetadata->Item;
43
            foreach ($_payload as $callback) {
44
                $real_data[$callback->Name] = @$callback->Value;
45
            }
46
            $callback = MpesaStkCallback::create($real_data);
47
        } else {
48
            $callback = MpesaStkCallback::create($real_data);
49
        }
50
        $this->fireStkEvent($callback, get_object_vars($data));
51
        return $callback;
52
    }
53
54
    /**
55
     * @param $response
56
     * @param array $body
57
     * @return MpesaBulkPaymentRequest|\Illuminate\Database\Eloquent\Model
58
     */
59
    public function saveB2cRequest($response, $body = [])
60
    {
61
        return MpesaBulkPaymentRequest::create([
62
            'conversation_id' => $response->ConversationID,
63
            'originator_conversation_id' => $response->OriginatorConversationID,
64
            'amount' => $body['Amount'],
65
            'phone' => $body['PartyB'],
66
            'remarks' => $body['Remarks'],
67
            'CommandID' => $body['CommandID'],
68
            'user_id' => Auth::id(),
69
        ]);
70
    }
71
72
    /**
73
     * @param string $json
74
     * @return $this|\Illuminate\Database\Eloquent\Model
75
     */
76
    public function processConfirmation($json)
77
    {
78
        $data = json_decode($json, true);
79
        $callback = MpesaC2bCallback::create($data);
80
        event(new C2bConfirmationEvent($callback, $data));
81
        return $callback;
82
    }
83
84
    /**
85
     * @return MpesaBulkPaymentResponse|\Illuminate\Database\Eloquent\Model
86
     */
87
    private function handleB2cResult()
88
    {
89
        $data = request('Result');
90
91
        //check if data is an array
92
        if (!is_array($data)) {
93
            $data->toArray();
94
        }
95
96
        $common = [
97
            'ResultType', 'ResultCode', 'ResultDesc', 'OriginatorConversationID', 'ConversationID', 'TransactionID'
98
        ];
99
        $seek = ['OriginatorConversationID' => $data['OriginatorConversationID']];
100
        /** @var MpesaBulkPaymentResponse $response */
101
        $response = null;
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
102
        if ($data['ResultCode'] !== 0) {
103
            $response = MpesaBulkPaymentResponse::updateOrCreate($seek, Arr::only($data, $common));
104
            event(new B2cPaymentFailedEvent($response, $data));
105
            return $response;
106
        }
107
        $resultParameter = $data['ResultParameters'];
108
109
        $data['ResultParameters'] = json_encode($resultParameter);
110
        $response = MpesaBulkPaymentResponse::updateOrCreate($seek, Arr::except($data, ['ReferenceData']));
111
        $this->saveResultParams($resultParameter, $response);
112
        event(new B2cPaymentSuccessEvent($response, $data));
113
        return $response;
114
    }
115
116
    private function saveResultParams(array $params, MpesaBulkPaymentResponse $response): \Illuminate\Database\Eloquent\Model
117
    {
118
        $params_payload = $params['ResultParameter'];
119
        $new_params = Arr::pluck($params_payload, 'Value', 'Key');
120
        return $response->data()->create($new_params);
121
    }
122
123
    /**
124
     * @param string|null $initiator
125
     * @return MpesaBulkPaymentResponse|void
126
     */
127
    public function handleResult($initiator = null)
128
    {
129
        if ($initiator === 'b2c') {
130
            return $this->handleB2cResult();
131
        }
132
        return;
133
    }
134
135
    /**
136
     * @param $title
137
     * @param bool $important
138
     */
139
    public function notification($title, $important = false): void
140
    {
141
        $slack = \config('samerior.mpesa.notifications.slack_web_hook');
142
        if (!$important && empty($slack) && \config('samerior.mpesa.notifications.only_important')) {
143
            return;
144
        }
145
        \config([
146
            'slack.incoming-webhook' => \config('samerior.mpesa.notifications.slack_web_hook'),
147
            'slack.default_username' => 'MPESA',
148
            'slack.default_emoji' => ':mailbox_with_mail:',]);
149
        Slack::send($title);
150
        Slack::send('```' . json_encode(request()->all(), JSON_PRETTY_PRINT) . '```');
151
    }
152
153
    /**
154
     * @return array
155
     */
156
    public function queryStkStatus(): array
157
    {
158
        /** @var MpesaStkRequest[] $stk */
159
        $stk = MpesaStkRequest::whereDoesntHave('response')->get();
160
        $success = $errors = [];
161
        foreach ($stk as $item) {
162
            try {
163
                $status = mpesa_stk_status($item->id);
164
                if (isset($status->errorMessage)) {
165
                    $errors[$item->CheckoutRequestID] = $status->errorMessage;
166
                    continue;
167
                }
168
                $attributes = [
169
                    'MerchantRequestID' => $status->MerchantRequestID,
170
                    'CheckoutRequestID' => $status->CheckoutRequestID,
171
                    'ResultCode' => $status->ResultCode,
172
                    'ResultDesc' => $status->ResultDesc,
173
                    'Amount' => $item->amount,
174
                ];
175
                $errors[$item->CheckoutRequestID] = $status->ResultDesc;
176
                $callback = MpesaStkCallback::create($attributes);
177
                $this->fireStkEvent($callback, get_object_vars($status));
178
            } catch (\Exception $e) {
179
                $errors[$item->CheckoutRequestID] = $e->getMessage();
180
            }
181
        }
182
        return ['successful' => $success, 'errors' => $errors];
183
    }
184
185
    /**
186
     * @param MpesaStkCallback $stkCallback
187
     * @param array $response
188
     * @return MpesaStkCallback
189
     */
190
    private function fireStkEvent(MpesaStkCallback $stkCallback, $response): MpesaStkCallback
191
    {
192
        if ($stkCallback->ResultCode == 0) {
193
            event(new StkPushPaymentSuccessEvent($stkCallback, $response));
194
        } else {
195
            event(new StkPushPaymentFailedEvent($stkCallback, $response));
196
        }
197
        return $stkCallback;
198
    }
199
}
200