@artilingo/artiframe-cli 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/core-stubs/bin/SystemMethod.php +600 -521
  2. package/core-stubs/bin/ViewMethod.php +591 -393
  3. package/core-stubs/docs/de.html +4347 -4390
  4. package/core-stubs/docs/en.html +4347 -4389
  5. package/core-stubs/docs/es.html +4347 -4390
  6. package/core-stubs/docs/fr.html +4347 -4389
  7. package/core-stubs/docs/tr.html +138 -109
  8. package/package.json +1 -1
  9. package/src/App.php +8 -0
  10. package/src/Commands/AddCommand.php +1 -1
  11. package/src/Commands/ListCommand.php +2 -1
  12. package/src/Commands/MakeApiCommand.php +1 -1
  13. package/src/Commands/MakeClassCommand.php +1 -1
  14. package/src/Commands/MakeViewCommand.php +1 -1
  15. package/src/Commands/NewProjectCommand.php +37 -25
  16. package/src/Commands/RemoveCommand.php +21 -10
  17. package/src/Commands/ServeCommand.php +29 -9
  18. package/src/Commands/TableCommand.php +2 -1
  19. package/src/Commands/UpgradeCommand.php +209 -0
  20. package/src/Commands/VersionCommand.php +2 -1
  21. package/src/Lang/de.php +7 -1
  22. package/src/Lang/en.php +6 -0
  23. package/src/Lang/es.php +7 -1
  24. package/src/Lang/fr.php +6 -0
  25. package/src/Lang/tr.php +7 -1
  26. package/src/Services/Safeguard.php +25 -0
  27. package/stubs/service/image.stub +334 -334
  28. package/stubs/service/iyzico.stub +637 -637
  29. package/stubs/service/jwt.stub +312 -312
  30. package/stubs/service/phpmailer.stub +143 -143
  31. package/stubs/service/pusher.stub +232 -232
  32. package/stubs/service/qrcode.stub +169 -169
  33. package/stubs/service/redis.stub +361 -361
  34. package/stubs/service/s3.stub +377 -377
  35. package/stubs/service/sentry.stub +76 -106
  36. package/stubs/service/stripe.stub +526 -526
  37. package/stubs/service/twilio.stub +361 -361
  38. package/core-stubs/app/R2Manager.php +0 -130
