This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Created by Graham Owens ([email protected]) |
||
4 | * Company: PartFire Ltd (www.partfire.co.uk) |
||
5 | * Console: Discovery |
||
6 | * |
||
7 | * User: gra |
||
8 | * Date: 20/01/17 |
||
9 | * Time: 09:52 |
||
10 | * Project: PartFire MangoPay Bundle |
||
11 | * File: HookHandleService.php |
||
12 | * |
||
13 | **/ |
||
14 | |||
15 | namespace PartFire\MangoPayBundle\Services; |
||
16 | |||
17 | use Composer\EventDispatcher\Event; |
||
18 | use Fruitful\FFConstants; |
||
19 | use PartFire\CommonBundle\Services\Output\CommonOutputInterface; |
||
20 | use PartFire\MangoPayBundle\Entity\Hook; |
||
0 ignored issues
–
show
|
|||
21 | use PartFire\MangoPayBundle\Entity\Repository\HookRepository; |
||
22 | use PartFire\MangoPayBundle\Entity\Repository\MangoPayRepositoryFactory; |
||
23 | use PartFire\MangoPayBundle\Event\MangoPayWebhookEvent; |
||
24 | use PartFire\MangoPayBundle\MangoPayConstants; |
||
25 | use PartFire\SlackBundle\Services\SlackService; |
||
26 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
||
27 | |||
28 | class HookHandleService |
||
29 | { |
||
30 | /** |
||
31 | * @var IdentityCheckFactoryRepository |
||
32 | */ |
||
33 | protected $mangoPayRepositoryFactory; |
||
34 | protected $slackService; |
||
35 | private $payIn; |
||
36 | private $payOut; |
||
37 | private $transfer; |
||
38 | private $kyc; |
||
39 | private $currentEnvironment; |
||
40 | |||
41 | const CHECK_COMPLETE = "check.completed"; |
||
42 | const REPORT_COMPLETE = "report.completed"; |
||
43 | |||
44 | |||
45 | public function __construct( |
||
46 | MangoPayRepositoryFactory $mangoPayRepositoryFactory, |
||
47 | SlackService $slackService, |
||
48 | EventDispatcherInterface $event, |
||
49 | PayIn $payIn, |
||
50 | PayOut $payOut, |
||
51 | Transfer $transfer, |
||
52 | Kyc $kyc, |
||
53 | $currentEnvironment |
||
54 | ) |
||
55 | { |
||
56 | $this->mangoPayRepositoryFactory = $mangoPayRepositoryFactory; |
||
57 | $this->slackService = $slackService; |
||
58 | $this->event = $event; |
||
0 ignored issues
–
show
The property
event does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
59 | $this->payIn = $payIn; |
||
60 | $this->payOut = $payOut; |
||
61 | $this->transfer = $transfer; |
||
62 | $this->kyc = $kyc; |
||
63 | $this->currentEnvironment = $currentEnvironment; |
||
64 | } |
||
65 | |||
66 | public function processRequest($getArray) |
||
67 | { |
||
68 | $formattedJson = json_encode($getArray); |
||
69 | $this->sendMessage( |
||
70 | "New Webhook received from MangoPay at " . date('l jS \of F Y h:i:s A') . "\n ```" . $formattedJson . "```", |
||
71 | ':leftwards_arrow_with_hook:' |
||
72 | ); |
||
73 | |||
74 | $hookQueueEntity = new Hook(); |
||
75 | $hookQueueEntity->setEventType($getArray[MangoPayConstants::HOOK_EVENT_TYPE]); |
||
76 | $hookQueueEntity->setResourceId($getArray[MangoPayConstants::HOOK_RESOURCE_ID]); |
||
77 | $hookQueueEntity->setDate($getArray[MangoPayConstants::HOOK_DATE]); |
||
78 | |||
79 | $hookQueueEntity->setRawHookData($formattedJson); |
||
80 | |||
81 | $this->mangoPayRepositoryFactory->saveAndGetEntity($hookQueueEntity); |
||
82 | |||
83 | return true; |
||
84 | } |
||
85 | |||
86 | public function processNewWebhooks(CommonOutputInterface $output) |
||
87 | { |
||
88 | $output->info(count($this->getAllNewWebhooks()) . " new hooks to check"); |
||
89 | |||
90 | foreach($this->getAllNewWebhooks() as $webHook) { |
||
91 | $output->infoid(" Processing hook ID " . $webHook->getResourceId() . " - Action Type = " . $webHook->getEventType()); |
||
92 | try { |
||
93 | $this->processWebhook($webHook, $output); |
||
94 | } catch (\Exception $e) { |
||
95 | $output->error($e->getMessage()); |
||
96 | } |
||
97 | } |
||
98 | } |
||
99 | |||
100 | private function processWebhook(Hook $hook, CommonOutputInterface $commonOutput) |
||
101 | { |
||
102 | $hook = $this->setWebhookInProgress($hook); |
||
103 | $commonOutput->infoid(" Webhook set to in progress"); |
||
104 | if (MangoPayConstants::isEventTypeOk($hook->getEventType())) { |
||
0 ignored issues
–
show
This
if statement is empty and can be removed.
This check looks for the bodies of These if (rand(1, 6) > 3) {
//print "Check failed";
} else {
print "Check succeeded";
}
could be turned into if (rand(1, 6) <= 3) {
print "Check succeeded";
}
This is much more concise to read. ![]() |
|||
105 | |||
106 | } else { |
||
107 | $errMsg = "Received webhook from MangoPay *" . $hook->getEventType() ."*, which is unknown. Firing event anyway \n ```" . json_encode($hook->getRawHookData()) . "```"; |
||
108 | $commonOutput->error($errMsg); |
||
109 | $this->sendErrorMessage( |
||
110 | $errMsg, |
||
111 | ':anguished:' |
||
112 | ); |
||
113 | } |
||
114 | |||
115 | $dtoResponse = $this->getDTOReponse($hook, $commonOutput); |
||
116 | |||
117 | if ($this->currentEnvironment != 'prod') { |
||
118 | $forcedTo = $this->getForcedTypeFromEventType($hook->getEventType()); |
||
119 | $commonOutput->highlight("We are in " . $this->currentEnvironment . " mode! - DTO came back as " . $dtoResponse->getStatus() . " but forcing to " . $forcedTo); |
||
120 | $dtoResponse->setStatus($forcedTo); |
||
121 | } |
||
122 | |||
123 | $hook->setDto($dtoResponse); |
||
124 | $hook = $this->mangoPayRepositoryFactory->saveAndGetEntity($hook); |
||
125 | |||
126 | $webhookEvent = new MangoPayWebhookEvent(); |
||
127 | $webhookEvent->setOutput($commonOutput); |
||
128 | $webhookEvent->setHook($hook); |
||
129 | $webhookEvent->setDto($dtoResponse); |
||
130 | |||
131 | $this->event->dispatch(MangoPayWebhookEvent::NAME, $webhookEvent); |
||
132 | $hook = $this->setWebhookToActioned($hook); |
||
133 | $commonOutput->info("Hook ID" . $hook->getId() . " regarding resourceId " . $hook->getResourceId() . " has finished"); |
||
134 | } |
||
135 | |||
136 | private function getForcedTypeFromEventType($eventType) |
||
137 | { |
||
138 | $split = explode("_", $eventType); |
||
139 | return end($split); |
||
140 | } |
||
141 | |||
142 | private function getDTOReponse(Hook $hook, CommonOutputInterface $commonOutput) |
||
143 | { |
||
144 | $dto = null; |
||
145 | $errorMsg = null; |
||
146 | |||
147 | if (MangoPayConstants::isEventTypeToDoWithPayInNormal($hook->getEventType())) { |
||
148 | $commonOutput->infoid(" Hook is to do with a Pay In Normal"); |
||
149 | $dto = $this->payIn->getPayIn($hook->getResourceId()); |
||
150 | } |
||
151 | |||
152 | if (MangoPayConstants::isEventTypeToDoWithPayOutNormal($hook->getEventType())) { |
||
153 | $commonOutput->infoid(" Hook is to do with a Pay Out Normal"); |
||
154 | $dto = $this->payOut->get($hook->getResourceId()); |
||
155 | } |
||
156 | |||
157 | if (MangoPayConstants::isEventTypeToDoWithTransferNormal($hook->getEventType())) { |
||
158 | $commonOutput->infoid(" Hook is to do with a Transfer Normal"); |
||
159 | $dto = $this->transfer->get($hook->getResourceId()); |
||
160 | } |
||
161 | |||
162 | if (MangoPayConstants::isEventTypeToDoWithPayInRefund($hook->getEventType())) { |
||
163 | $commonOutput->infoid(" Hook is to do with a Pay In Refund"); |
||
164 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
165 | } |
||
166 | |||
167 | if (MangoPayConstants::isEventTypeToDoWithPayOutRefund($hook->getEventType())) { |
||
168 | $commonOutput->infoid(" Hook is to do with a Pay Out Refund"); |
||
169 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
170 | } |
||
171 | |||
172 | if (MangoPayConstants::isEventTypeToDoWithTransferRefund($hook->getEventType())) { |
||
173 | $commonOutput->infoid(" Hook is to do with a Transfer Refund"); |
||
174 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
175 | } |
||
176 | |||
177 | if (MangoPayConstants::isEventTypeToDoWithPayInRepudiation($hook->getEventType())) { |
||
178 | $commonOutput->infoid(" Hook is to do with a Pay In Repudiation"); |
||
179 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
180 | } |
||
181 | |||
182 | if (MangoPayConstants::isEventTypeToDoWithKYC($hook->getEventType())) { |
||
183 | $commonOutput->infoid(" Hook is to do with a KYC"); |
||
184 | $dto = $this->kyc->getDocument($hook->getResourceId()); |
||
185 | } |
||
186 | |||
187 | if (MangoPayConstants::isEventTypeToDoWithDisputeDocument($hook->getEventType())) { |
||
188 | $commonOutput->infoid(" Hook is to do with a Dispute Document"); |
||
189 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
190 | } |
||
191 | |||
192 | if (MangoPayConstants::isEventTypeToDoWithDispute($hook->getEventType())) { |
||
193 | $commonOutput->infoid(" Hook is to do with a Dispute"); |
||
194 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
195 | } |
||
196 | |||
197 | if (MangoPayConstants::isEventTypeToDoWithTransferSettlement($hook->getEventType())) { |
||
198 | $commonOutput->infoid(" Hook is to do with a Transfer Settlement"); |
||
199 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
200 | } |
||
201 | |||
202 | if (MangoPayConstants::isEventTypeToDoWithMandate($hook->getEventType())) { |
||
203 | $commonOutput->infoid(" Hook is to do with a Mandate"); |
||
204 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
205 | } |
||
206 | |||
207 | if (MangoPayConstants::isEventTypeToDoWithPreauthorisation($hook->getEventType())) { |
||
208 | $commonOutput->infoid(" Hook is to do with a PreAuthorisation"); |
||
209 | $errorMsg = $hook->getEventType() . " NOT YET HANDLED. NEEDS CODING UP!"; |
||
210 | } |
||
211 | |||
212 | if (!is_null($errorMsg)) { |
||
213 | $this->sendMessage( |
||
214 | "Error, no code to action HookHandleService \n ```" . $errorMsg . "```", |
||
215 | ':leftwards_arrow_with_hook:' |
||
216 | ); |
||
217 | $commonOutput->error($errorMsg); |
||
218 | |||
219 | throw new \Exception("Inbound hook with event " . $hook->getEventType() . " not handled!"); |
||
220 | } else { |
||
221 | $commonOutput->infoid(" Hook returning with status " . $dto->getStatus()); |
||
222 | } |
||
223 | |||
224 | return $dto; |
||
225 | } |
||
226 | |||
227 | private function setWebhookInProgress(Hook $hook) : Hook |
||
228 | { |
||
229 | $hook->setStatus(MangoPayConstants::HOOK_IN_PROGRESS); |
||
230 | return $this->mangoPayRepositoryFactory->saveAndGetEntity($hook); |
||
231 | } |
||
232 | |||
233 | private function setWebhookToActioned(Hook $hook) : Hook |
||
234 | { |
||
235 | $hook->setStatus(MangoPayConstants::HOOK_ACTIONED); |
||
236 | return $this->mangoPayRepositoryFactory->saveAndGetEntity($hook); |
||
237 | } |
||
238 | |||
239 | private function getIdentityCheckReportByOnfidoReportId(OnfidoHookQueue $onfidoHookQueue) : ?IdentityCheckReport |
||
0 ignored issues
–
show
|
|||
240 | { |
||
241 | return $this->mangoPayRepositoryFactory->getIdentityCheckReport()->findOneByOnfidoReportId( |
||
242 | $onfidoHookQueue->getResourceId() |
||
243 | ); |
||
244 | } |
||
245 | |||
246 | private function getAllNewWebhooks() |
||
247 | { |
||
248 | return $this->getHookRepo()->findBy( |
||
249 | [ |
||
250 | 'status' => MangoPayConstants::HOOK_NEW |
||
251 | ] |
||
252 | ); |
||
253 | } |
||
254 | |||
255 | private function getHookRepo() : HookRepository |
||
256 | { |
||
257 | return $this->mangoPayRepositoryFactory->getHook(); |
||
258 | } |
||
259 | |||
260 | // Made public so tests pass |
||
261 | |||
262 | public function isValidOnfidoRequest($bodyJson) |
||
263 | { |
||
264 | if ($bodyJson instanceof \stdClass) { |
||
265 | |||
266 | if (!isset($bodyJson->payload->resource_type)) { |
||
267 | return false; |
||
268 | } |
||
269 | |||
270 | if (!isset($bodyJson->payload->action)) { |
||
271 | return false; |
||
272 | } |
||
273 | |||
274 | if (!isset($bodyJson->payload->object->id)) { |
||
275 | return false; |
||
276 | } |
||
277 | |||
278 | if (!isset($bodyJson->payload->object->href) || |
||
279 | !strstr($bodyJson->payload->object->href, 'api.onfido.com/v') === true |
||
280 | ) { |
||
281 | return false; |
||
282 | } |
||
283 | |||
284 | return true; |
||
285 | } |
||
286 | return false; |
||
287 | } |
||
288 | |||
289 | private function sendMessage(string $message, string $emoji) |
||
290 | { |
||
291 | $this->slackService->sendMessage($message, 'ff-mangopay-webhooks', $emoji); |
||
292 | } |
||
293 | |||
294 | private function sendErrorMessage(string $message, string $emoji) |
||
295 | { |
||
296 | $this->slackService->sendMessage($message, 'ff-error', $emoji); |
||
297 | } |
||
298 | |||
299 | } |
||
300 |
Let’s assume that you have a directory layout like this:
and let’s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: