Skip to content

Commit e53da8f

Browse files
committed
refactor(docs): created separate doc file for 3D Secure payment.
1 parent f02b934 commit e53da8f

4 files changed

Lines changed: 332 additions & 248 deletions

File tree

.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ tests/ export-ignore
66
var/
77
.github/ export-ignore
88
.php-cs-fixer.php export-ignore
9-
phpstan.neon export-ignore
9+
phpstan.neon export-ignore
10+
phpstan-baseline.neon export-ignore

README.md

Lines changed: 83 additions & 245 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
- [Minimum Gereksinimler](#minimum-gereksinimler)
99
- [Kurulum](#kurulum)
10-
- [Ornek 3D Secure Odeme](#farkli-banka-sanal-poslarini-eklemek)
10+
- [Servis Kullanımı](#servis-kullanımı)
11+
- [Örnek 3D Secure Ödeme](./docs/EXAMPLE_3D_SECURE_ODEME.md)
1112
- [Konfigurasyon Yapısı ve Örnekler](./docs/EXAMPLE_CONFIGURATIONS.md)
1213
- [API ve 3D Form verisini degiştirme](./docs/EXAMPLE-API-ISTEK-VE-3D-FORM-VERSINI-DEGISTIRME.md)
1314
- [PosQuery Servisleri (geçmiş, taksit, BIN sorguları)](./docs/POS-QUERY.md)
@@ -39,8 +40,7 @@
3940
gateway_3d: 'https://entegrasyon.asseco-see.com.tr/fim/est3Dgate'
4041
gateway_3d_host: 'https://sanalpos.sanalakpos.com.tr/fim/est3Dgate' # optional, 3D Host ödemeler için zorunlu
4142
gateway_configs:
42-
test_mode: false # optional, default: false
43-
lang: tr # optional, default: tr
43+
lang: !php/const Mews\Pos\PosInterface::LANG_TR # optional, default: LANG_TR
4444
yapikredi:
4545
gateway_class: Mews\Pos\Gateway\PosNetPos
4646
credentials:
@@ -53,266 +53,104 @@
5353
gateway_3d: 'https://setmpos.ykb.com/3DSWebService/YKBPaymentService'
5454
```
5555

56-
### Ornek 3D Secure Odeme
56+
Diğer banka konfigurasyon örnekleri için bkz. [Konfigurasyon Yapısı ve Örnekler](./docs/EXAMPLE_CONFIGURATIONS.md).
57+
58+
## Servis Kullanımı
59+
60+
### POS Gateway inject etme
61+
62+
`mews_pos.yaml`'daki **ilk banka** `PosInterface` tipiyle doğrudan inject edilebilir:
63+
5764
```php
58-
<?php
65+
use Mews\Pos\PosInterface;
66+
67+
class MyService
68+
{
69+
public function __construct(private PosInterface $pos) {}
70+
}
71+
```
5972
60-
namespace App\Controller;
73+
**Belirli bir bankayı** inject etmek için argüman adını `mews_pos.yaml`'daki banka anahtarıyla eşleştirin:
6174

62-
use Mews\Pos\Entity\Card\CreditCardInterface;
63-
use Mews\Pos\Exceptions\CardTypeNotSupportedException;
64-
use Mews\Pos\Exceptions\CardTypeRequiredException;
65-
use Mews\Pos\Exceptions\HashMismatchException;
66-
use Mews\Pos\Factory\CreditCardFactory;
67-
use Mews\Pos\Gateway\PayFlexV4Pos;
75+
```php
6876
use Mews\Pos\PosInterface;
69-
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
70-
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
71-
use Symfony\Component\HttpFoundation\RedirectResponse;
72-
use Symfony\Component\HttpFoundation\Request;
73-
use Symfony\Component\Routing\Annotation\Route;
74-
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
7577
76-
#[Route('/payment/3d')]
77-
class SingleBankThreeDSecurePaymentController extends AbstractController
78+
class MyService
7879
{
79-
private string $paymentModel = PosInterface::MODEL_3D_HOST;
80+
public function __construct(
81+
private PosInterface $asseco, // mews_pos.yaml'daki "asseco" bankası
82+
private PosInterface $yapikredi, // mews_pos.yaml'daki "yapikredi" bankası
83+
) {}
84+
}
85+
```
86+
87+
**Tüm bankalara** erişmek için `TaggedIterator` kullanın:
8088

89+
```php
90+
use Mews\Pos\PosInterface;
91+
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
92+
93+
class MyService
94+
{
8195
public function __construct(
82-
/**
83-
* mews_pos.yaml'da birden fazla banka configurasyonu varsa, ilki default olarak inject edilecek
84-
*/
85-
private PosInterface $pos,
86-
/**
87-
* spesifik bir bankayi inject etmek istiyorsak:
88-
*/
89-
private PosInterface $yapikrediTest,
90-
private UrlGeneratorInterface $urlGenerator,
91-
/**
92-
* birden fazla banka oldugunda bu sekilde hepsine erisebilirsiniz
93-
* @var PosInterface[]
94-
*/
9596
#[TaggedIterator('mews_pos.gateway')]
9697
private iterable $banks,
97-
)
98-
{
99-
// foreach ($this->banks as $bank) {
100-
// if ('asseco' === $bank->getAccount()->getBankName()) {
101-
// // todo
102-
// }
103-
// }
104-
}
105-
106-
/**
107-
* Kullanicidan kredi kart bilgileri alip buraya POST ediyoruz
108-
*/
109-
#[Route('/form', name: 'single_bank_payment_3d_redirect_form', methods: ['POST'])]
110-
public function form(Request $request)
111-
{
112-
$session = $request->getSession();
113-
114-
$transaction = $request->get('tx', PosInterface::TX_TYPE_PAY_AUTH);
115-
116-
$callbackUrl = $this->urlGenerator->generate('single_bank_payment_3d_response', [], UrlGeneratorInterface::ABSOLUTE_URL);
117-
$order = $this->createNewOrder(
118-
$this->paymentModel,
119-
$callbackUrl,
120-
$request->getClientIp(),
121-
$request->get('currency', PosInterface::CURRENCY_TRY),
122-
$request->get('installment'),
123-
$request->get('lang', PosInterface::LANG_TR)
124-
);
125-
$session->set('order', $order);
126-
127-
$card = $this->createCard($this->pos, $request->request->all());
128-
129-
/**
130-
* PayFlex'te provizyonu (odemeyi) tamamlamak icin tekrar kredi kart bilgileri isteniyor,
131-
* bu yuzden kart bilgileri kaydediyoruz
132-
*/
133-
if ($this->pos::class === PayFlexV4Pos::class) {
134-
$session->set('card', $request->request->all());
135-
}
136-
$session->set('tx', $transaction);
137-
138-
try {
139-
$formData = $this->pos->get3DFormData(
140-
$order,
141-
$this->paymentModel,
142-
$transaction,
143-
$card,
144-
/**
145-
* MODEL_3D_SECURE veya MODEL_3D_PAY ödemelerde kredi kart verileri olmadan
146-
* form verisini oluşturmak için true yapabilirsiniz.
147-
* Yine de bazı gatewaylerde kartsız form verisi oluşturulamıyor.
148-
*/
149-
false
150-
);
151-
} catch (\Throwable $e) {
152-
dd($e);
153-
}
154-
155-
/**
156-
* Bazı 3D Host gateway'leri (VakifKatilimPos, KuveytPos, vb.) doğrudan bir yönlendirme URL'i döner:
157-
* method=GET ve inputs=[]. Bu durumda HTML form render etmek yerine doğrudan yönlendiriyoruz.
158-
*/
159-
if (!is_string($formData) && $formData['method'] === 'GET' && [] === $formData['inputs']) {
160-
return new RedirectResponse($formData['gateway']);
161-
}
162-
163-
return $this->render('redirect-form.html.twig', [
164-
'formData' => $formData,
165-
]);
166-
}
167-
168-
169-
/**
170-
* kullanici bankadan geri buraya redirect edilir
171-
*/
172-
#[Route('/response', name: 'single_bank_payment_3d_response')]
173-
public function response(Request $request)
174-
{
175-
$session = $request->getSession();
176-
177-
$transaction = $session->get('tx', PosInterface::TX_TYPE_PAY_AUTH);
178-
179-
// bankadan POST veya GET ile veri gelmesi gerekiyor
180-
if (($request->getMethod() !== 'POST')
181-
// PayFlex-CP GET request ile cevapliyor
182-
&& ($request->getMethod() === 'GET' && ($this->pos::class !== \Mews\Pos\Gateway\PayFlexCPV4Pos::class || [] === $request->query->all()))
183-
) {
184-
return new RedirectResponse($request->getBaseUrl());
185-
}
186-
187-
$card = null;
188-
if ($this->pos::class === \Mews\Pos\Gateway\PayFlexV4Pos::class) {
189-
// bu gateway için ödemeyi tamamlarken tekrar kart bilgisi lazım.
190-
$savedCard = $session->get('card');
191-
$card = $this->createCard($this->pos, $savedCard);
192-
$session->remove('card');
193-
}
194-
195-
$order = $session->get('order');
196-
if (!$order) {
197-
throw new \Exception('Sipariş bulunamadı, session sıfırlanmış olabilir.');
198-
}
199-
200-
// PayFlexCPV4 GET ile cevap veriyor, diğerleri POST
201-
$gatewayResponseData = $this->pos::class === \Mews\Pos\Gateway\PayFlexCPV4Pos::class
202-
? $request->query->all()
203-
: $request->request->all();
204-
205-
try {
206-
$response = $this->pos->payment($this->paymentModel, $order, $transaction, $card, $gatewayResponseData);
207-
} catch (HashMismatchException $e) {
208-
/**
209-
* Bankadan gelen verilerin bankaya ait olmadığında bu exception oluşur.
210-
* Veya Banka API bilgileriniz hatalı ise de oluşur.
211-
* Eğer kütühaneden dolayı hash doğrulama hatası alıyorsanız, issue oluşturunuz.
212-
* Issue çözülene kadar geçici olarak disable_3d_hash_check: true ayarla hash doğrulamasını devre dışı bırakabilirsiniz.
213-
* Güvenlik açısından disable_3d_hash_check: false olarak kullanılması tavsiye edilmez.
214-
*/
215-
dd($e);
216-
} catch (\Exception|\Error $e) {
217-
dd($e);
218-
}
219-
220-
if ($this->pos->isSuccess()) {
221-
echo 'success';
222-
dd($response);
223-
} else {
224-
dd($response);
225-
}
226-
}
227-
228-
private function createNewOrder(
229-
string $paymentModel,
230-
string $callbackUrl,
231-
string $ip,
232-
string $currency,
233-
?int $installment = 0,
234-
string $lang = PosInterface::LANG_TR
235-
): array
236-
{
237-
$orderId = date('Ymd').strtoupper(substr(uniqid(sha1(time())), 0, 4));
238-
239-
$order = [
240-
'id' => $orderId,
241-
'amount' => 10.01,
242-
'currency' => $currency,
243-
'installment' => $installment,
244-
'ip' => \filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? $ip : '127.0.0.1',
245-
];
246-
247-
if (\in_array($paymentModel, [
248-
PosInterface::MODEL_3D_SECURE,
249-
PosInterface::MODEL_3D_PAY,
250-
PosInterface::MODEL_3D_HOST,
251-
PosInterface::MODEL_3D_PAY_HOSTING,
252-
], true)) {
253-
$order['success_url'] = $callbackUrl;
254-
$order['fail_url'] = $callbackUrl;
255-
}
256-
257-
if ($lang) {
258-
$order['lang'] = $lang;
259-
}
260-
261-
return $order;
262-
}
263-
264-
private function createCard(PosInterface $pos, array $card): CreditCardInterface
265-
{
266-
try {
267-
return CreditCardFactory::createForGateway(
268-
$pos,
269-
$card['number'],
270-
$card['year'],
271-
$card['month'],
272-
$card['cvv'],
273-
$card['name'],
274-
$card['type'] ?? null
275-
);
276-
} catch (CardTypeRequiredException|CardTypeNotSupportedException $e) {
277-
dd($e);
278-
} catch (\LogicException $e) {
279-
dd($e);
280-
}
281-
}
98+
) {}
28299
}
283100
```
284101

285-
`redirect-form.html.twig`:
286-
```html
287-
{% if formData is iterable %}
288-
<form method="{{ formData.method }}" action="{{ formData.gateway }}" class="redirect-form" role="form">
289-
{% for key, value in formData.inputs %}
290-
<input type="hidden" name="{{ key }}" value="{{ value }}">
291-
{% endfor %}
292-
<div class="text-center">Redirecting...</div>
293-
<hr>
294-
<div class="form-group text-center">
295-
<button type="submit" class="btn btn-lg btn-block btn-success">Submit</button>
296-
</div>
297-
</form>
298-
<script>
299-
document.querySelector('form.redirect-form').submit();
300-
</script>
301-
{% else %}
302-
{{ formData | raw }}
303-
{% endif %}
102+
Tam controller örneği için bkz. [Örnek 3D Secure Ödeme](./docs/EXAMPLE_3D_SECURE_ODEME.md).
103+
104+
---
105+
106+
### PosQuery inject etme
107+
108+
`PosQueryInterface`, ödeme işlemiyle ilişkili olmayan banka sorguları (işlem geçmişi, taksit oranları, BIN sorgusu vb.) için kullanılır. Her gateway PosQuery desteği sunmaz; bundle yalnızca `mews/pos` kütüphanesinin o gateway için bir PosQuery sınıfı tanımladığı durumlarda servisi oluşturur.
109+
110+
`mews_pos.yaml`'daki **ilk banka** PosQuery destekliyorsa doğrudan inject edilebilir:
111+
112+
```php
113+
use Mews\Pos\PosQuery\PosQueryInterface;
114+
115+
class MyService
116+
{
117+
public function __construct(private PosQueryInterface $posQuery) {}
118+
}
119+
```
120+
121+
**Belirli bir bankayı** inject etmek için argüman adını banka anahtarıyla eşleştirin:
122+
123+
```php
124+
use Mews\Pos\PosQuery\PosQueryInterface;
125+
126+
class MyService
127+
{
128+
public function __construct(
129+
private PosQueryInterface $asseco,
130+
private PosQueryInterface $yapikredi,
131+
) {}
132+
}
304133
```
305134
135+
**Tüm PosQuery servislerine** erişmek için:
136+
137+
```php
138+
use Mews\Pos\PosQuery\PosQueryInterface;
139+
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
306140
307-
PHP Sessioni kullanıyorsanız bu ayarları da yapmanız gerekiyor:
308-
```yaml
309-
# /config/packages/framework.yaml
310-
framework:
311-
session:
312-
cookie_secure: true
313-
cookie_samesite: none
141+
class MyService
142+
{
143+
public function __construct(
144+
#[TaggedIterator('mews_pos.query')]
145+
private iterable $posQueries,
146+
) {}
147+
}
314148
```
315149
150+
Tam örnek ve desteklenen sorgu tipleri için bkz. [PosQuery Servisleri](./docs/POS-QUERY.md).
151+
152+
---
153+
316154
License
317155
----
318156

0 commit comments

Comments
 (0)