@@ -1,637 +1,637 @@
1
- <?php
2
-
3
- namespace Service;
4
-
5
- /**
6
- * Iyzico Payment Service
7
- *
8
- * Provides a clean wrapper around the iyzipay-php SDK for payment processing,
9
- * 3D Secure flows, refunds, cancellations, card vault, and marketplace sub-merchants.
10
- *
11
- * Required environment variables:
12
- * IYZICO_API_KEY — Your iyzico API key
13
- * IYZICO_SECRET_KEY — Your iyzico secret key
14
- * IYZICO_BASE_URL — API base URL (https://sandbox-api.iyzipay.com or https://api.iyzipay.com)
15
- *
16
- * @package Service
17
- */
18
- class Iyzico
19
- {
20
- /**
21
- * Iyzipay connection options.
22
- *
23
- * @var \Iyzipay\Options
24
- */
25
- private \Iyzipay\Options $options;
26
-
27
- /**
28
- * Create a new Iyzico service instance.
29
- *
30
- * Reads API credentials and base URL from $_ENV and builds
31
- * the \Iyzipay\Options object used by every SDK call.
32
- */
33
- public function __construct()
34
- {
35
- $this->options = new \Iyzipay\Options();
36
- $this->options->setApiKey($_ENV['IYZICO_API_KEY']);
37
- $this->options->setSecretKey($_ENV['IYZICO_SECRET_KEY']);
38
- $this->options->setBaseUrl($_ENV['IYZICO_BASE_URL']);
39
- }
40
-
41
- /**
42
- * Process a single (non-3D) payment.
43
- *
44
- * @param array $data {
45
- * @type float $price Base price
46
- * @type float $paidPrice Final charged price (including installment cost)
47
- * @type string $currency ISO currency code (default: TRY)
48
- * @type int $installment Number of installments (default: 1)
49
- * @type array $card {
50
- * @type string $holder Card holder full name
51
- * @type string $number Card number
52
- * @type string $month Expiry month (2 digits)
53
- * @type string $year Expiry year (4 digits)
54
- * @type string $cvc CVC / CVV code
55
- * }
56
- * @type array $buyer {
57
- * @type string $id Merchant-side buyer ID
58
- * @type string $name First name
59
- * @type string $surname Last name
60
- * @type string $email E-mail address
61
- * @type string $phone Phone number
62
- * @type string $ip IP address of buyer
63
- * @type string $city City
64
- * @type string $country Country
65
- * @type string $address Full address line
66
- * @type string $zipCode ZIP / postal code
67
- * }
68
- * @type array $items Array of basket items, each having name, price, category
69
- * }
70
- * @return array Standardised response with status, message, and data keys
71
- */
72
- public function pay(array $data): array
73
- {
74
- try {
75
- $request = new \Iyzipay\Request\CreatePaymentRequest();
76
- $request->setLocale(\Iyzipay\Model\Locale::TR);
77
- $request->setConversationId(uniqid('pay_'));
78
- $request->setPrice($data['price']);
79
- $request->setPaidPrice($data['paidPrice']);
80
- $request->setCurrency($data['currency'] ?? \Iyzipay\Model\Currency::TL);
81
- $request->setInstallment($data['installment'] ?? 1);
82
- $request->setPaymentChannel(\Iyzipay\Model\PaymentChannel::WEB);
83
- $request->setPaymentGroup(\Iyzipay\Model\PaymentGroup::PRODUCT);
84
-
85
- // Payment card
86
- $card = new \Iyzipay\Model\PaymentCard();
87
- $card->setCardHolderName($data['card']['holder']);
88
- $card->setCardNumber($data['card']['number']);
89
- $card->setExpireMonth($data['card']['month']);
90
- $card->setExpireYear($data['card']['year']);
91
- $card->setCvc($data['card']['cvc']);
92
- $card->setRegisterCard(0);
93
- $request->setPaymentCard($card);
94
-
95
- // Buyer
96
- $buyer = new \Iyzipay\Model\Buyer();
97
- $buyer->setId($data['buyer']['id']);
98
- $buyer->setName($data['buyer']['name']);
99
- $buyer->setSurname($data['buyer']['surname']);
100
- $buyer->setEmail($data['buyer']['email']);
101
- $buyer->setGsmNumber($data['buyer']['phone']);
102
- $buyer->setIp($data['buyer']['ip']);
103
- $buyer->setCity($data['buyer']['city']);
104
- $buyer->setCountry($data['buyer']['country']);
105
- $buyer->setRegistrationAddress($data['buyer']['address']);
106
- $buyer->setZipCode($data['buyer']['zipCode']);
107
- $buyer->setIdentityNumber('00000000000');
108
- $request->setBuyer($buyer);
109
-
110
- // Shipping & billing address (use buyer address for both)
111
- $address = new \Iyzipay\Model\Address();
112
- $address->setContactName($data['buyer']['name'] . ' ' . $data['buyer']['surname']);
113
- $address->setCity($data['buyer']['city']);
114
- $address->setCountry($data['buyer']['country']);
115
- $address->setAddress($data['buyer']['address']);
116
- $address->setZipCode($data['buyer']['zipCode']);
117
- $request->setShippingAddress($address);
118
- $request->setBillingAddress($address);
119
-
120
- // Basket items
121
- $basketItems = [];
122
- foreach ($data['items'] as $index => $item) {
123
- $basketItem = new \Iyzipay\Model\BasketItem();
124
- $basketItem->setId('ITEM_' . ($index + 1));
125
- $basketItem->setName($item['name']);
126
- $basketItem->setCategory1($item['category'] ?? 'Default');
127
- $basketItem->setItemType(\Iyzipay\Model\BasketItemType::PHYSICAL);
128
- $basketItem->setPrice($item['price']);
129
- $basketItems[] = $basketItem;
130
- }
131
- $request->setBasketItems($basketItems);
132
-
133
- $payment = \Iyzipay\Model\Payment::create($request, $this->options);
134
-
135
- if ($payment->getStatus() === 'success') {
136
- return [
137
- 'status' => 'success',
138
- 'message' => 'Payment processed successfully.',
139
- 'data' => [
140
- 'paymentId' => $payment->getPaymentId(),
141
- 'price' => $payment->getPrice(),
142
- 'paidPrice' => $payment->getPaidPrice(),
143
- 'currency' => $payment->getCurrency(),
144
- 'installment' => $payment->getInstallment(),
145
- 'paymentTransactionId' => $payment->getPaymentItems()[0]->getPaymentTransactionId() ?? null,
146
- 'fraudStatus' => $payment->getFraudStatus(),
147
- ],
148
- ];
149
- }
150
-
151
- return [
152
- 'status' => 'error',
153
- 'message' => $payment->getErrorMessage() ?? 'Payment failed.',
154
- 'data' => ['errorCode' => $payment->getErrorCode()],
155
- ];
156
- } catch (\Exception $e) {
157
- return [
158
- 'status' => 'error',
159
- 'message' => $e->getMessage(),
160
- 'data' => [],
161
- ];
162
- }
163
- }
164
-
165
- /**
166
- * Initialise a 3D Secure payment flow.
167
- *
168
- * Returns an HTML snippet that must be rendered in the buyer's browser
169
- * to redirect them to the bank's 3D Secure verification page.
170
- *
171
- * @param array $data Same structure as pay() with an additional `callbackUrl` key
172
- * @return array Response containing threeDSHtmlContent on success
173
- */
174
- public function threeDSecureInit(array $data): array
175
- {
176
- try {
177
- $request = new \Iyzipay\Request\CreatePaymentRequest();
178
- $request->setLocale(\Iyzipay\Model\Locale::TR);
179
- $request->setConversationId(uniqid('3ds_'));
180
- $request->setPrice($data['price']);
181
- $request->setPaidPrice($data['paidPrice']);
182
- $request->setCurrency($data['currency'] ?? \Iyzipay\Model\Currency::TL);
183
- $request->setInstallment($data['installment'] ?? 1);
184
- $request->setPaymentChannel(\Iyzipay\Model\PaymentChannel::WEB);
185
- $request->setPaymentGroup(\Iyzipay\Model\PaymentGroup::PRODUCT);
186
- $request->setCallbackUrl($data['callbackUrl']);
187
-
188
- // Payment card
189
- $card = new \Iyzipay\Model\PaymentCard();
190
- $card->setCardHolderName($data['card']['holder']);
191
- $card->setCardNumber($data['card']['number']);
192
- $card->setExpireMonth($data['card']['month']);
193
- $card->setExpireYear($data['card']['year']);
194
- $card->setCvc($data['card']['cvc']);
195
- $card->setRegisterCard(0);
196
- $request->setPaymentCard($card);
197
-
198
- // Buyer
199
- $buyer = new \Iyzipay\Model\Buyer();
200
- $buyer->setId($data['buyer']['id']);
201
- $buyer->setName($data['buyer']['name']);
202
- $buyer->setSurname($data['buyer']['surname']);
203
- $buyer->setEmail($data['buyer']['email']);
204
- $buyer->setGsmNumber($data['buyer']['phone']);
205
- $buyer->setIp($data['buyer']['ip']);
206
- $buyer->setCity($data['buyer']['city']);
207
- $buyer->setCountry($data['buyer']['country']);
208
- $buyer->setRegistrationAddress($data['buyer']['address']);
209
- $buyer->setZipCode($data['buyer']['zipCode']);
210
- $buyer->setIdentityNumber('00000000000');
211
- $request->setBuyer($buyer);
212
-
213
- // Address
214
- $address = new \Iyzipay\Model\Address();
215
- $address->setContactName($data['buyer']['name'] . ' ' . $data['buyer']['surname']);
216
- $address->setCity($data['buyer']['city']);
217
- $address->setCountry($data['buyer']['country']);
218
- $address->setAddress($data['buyer']['address']);
219
- $address->setZipCode($data['buyer']['zipCode']);
220
- $request->setShippingAddress($address);
221
- $request->setBillingAddress($address);
222
-
223
- // Basket items
224
- $basketItems = [];
225
- foreach ($data['items'] as $index => $item) {
226
- $basketItem = new \Iyzipay\Model\BasketItem();
227
- $basketItem->setId('ITEM_' . ($index + 1));
228
- $basketItem->setName($item['name']);
229
- $basketItem->setCategory1($item['category'] ?? 'Default');
230
- $basketItem->setItemType(\Iyzipay\Model\BasketItemType::PHYSICAL);
231
- $basketItem->setPrice($item['price']);
232
- $basketItems[] = $basketItem;
233
- }
234
- $request->setBasketItems($basketItems);
235
-
236
- $threedsInit = \Iyzipay\Model\ThreedsInitialize::create($request, $this->options);
237
-
238
- if ($threedsInit->getStatus() === 'success') {
239
- return [
240
- 'status' => 'success',
241
- 'message' => '3D Secure initialisation successful.',
242
- 'data' => [
243
- 'threeDSHtmlContent' => $threedsInit->getHtmlContent(),
244
- ],
245
- ];
246
- }
247
-
248
- return [
249
- 'status' => 'error',
250
- 'message' => $threedsInit->getErrorMessage() ?? '3D Secure initialisation failed.',
251
- 'data' => ['errorCode' => $threedsInit->getErrorCode()],
252
- ];
253
- } catch (\Exception $e) {
254
- return [
255
- 'status' => 'error',
256
- 'message' => $e->getMessage(),
257
- 'data' => [],
258
- ];
259
- }
260
- }
261
-
262
- /**
263
- * Complete a 3D Secure payment after bank verification callback.
264
- *
265
- * Call this from your callback URL handler with the paymentId received
266
- * from the bank's POST response.
267
- *
268
- * @param array $data {
269
- * @type string $paymentId The payment ID returned by the bank callback
270
- * }
271
- * @return array Standardised response
272
- */
273
- public function threeDSecureComplete(array $data): array
274
- {
275
- try {
276
- $request = new \Iyzipay\Request\CreateThreedsPaymentRequest();
277
- $request->setLocale(\Iyzipay\Model\Locale::TR);
278
- $request->setConversationId(uniqid('3ds_complete_'));
279
- $request->setPaymentId($data['paymentId']);
280
-
281
- $threedsPayment = \Iyzipay\Model\ThreedsPayment::create($request, $this->options);
282
-
283
- if ($threedsPayment->getStatus() === 'success') {
284
- return [
285
- 'status' => 'success',
286
- 'message' => '3D Secure payment completed successfully.',
287
- 'data' => [
288
- 'paymentId' => $threedsPayment->getPaymentId(),
289
- 'price' => $threedsPayment->getPrice(),
290
- 'paidPrice' => $threedsPayment->getPaidPrice(),
291
- 'currency' => $threedsPayment->getCurrency(),
292
- 'fraudStatus' => $threedsPayment->getFraudStatus(),
293
- ],
294
- ];
295
- }
296
-
297
- return [
298
- 'status' => 'error',
299
- 'message' => $threedsPayment->getErrorMessage() ?? '3D Secure completion failed.',
300
- 'data' => ['errorCode' => $threedsPayment->getErrorCode()],
301
- ];
302
- } catch (\Exception $e) {
303
- return [
304
- 'status' => 'error',
305
- 'message' => $e->getMessage(),
306
- 'data' => [],
307
- ];
308
- }
309
- }
310
-
311
- /**
312
- * Refund a specific payment transaction.
313
- *
314
- * @param string $paymentTransactionId The transaction ID to refund (from basket item)
315
- * @param float $price Amount to refund
316
- * @return array Standardised response
317
- */
318
- public function refund(string $paymentTransactionId, float $price): array
319
- {
320
- try {
321
- $request = new \Iyzipay\Request\CreateRefundRequest();
322
- $request->setLocale(\Iyzipay\Model\Locale::TR);
323
- $request->setConversationId(uniqid('refund_'));
324
- $request->setPaymentTransactionId($paymentTransactionId);
325
- $request->setPrice($price);
326
- $request->setCurrency(\Iyzipay\Model\Currency::TL);
327
- $request->setIp('127.0.0.1');
328
-
329
- $refund = \Iyzipay\Model\Refund::create($request, $this->options);
330
-
331
- if ($refund->getStatus() === 'success') {
332
- return [
333
- 'status' => 'success',
334
- 'message' => 'Refund processed successfully.',
335
- 'data' => [
336
- 'paymentId' => $refund->getPaymentId(),
337
- 'paymentTransactionId' => $refund->getPaymentTransactionId(),
338
- 'price' => $refund->getPrice(),
339
- ],
340
- ];
341
- }
342
-
343
- return [
344
- 'status' => 'error',
345
- 'message' => $refund->getErrorMessage() ?? 'Refund failed.',
346
- 'data' => ['errorCode' => $refund->getErrorCode()],
347
- ];
348
- } catch (\Exception $e) {
349
- return [
350
- 'status' => 'error',
351
- 'message' => $e->getMessage(),
352
- 'data' => [],
353
- ];
354
- }
355
- }
356
-
357
- /**
358
- * Cancel an entire payment.
359
- *
360
- * @param string $paymentId The payment ID to cancel
361
- * @return array Standardised response
362
- */
363
- public function cancel(string $paymentId): array
364
- {
365
- try {
366
- $request = new \Iyzipay\Request\CreateCancelRequest();
367
- $request->setLocale(\Iyzipay\Model\Locale::TR);
368
- $request->setConversationId(uniqid('cancel_'));
369
- $request->setPaymentId($paymentId);
370
- $request->setIp('127.0.0.1');
371
-
372
- $cancel = \Iyzipay\Model\Cancel::create($request, $this->options);
373
-
374
- if ($cancel->getStatus() === 'success') {
375
- return [
376
- 'status' => 'success',
377
- 'message' => 'Payment cancelled successfully.',
378
- 'data' => [
379
- 'paymentId' => $cancel->getPaymentId(),
380
- 'price' => $cancel->getPrice(),
381
- 'currency' => $cancel->getCurrency(),
382
- ],
383
- ];
384
- }
385
-
386
- return [
387
- 'status' => 'error',
388
- 'message' => $cancel->getErrorMessage() ?? 'Cancellation failed.',
389
- 'data' => ['errorCode' => $cancel->getErrorCode()],
390
- ];
391
- } catch (\Exception $e) {
392
- return [
393
- 'status' => 'error',
394
- 'message' => $e->getMessage(),
395
- 'data' => [],
396
- ];
397
- }
398
- }
399
-
400
- /**
401
- * Save a card to the iyzico card vault for future payments.
402
- *
403
- * @param array $cardData {
404
- * @type string $holder Card holder full name
405
- * @type string $number Card number
406
- * @type string $month Expiry month
407
- * @type string $year Expiry year
408
- * @type string $alias A user-friendly card alias (e.g. "My Visa")
409
- * }
410
- * @param string $email Buyer e-mail (used as external identifier)
411
- * @return array Standardised response with cardUserKey and cardToken
412
- */
413
- public function saveCard(array $cardData, string $email): array
414
- {
415
- try {
416
- $request = new \Iyzipay\Request\CreateCardRequest();
417
- $request->setLocale(\Iyzipay\Model\Locale::TR);
418
- $request->setConversationId(uniqid('card_'));
419
- $request->setEmail($email);
420
- $request->setExternalId(md5($email));
421
-
422
- $cardInfo = new \Iyzipay\Model\CardInformation();
423
- $cardInfo->setCardAlias($cardData['alias'] ?? 'Default Card');
424
- $cardInfo->setCardHolderName($cardData['holder']);
425
- $cardInfo->setCardNumber($cardData['number']);
426
- $cardInfo->setExpireMonth($cardData['month']);
427
- $cardInfo->setExpireYear($cardData['year']);
428
- $request->setCard($cardInfo);
429
-
430
- $card = \Iyzipay\Model\Card::create($request, $this->options);
431
-
432
- if ($card->getStatus() === 'success') {
433
- return [
434
- 'status' => 'success',
435
- 'message' => 'Card saved successfully.',
436
- 'data' => [
437
- 'cardUserKey' => $card->getCardUserKey(),
438
- 'cardToken' => $card->getCardToken(),
439
- 'cardAlias' => $card->getCardAlias(),
440
- 'lastFour' => $card->getLastFourDigits(),
441
- 'cardType' => $card->getCardType(),
442
- ],
443
- ];
444
- }
445
-
446
- return [
447
- 'status' => 'error',
448
- 'message' => $card->getErrorMessage() ?? 'Card save failed.',
449
- 'data' => ['errorCode' => $card->getErrorCode()],
450
- ];
451
- } catch (\Exception $e) {
452
- return [
453
- 'status' => 'error',
454
- 'message' => $e->getMessage(),
455
- 'data' => [],
456
- ];
457
- }
458
- }
459
-
460
- /**
461
- * Retrieve all saved cards for a given card user key.
462
- *
463
- * @param string $cardUserKey The user key returned when a card was first saved
464
- * @return array Standardised response with array of cards
465
- */
466
- public function listCards(string $cardUserKey): array
467
- {
468
- try {
469
- $request = new \Iyzipay\Request\RetrieveCardListRequest();
470
- $request->setLocale(\Iyzipay\Model\Locale::TR);
471
- $request->setConversationId(uniqid('cards_'));
472
- $request->setCardUserKey($cardUserKey);
473
-
474
- $cardList = \Iyzipay\Model\CardList::retrieve($request, $this->options);
475
-
476
- if ($cardList->getStatus() === 'success') {
477
- $cards = [];
478
- foreach ($cardList->getCardDetails() as $card) {
479
- $cards[] = [
480
- 'cardToken' => $card->getCardToken(),
481
- 'cardAlias' => $card->getCardAlias(),
482
- 'binNumber' => $card->getBinNumber(),
483
- 'lastFourDigits' => $card->getLastFourDigits(),
484
- 'cardType' => $card->getCardType(),
485
- 'cardAssociation'=> $card->getCardAssociation(),
486
- 'cardFamily' => $card->getCardFamily(),
487
- ];
488
- }
489
-
490
- return [
491
- 'status' => 'success',
492
- 'message' => 'Cards retrieved successfully.',
493
- 'data' => [
494
- 'cardUserKey' => $cardList->getCardUserKey(),
495
- 'cards' => $cards,
496
- ],
497
- ];
498
- }
499
-
500
- return [
501
- 'status' => 'error',
502
- 'message' => $cardList->getErrorMessage() ?? 'Could not retrieve cards.',
503
- 'data' => ['errorCode' => $cardList->getErrorCode()],
504
- ];
505
- } catch (\Exception $e) {
506
- return [
507
- 'status' => 'error',
508
- 'message' => $e->getMessage(),
509
- 'data' => [],
510
- ];
511
- }
512
- }
513
-
514
- /**
515
- * Query the status of an existing payment.
516
- *
517
- * @param string $paymentId The payment ID to query
518
- * @return array Standardised response with payment details
519
- */
520
- public function checkPayment(string $paymentId): array
521
- {
522
- try {
523
- $request = new \Iyzipay\Request\RetrievePaymentRequest();
524
- $request->setLocale(\Iyzipay\Model\Locale::TR);
525
- $request->setConversationId(uniqid('check_'));
526
- $request->setPaymentId($paymentId);
527
-
528
- $payment = \Iyzipay\Model\Payment::retrieve($request, $this->options);
529
-
530
- if ($payment->getStatus() === 'success') {
531
- $items = [];
532
- if ($payment->getPaymentItems()) {
533
- foreach ($payment->getPaymentItems() as $item) {
534
- $items[] = [
535
- 'itemId' => $item->getItemId(),
536
- 'paymentTransactionId' => $item->getPaymentTransactionId(),
537
- 'price' => $item->getPrice(),
538
- 'paidPrice' => $item->getPaidPrice(),
539
- 'transactionStatus' => $item->getTransactionStatus(),
540
- ];
541
- }
542
- }
543
-
544
- return [
545
- 'status' => 'success',
546
- 'message' => 'Payment details retrieved.',
547
- 'data' => [
548
- 'paymentId' => $payment->getPaymentId(),
549
- 'price' => $payment->getPrice(),
550
- 'paidPrice' => $payment->getPaidPrice(),
551
- 'currency' => $payment->getCurrency(),
552
- 'installment' => $payment->getInstallment(),
553
- 'paymentStatus'=> $payment->getPaymentStatus(),
554
- 'fraudStatus' => $payment->getFraudStatus(),
555
- 'cardType' => $payment->getCardType(),
556
- 'lastFourDigits' => $payment->getLastFourDigits(),
557
- 'items' => $items,
558
- ],
559
- ];
560
- }
561
-
562
- return [
563
- 'status' => 'error',
564
- 'message' => $payment->getErrorMessage() ?? 'Could not retrieve payment.',
565
- 'data' => ['errorCode' => $payment->getErrorCode()],
566
- ];
567
- } catch (\Exception $e) {
568
- return [
569
- 'status' => 'error',
570
- 'message' => $e->getMessage(),
571
- 'data' => [],
572
- ];
573
- }
574
- }
575
-
576
- /**
577
- * Register a new sub-merchant for marketplace payments.
578
- *
579
- * @param array $data {
580
- * @type string $name Sub-merchant legal name
581
- * @type string $type PERSONAL_COMPANY | PRIVATE_COMPANY | LIMITED_OR_JOINT_STOCK_COMPANY
582
- * @type string $taxOffice Tax office name
583
- * @type string $taxNumber Tax / identity number
584
- * @type string $legalCompanyName Legal company title
585
- * @type string $email Contact e-mail
586
- * @type string $phone Contact phone (GSM)
587
- * @type string $address Registered address
588
- * @type string $iban IBAN for payouts
589
- * @type string $currency Currency code (default: TRY)
590
- * @type string $subMerchantExternalId Unique external identifier
591
- * }
592
- * @return array Standardised response with subMerchantKey
593
- */
594
- public function createSubMerchant(array $data): array
595
- {
596
- try {
597
- $request = new \Iyzipay\Request\CreateSubMerchantRequest();
598
- $request->setLocale(\Iyzipay\Model\Locale::TR);
599
- $request->setConversationId(uniqid('sub_'));
600
- $request->setSubMerchantExternalId($data['subMerchantExternalId'] ?? uniqid('sm_'));
601
- $request->setSubMerchantType($data['type'] ?? \Iyzipay\Model\SubMerchantType::LIMITED_OR_JOINT_STOCK_COMPANY);
602
- $request->setAddress($data['address']);
603
- $request->setTaxOffice($data['taxOffice'] ?? '');
604
- $request->setLegalCompanyTitle($data['legalCompanyName'] ?? $data['name']);
605
- $request->setEmail($data['email']);
606
- $request->setGsmNumber($data['phone']);
607
- $request->setName($data['name']);
608
- $request->setIban($data['iban']);
609
- $request->setIdentityNumber($data['taxNumber'] ?? '00000000000');
610
- $request->setCurrency($data['currency'] ?? \Iyzipay\Model\Currency::TL);
611
-
612
- $subMerchant = \Iyzipay\Model\SubMerchant::create($request, $this->options);
613
-
614
- if ($subMerchant->getStatus() === 'success') {
615
- return [
616
- 'status' => 'success',
617
- 'message' => 'Sub-merchant created successfully.',
618
- 'data' => [
619
- 'subMerchantKey' => $subMerchant->getSubMerchantKey(),
620
- ],
621
- ];
622
- }
623
-
624
- return [
625
- 'status' => 'error',
626
- 'message' => $subMerchant->getErrorMessage() ?? 'Sub-merchant creation failed.',
627
- 'data' => ['errorCode' => $subMerchant->getErrorCode()],
628
- ];
629
- } catch (\Exception $e) {
630
- return [
631
- 'status' => 'error',
632
- 'message' => $e->getMessage(),
633
- 'data' => [],
634
- ];
635
- }
636
- }
637
- }
1
+ <?php
2
+
3
+ namespace Src\Service;
4
+
5
+ /**
6
+ * Iyzico Payment Service
7
+ *
8
+ * Provides a clean wrapper around the iyzipay-php SDK for payment processing,
9
+ * 3D Secure flows, refunds, cancellations, card vault, and marketplace sub-merchants.
10
+ *
11
+ * Required environment variables:
12
+ * IYZICO_API_KEY — Your iyzico API key
13
+ * IYZICO_SECRET_KEY — Your iyzico secret key
14
+ * IYZICO_BASE_URL — API base URL (https://sandbox-api.iyzipay.com or https://api.iyzipay.com)
15
+ *
16
+ * @package Service
17
+ */
18
+ class Iyzico
19
+ {
20
+ /**
21
+ * Iyzipay connection options.
22
+ *
23
+ * @var \Iyzipay\Options
24
+ */
25
+ private \Iyzipay\Options $options;
26
+
27
+ /**
28
+ * Create a new Iyzico service instance.
29
+ *
30
+ * Reads API credentials and base URL from $_ENV and builds
31
+ * the \Iyzipay\Options object used by every SDK call.
32
+ */
33
+ public function __construct()
34
+ {
35
+ $this->options = new \Iyzipay\Options();
36
+ $this->options->setApiKey($_ENV['IYZICO_API_KEY']);
37
+ $this->options->setSecretKey($_ENV['IYZICO_SECRET_KEY']);
38
+ $this->options->setBaseUrl($_ENV['IYZICO_BASE_URL']);
39
+ }
40
+
41
+ /**
42
+ * Process a single (non-3D) payment.
43
+ *
44
+ * @param array $data {
45
+ * @type float $price Base price
46
+ * @type float $paidPrice Final charged price (including installment cost)
47
+ * @type string $currency ISO currency code (default: TRY)
48
+ * @type int $installment Number of installments (default: 1)
49
+ * @type array $card {
50
+ * @type string $holder Card holder full name
51
+ * @type string $number Card number
52
+ * @type string $month Expiry month (2 digits)
53
+ * @type string $year Expiry year (4 digits)
54
+ * @type string $cvc CVC / CVV code
55
+ * }
56
+ * @type array $buyer {
57
+ * @type string $id Merchant-side buyer ID
58
+ * @type string $name First name
59
+ * @type string $surname Last name
60
+ * @type string $email E-mail address
61
+ * @type string $phone Phone number
62
+ * @type string $ip IP address of buyer
63
+ * @type string $city City
64
+ * @type string $country Country
65
+ * @type string $address Full address line
66
+ * @type string $zipCode ZIP / postal code
67
+ * }
68
+ * @type array $items Array of basket items, each having name, price, category
69
+ * }
70
+ * @return array Standardised response with status, message, and data keys
71
+ */
72
+ public function pay(array $data): array
73
+ {
74
+ try {
75
+ $request = new \Iyzipay\Request\CreatePaymentRequest();
76
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
77
+ $request->setConversationId(uniqid('pay_'));
78
+ $request->setPrice($data['price']);
79
+ $request->setPaidPrice($data['paidPrice']);
80
+ $request->setCurrency($data['currency'] ?? \Iyzipay\Model\Currency::TL);
81
+ $request->setInstallment($data['installment'] ?? 1);
82
+ $request->setPaymentChannel(\Iyzipay\Model\PaymentChannel::WEB);
83
+ $request->setPaymentGroup(\Iyzipay\Model\PaymentGroup::PRODUCT);
84
+
85
+ // Payment card
86
+ $card = new \Iyzipay\Model\PaymentCard();
87
+ $card->setCardHolderName($data['card']['holder']);
88
+ $card->setCardNumber($data['card']['number']);
89
+ $card->setExpireMonth($data['card']['month']);
90
+ $card->setExpireYear($data['card']['year']);
91
+ $card->setCvc($data['card']['cvc']);
92
+ $card->setRegisterCard(0);
93
+ $request->setPaymentCard($card);
94
+
95
+ // Buyer
96
+ $buyer = new \Iyzipay\Model\Buyer();
97
+ $buyer->setId($data['buyer']['id']);
98
+ $buyer->setName($data['buyer']['name']);
99
+ $buyer->setSurname($data['buyer']['surname']);
100
+ $buyer->setEmail($data['buyer']['email']);
101
+ $buyer->setGsmNumber($data['buyer']['phone']);
102
+ $buyer->setIp($data['buyer']['ip']);
103
+ $buyer->setCity($data['buyer']['city']);
104
+ $buyer->setCountry($data['buyer']['country']);
105
+ $buyer->setRegistrationAddress($data['buyer']['address']);
106
+ $buyer->setZipCode($data['buyer']['zipCode']);
107
+ $buyer->setIdentityNumber('00000000000');
108
+ $request->setBuyer($buyer);
109
+
110
+ // Shipping & billing address (use buyer address for both)
111
+ $address = new \Iyzipay\Model\Address();
112
+ $address->setContactName($data['buyer']['name'] . ' ' . $data['buyer']['surname']);
113
+ $address->setCity($data['buyer']['city']);
114
+ $address->setCountry($data['buyer']['country']);
115
+ $address->setAddress($data['buyer']['address']);
116
+ $address->setZipCode($data['buyer']['zipCode']);
117
+ $request->setShippingAddress($address);
118
+ $request->setBillingAddress($address);
119
+
120
+ // Basket items
121
+ $basketItems = [];
122
+ foreach ($data['items'] as $index => $item) {
123
+ $basketItem = new \Iyzipay\Model\BasketItem();
124
+ $basketItem->setId('ITEM_' . ($index + 1));
125
+ $basketItem->setName($item['name']);
126
+ $basketItem->setCategory1($item['category'] ?? 'Default');
127
+ $basketItem->setItemType(\Iyzipay\Model\BasketItemType::PHYSICAL);
128
+ $basketItem->setPrice($item['price']);
129
+ $basketItems[] = $basketItem;
130
+ }
131
+ $request->setBasketItems($basketItems);
132
+
133
+ $payment = \Iyzipay\Model\Payment::create($request, $this->options);
134
+
135
+ if ($payment->getStatus() === 'success') {
136
+ return [
137
+ 'status' => 'success',
138
+ 'message' => 'Payment processed successfully.',
139
+ 'data' => [
140
+ 'paymentId' => $payment->getPaymentId(),
141
+ 'price' => $payment->getPrice(),
142
+ 'paidPrice' => $payment->getPaidPrice(),
143
+ 'currency' => $payment->getCurrency(),
144
+ 'installment' => $payment->getInstallment(),
145
+ 'paymentTransactionId' => $payment->getPaymentItems()[0]->getPaymentTransactionId() ?? null,
146
+ 'fraudStatus' => $payment->getFraudStatus(),
147
+ ],
148
+ ];
149
+ }
150
+
151
+ return [
152
+ 'status' => 'error',
153
+ 'message' => $payment->getErrorMessage() ?? 'Payment failed.',
154
+ 'data' => ['errorCode' => $payment->getErrorCode()],
155
+ ];
156
+ } catch (\Exception $e) {
157
+ return [
158
+ 'status' => 'error',
159
+ 'message' => $e->getMessage(),
160
+ 'data' => [],
161
+ ];
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Initialise a 3D Secure payment flow.
167
+ *
168
+ * Returns an HTML snippet that must be rendered in the buyer's browser
169
+ * to redirect them to the bank's 3D Secure verification page.
170
+ *
171
+ * @param array $data Same structure as pay() with an additional `callbackUrl` key
172
+ * @return array Response containing threeDSHtmlContent on success
173
+ */
174
+ public function threeDSecureInit(array $data): array
175
+ {
176
+ try {
177
+ $request = new \Iyzipay\Request\CreatePaymentRequest();
178
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
179
+ $request->setConversationId(uniqid('3ds_'));
180
+ $request->setPrice($data['price']);
181
+ $request->setPaidPrice($data['paidPrice']);
182
+ $request->setCurrency($data['currency'] ?? \Iyzipay\Model\Currency::TL);
183
+ $request->setInstallment($data['installment'] ?? 1);
184
+ $request->setPaymentChannel(\Iyzipay\Model\PaymentChannel::WEB);
185
+ $request->setPaymentGroup(\Iyzipay\Model\PaymentGroup::PRODUCT);
186
+ $request->setCallbackUrl($data['callbackUrl']);
187
+
188
+ // Payment card
189
+ $card = new \Iyzipay\Model\PaymentCard();
190
+ $card->setCardHolderName($data['card']['holder']);
191
+ $card->setCardNumber($data['card']['number']);
192
+ $card->setExpireMonth($data['card']['month']);
193
+ $card->setExpireYear($data['card']['year']);
194
+ $card->setCvc($data['card']['cvc']);
195
+ $card->setRegisterCard(0);
196
+ $request->setPaymentCard($card);
197
+
198
+ // Buyer
199
+ $buyer = new \Iyzipay\Model\Buyer();
200
+ $buyer->setId($data['buyer']['id']);
201
+ $buyer->setName($data['buyer']['name']);
202
+ $buyer->setSurname($data['buyer']['surname']);
203
+ $buyer->setEmail($data['buyer']['email']);
204
+ $buyer->setGsmNumber($data['buyer']['phone']);
205
+ $buyer->setIp($data['buyer']['ip']);
206
+ $buyer->setCity($data['buyer']['city']);
207
+ $buyer->setCountry($data['buyer']['country']);
208
+ $buyer->setRegistrationAddress($data['buyer']['address']);
209
+ $buyer->setZipCode($data['buyer']['zipCode']);
210
+ $buyer->setIdentityNumber('00000000000');
211
+ $request->setBuyer($buyer);
212
+
213
+ // Address
214
+ $address = new \Iyzipay\Model\Address();
215
+ $address->setContactName($data['buyer']['name'] . ' ' . $data['buyer']['surname']);
216
+ $address->setCity($data['buyer']['city']);
217
+ $address->setCountry($data['buyer']['country']);
218
+ $address->setAddress($data['buyer']['address']);
219
+ $address->setZipCode($data['buyer']['zipCode']);
220
+ $request->setShippingAddress($address);
221
+ $request->setBillingAddress($address);
222
+
223
+ // Basket items
224
+ $basketItems = [];
225
+ foreach ($data['items'] as $index => $item) {
226
+ $basketItem = new \Iyzipay\Model\BasketItem();
227
+ $basketItem->setId('ITEM_' . ($index + 1));
228
+ $basketItem->setName($item['name']);
229
+ $basketItem->setCategory1($item['category'] ?? 'Default');
230
+ $basketItem->setItemType(\Iyzipay\Model\BasketItemType::PHYSICAL);
231
+ $basketItem->setPrice($item['price']);
232
+ $basketItems[] = $basketItem;
233
+ }
234
+ $request->setBasketItems($basketItems);
235
+
236
+ $threedsInit = \Iyzipay\Model\ThreedsInitialize::create($request, $this->options);
237
+
238
+ if ($threedsInit->getStatus() === 'success') {
239
+ return [
240
+ 'status' => 'success',
241
+ 'message' => '3D Secure initialisation successful.',
242
+ 'data' => [
243
+ 'threeDSHtmlContent' => $threedsInit->getHtmlContent(),
244
+ ],
245
+ ];
246
+ }
247
+
248
+ return [
249
+ 'status' => 'error',
250
+ 'message' => $threedsInit->getErrorMessage() ?? '3D Secure initialisation failed.',
251
+ 'data' => ['errorCode' => $threedsInit->getErrorCode()],
252
+ ];
253
+ } catch (\Exception $e) {
254
+ return [
255
+ 'status' => 'error',
256
+ 'message' => $e->getMessage(),
257
+ 'data' => [],
258
+ ];
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Complete a 3D Secure payment after bank verification callback.
264
+ *
265
+ * Call this from your callback URL handler with the paymentId received
266
+ * from the bank's POST response.
267
+ *
268
+ * @param array $data {
269
+ * @type string $paymentId The payment ID returned by the bank callback
270
+ * }
271
+ * @return array Standardised response
272
+ */
273
+ public function threeDSecureComplete(array $data): array
274
+ {
275
+ try {
276
+ $request = new \Iyzipay\Request\CreateThreedsPaymentRequest();
277
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
278
+ $request->setConversationId(uniqid('3ds_complete_'));
279
+ $request->setPaymentId($data['paymentId']);
280
+
281
+ $threedsPayment = \Iyzipay\Model\ThreedsPayment::create($request, $this->options);
282
+
283
+ if ($threedsPayment->getStatus() === 'success') {
284
+ return [
285
+ 'status' => 'success',
286
+ 'message' => '3D Secure payment completed successfully.',
287
+ 'data' => [
288
+ 'paymentId' => $threedsPayment->getPaymentId(),
289
+ 'price' => $threedsPayment->getPrice(),
290
+ 'paidPrice' => $threedsPayment->getPaidPrice(),
291
+ 'currency' => $threedsPayment->getCurrency(),
292
+ 'fraudStatus' => $threedsPayment->getFraudStatus(),
293
+ ],
294
+ ];
295
+ }
296
+
297
+ return [
298
+ 'status' => 'error',
299
+ 'message' => $threedsPayment->getErrorMessage() ?? '3D Secure completion failed.',
300
+ 'data' => ['errorCode' => $threedsPayment->getErrorCode()],
301
+ ];
302
+ } catch (\Exception $e) {
303
+ return [
304
+ 'status' => 'error',
305
+ 'message' => $e->getMessage(),
306
+ 'data' => [],
307
+ ];
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Refund a specific payment transaction.
313
+ *
314
+ * @param string $paymentTransactionId The transaction ID to refund (from basket item)
315
+ * @param float $price Amount to refund
316
+ * @return array Standardised response
317
+ */
318
+ public function refund(string $paymentTransactionId, float $price): array
319
+ {
320
+ try {
321
+ $request = new \Iyzipay\Request\CreateRefundRequest();
322
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
323
+ $request->setConversationId(uniqid('refund_'));
324
+ $request->setPaymentTransactionId($paymentTransactionId);
325
+ $request->setPrice($price);
326
+ $request->setCurrency(\Iyzipay\Model\Currency::TL);
327
+ $request->setIp('127.0.0.1');
328
+
329
+ $refund = \Iyzipay\Model\Refund::create($request, $this->options);
330
+
331
+ if ($refund->getStatus() === 'success') {
332
+ return [
333
+ 'status' => 'success',
334
+ 'message' => 'Refund processed successfully.',
335
+ 'data' => [
336
+ 'paymentId' => $refund->getPaymentId(),
337
+ 'paymentTransactionId' => $refund->getPaymentTransactionId(),
338
+ 'price' => $refund->getPrice(),
339
+ ],
340
+ ];
341
+ }
342
+
343
+ return [
344
+ 'status' => 'error',
345
+ 'message' => $refund->getErrorMessage() ?? 'Refund failed.',
346
+ 'data' => ['errorCode' => $refund->getErrorCode()],
347
+ ];
348
+ } catch (\Exception $e) {
349
+ return [
350
+ 'status' => 'error',
351
+ 'message' => $e->getMessage(),
352
+ 'data' => [],
353
+ ];
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Cancel an entire payment.
359
+ *
360
+ * @param string $paymentId The payment ID to cancel
361
+ * @return array Standardised response
362
+ */
363
+ public function cancel(string $paymentId): array
364
+ {
365
+ try {
366
+ $request = new \Iyzipay\Request\CreateCancelRequest();
367
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
368
+ $request->setConversationId(uniqid('cancel_'));
369
+ $request->setPaymentId($paymentId);
370
+ $request->setIp('127.0.0.1');
371
+
372
+ $cancel = \Iyzipay\Model\Cancel::create($request, $this->options);
373
+
374
+ if ($cancel->getStatus() === 'success') {
375
+ return [
376
+ 'status' => 'success',
377
+ 'message' => 'Payment cancelled successfully.',
378
+ 'data' => [
379
+ 'paymentId' => $cancel->getPaymentId(),
380
+ 'price' => $cancel->getPrice(),
381
+ 'currency' => $cancel->getCurrency(),
382
+ ],
383
+ ];
384
+ }
385
+
386
+ return [
387
+ 'status' => 'error',
388
+ 'message' => $cancel->getErrorMessage() ?? 'Cancellation failed.',
389
+ 'data' => ['errorCode' => $cancel->getErrorCode()],
390
+ ];
391
+ } catch (\Exception $e) {
392
+ return [
393
+ 'status' => 'error',
394
+ 'message' => $e->getMessage(),
395
+ 'data' => [],
396
+ ];
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Save a card to the iyzico card vault for future payments.
402
+ *
403
+ * @param array $cardData {
404
+ * @type string $holder Card holder full name
405
+ * @type string $number Card number
406
+ * @type string $month Expiry month
407
+ * @type string $year Expiry year
408
+ * @type string $alias A user-friendly card alias (e.g. "My Visa")
409
+ * }
410
+ * @param string $email Buyer e-mail (used as external identifier)
411
+ * @return array Standardised response with cardUserKey and cardToken
412
+ */
413
+ public function saveCard(array $cardData, string $email): array
414
+ {
415
+ try {
416
+ $request = new \Iyzipay\Request\CreateCardRequest();
417
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
418
+ $request->setConversationId(uniqid('card_'));
419
+ $request->setEmail($email);
420
+ $request->setExternalId(md5($email));
421
+
422
+ $cardInfo = new \Iyzipay\Model\CardInformation();
423
+ $cardInfo->setCardAlias($cardData['alias'] ?? 'Default Card');
424
+ $cardInfo->setCardHolderName($cardData['holder']);
425
+ $cardInfo->setCardNumber($cardData['number']);
426
+ $cardInfo->setExpireMonth($cardData['month']);
427
+ $cardInfo->setExpireYear($cardData['year']);
428
+ $request->setCard($cardInfo);
429
+
430
+ $card = \Iyzipay\Model\Card::create($request, $this->options);
431
+
432
+ if ($card->getStatus() === 'success') {
433
+ return [
434
+ 'status' => 'success',
435
+ 'message' => 'Card saved successfully.',
436
+ 'data' => [
437
+ 'cardUserKey' => $card->getCardUserKey(),
438
+ 'cardToken' => $card->getCardToken(),
439
+ 'cardAlias' => $card->getCardAlias(),
440
+ 'lastFour' => $card->getLastFourDigits(),
441
+ 'cardType' => $card->getCardType(),
442
+ ],
443
+ ];
444
+ }
445
+
446
+ return [
447
+ 'status' => 'error',
448
+ 'message' => $card->getErrorMessage() ?? 'Card save failed.',
449
+ 'data' => ['errorCode' => $card->getErrorCode()],
450
+ ];
451
+ } catch (\Exception $e) {
452
+ return [
453
+ 'status' => 'error',
454
+ 'message' => $e->getMessage(),
455
+ 'data' => [],
456
+ ];
457
+ }
458
+ }
459
+
460
+ /**
461
+ * Retrieve all saved cards for a given card user key.
462
+ *
463
+ * @param string $cardUserKey The user key returned when a card was first saved
464
+ * @return array Standardised response with array of cards
465
+ */
466
+ public function listCards(string $cardUserKey): array
467
+ {
468
+ try {
469
+ $request = new \Iyzipay\Request\RetrieveCardListRequest();
470
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
471
+ $request->setConversationId(uniqid('cards_'));
472
+ $request->setCardUserKey($cardUserKey);
473
+
474
+ $cardList = \Iyzipay\Model\CardList::retrieve($request, $this->options);
475
+
476
+ if ($cardList->getStatus() === 'success') {
477
+ $cards = [];
478
+ foreach ($cardList->getCardDetails() as $card) {
479
+ $cards[] = [
480
+ 'cardToken' => $card->getCardToken(),
481
+ 'cardAlias' => $card->getCardAlias(),
482
+ 'binNumber' => $card->getBinNumber(),
483
+ 'lastFourDigits' => $card->getLastFourDigits(),
484
+ 'cardType' => $card->getCardType(),
485
+ 'cardAssociation'=> $card->getCardAssociation(),
486
+ 'cardFamily' => $card->getCardFamily(),
487
+ ];
488
+ }
489
+
490
+ return [
491
+ 'status' => 'success',
492
+ 'message' => 'Cards retrieved successfully.',
493
+ 'data' => [
494
+ 'cardUserKey' => $cardList->getCardUserKey(),
495
+ 'cards' => $cards,
496
+ ],
497
+ ];
498
+ }
499
+
500
+ return [
501
+ 'status' => 'error',
502
+ 'message' => $cardList->getErrorMessage() ?? 'Could not retrieve cards.',
503
+ 'data' => ['errorCode' => $cardList->getErrorCode()],
504
+ ];
505
+ } catch (\Exception $e) {
506
+ return [
507
+ 'status' => 'error',
508
+ 'message' => $e->getMessage(),
509
+ 'data' => [],
510
+ ];
511
+ }
512
+ }
513
+
514
+ /**
515
+ * Query the status of an existing payment.
516
+ *
517
+ * @param string $paymentId The payment ID to query
518
+ * @return array Standardised response with payment details
519
+ */
520
+ public function checkPayment(string $paymentId): array
521
+ {
522
+ try {
523
+ $request = new \Iyzipay\Request\RetrievePaymentRequest();
524
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
525
+ $request->setConversationId(uniqid('check_'));
526
+ $request->setPaymentId($paymentId);
527
+
528
+ $payment = \Iyzipay\Model\Payment::retrieve($request, $this->options);
529
+
530
+ if ($payment->getStatus() === 'success') {
531
+ $items = [];
532
+ if ($payment->getPaymentItems()) {
533
+ foreach ($payment->getPaymentItems() as $item) {
534
+ $items[] = [
535
+ 'itemId' => $item->getItemId(),
536
+ 'paymentTransactionId' => $item->getPaymentTransactionId(),
537
+ 'price' => $item->getPrice(),
538
+ 'paidPrice' => $item->getPaidPrice(),
539
+ 'transactionStatus' => $item->getTransactionStatus(),
540
+ ];
541
+ }
542
+ }
543
+
544
+ return [
545
+ 'status' => 'success',
546
+ 'message' => 'Payment details retrieved.',
547
+ 'data' => [
548
+ 'paymentId' => $payment->getPaymentId(),
549
+ 'price' => $payment->getPrice(),
550
+ 'paidPrice' => $payment->getPaidPrice(),
551
+ 'currency' => $payment->getCurrency(),
552
+ 'installment' => $payment->getInstallment(),
553
+ 'paymentStatus'=> $payment->getPaymentStatus(),
554
+ 'fraudStatus' => $payment->getFraudStatus(),
555
+ 'cardType' => $payment->getCardType(),
556
+ 'lastFourDigits' => $payment->getLastFourDigits(),
557
+ 'items' => $items,
558
+ ],
559
+ ];
560
+ }
561
+
562
+ return [
563
+ 'status' => 'error',
564
+ 'message' => $payment->getErrorMessage() ?? 'Could not retrieve payment.',
565
+ 'data' => ['errorCode' => $payment->getErrorCode()],
566
+ ];
567
+ } catch (\Exception $e) {
568
+ return [
569
+ 'status' => 'error',
570
+ 'message' => $e->getMessage(),
571
+ 'data' => [],
572
+ ];
573
+ }
574
+ }
575
+
576
+ /**
577
+ * Register a new sub-merchant for marketplace payments.
578
+ *
579
+ * @param array $data {
580
+ * @type string $name Sub-merchant legal name
581
+ * @type string $type PERSONAL_COMPANY | PRIVATE_COMPANY | LIMITED_OR_JOINT_STOCK_COMPANY
582
+ * @type string $taxOffice Tax office name
583
+ * @type string $taxNumber Tax / identity number
584
+ * @type string $legalCompanyName Legal company title
585
+ * @type string $email Contact e-mail
586
+ * @type string $phone Contact phone (GSM)
587
+ * @type string $address Registered address
588
+ * @type string $iban IBAN for payouts
589
+ * @type string $currency Currency code (default: TRY)
590
+ * @type string $subMerchantExternalId Unique external identifier
591
+ * }
592
+ * @return array Standardised response with subMerchantKey
593
+ */
594
+ public function createSubMerchant(array $data): array
595
+ {
596
+ try {
597
+ $request = new \Iyzipay\Request\CreateSubMerchantRequest();
598
+ $request->setLocale(\Iyzipay\Model\Locale::TR);
599
+ $request->setConversationId(uniqid('sub_'));
600
+ $request->setSubMerchantExternalId($data['subMerchantExternalId'] ?? uniqid('sm_'));
601
+ $request->setSubMerchantType($data['type'] ?? \Iyzipay\Model\SubMerchantType::LIMITED_OR_JOINT_STOCK_COMPANY);
602
+ $request->setAddress($data['address']);
603
+ $request->setTaxOffice($data['taxOffice'] ?? '');
604
+ $request->setLegalCompanyTitle($data['legalCompanyName'] ?? $data['name']);
605
+ $request->setEmail($data['email']);
606
+ $request->setGsmNumber($data['phone']);
607
+ $request->setName($data['name']);
608
+ $request->setIban($data['iban']);
609
+ $request->setIdentityNumber($data['taxNumber'] ?? '00000000000');
610
+ $request->setCurrency($data['currency'] ?? \Iyzipay\Model\Currency::TL);
611
+
612
+ $subMerchant = \Iyzipay\Model\SubMerchant::create($request, $this->options);
613
+
614
+ if ($subMerchant->getStatus() === 'success') {
615
+ return [
616
+ 'status' => 'success',
617
+ 'message' => 'Sub-merchant created successfully.',
618
+ 'data' => [
619
+ 'subMerchantKey' => $subMerchant->getSubMerchantKey(),
620
+ ],
621
+ ];
622
+ }
623
+
624
+ return [
625
+ 'status' => 'error',
626
+ 'message' => $subMerchant->getErrorMessage() ?? 'Sub-merchant creation failed.',
627
+ 'data' => ['errorCode' => $subMerchant->getErrorCode()],
628
+ ];
629
+ } catch (\Exception $e) {
630
+ return [
631
+ 'status' => 'error',
632
+ 'message' => $e->getMessage(),
633
+ 'data' => [],
634
+ ];
635
+ }
636
+ }
637
+ }