diff --git a/README.md b/README.md index 753370ff..e97cb405 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ sistemlerinin kullanılabilmesidir. | Gateway | Desktekleyen
bankalar | Desteklenen
Ödeme Tipleri | Desteklenen Sorgular | |----------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| | Tosla
(eski AKÖde) | ? | NonSecure
3DPay
3DHost | İptal
İade
Durum sorgulama
Sipariş Tarihçesini sorgulama
Özel Sorgu | -| ParamPos | ? | NonSecure
3DSecure
3DPay
3DHost (test edilmesi gerekiyor) | İptal
İade
Durum sorgulama
Geçmiş İşlemleri sorgulama
Özel Sorgu | +| ParamPos | ? | NonSecure
3DSecure
3DPay
(test edilmesi gerekiyor) | İptal
İade
Durum sorgulama
Geçmiş İşlemleri sorgulama
Özel Sorgu | +| Param3DHostPos | ? | 3DHost
(test edilmesi gerekiyor) | | | AkbankPos
(Akbankın yeni altyapısı) | Akbank | NonSecure
3DSecur
3DPay
3DHost
Tekrarlanan Ödeme | İptal
İade
Sipariş Tarihçesini sorgulama
Geçmiş İşlemleri sorgulama
Özel Sorgu | | EstV3Pos
(Asseco/Payten)
Eski `EstPos` altyapının
sha512 hash algoritmasıyla uygulaması.
| Akbank
TEB
İşbank
Şekerbank
Halkbank
Finansbank
Ziraat | NonSecure
3DSecure
3DPay
3DHost
3DPayHost
Tekrarlanan Ödeme | İptal
İade
Durum sorgulama
Sipariş Tarihçesini sorgulama
Özel Sorgu | | PayFlex MPI VPOS V4 | Ziraat
Vakıfbank VPOS 7/24
İşbank | NonSecure
3DSecure
Tekrarlanan Ödeme | İptal
İade
Durum sorgulama
Özel Sorgu | @@ -23,7 +24,8 @@ sistemlerinin kullanılabilmesidir. | PosNetV1
(JSON API) | Albaraka Türk | NonSecure
3DSecure | İptal
İade
Durum sorgulama
Özel Sorgu | | PayFor | Finansbank
Enpara
Ziraat Katılım | NonSecure
3DSecure
3DPay
3DHost | İptal
İade
Durum sorgulama
Sipariş Tarihçesini sorgulama
Geçmiş İşlemleri sorgulama
Özel Sorgu | | InterPOS | Deniz bank | NonSecure
3DSecure
3DPay
3DHost | İptal
İade
Durum sorgulama
Özel Sorgu | -| Kuveyt POS
TDV2.0.0 | Kuveyt Türk | NonSecure
3DSecure | İptal
İade
Durum sorgulama
(SOAP API)
Özel Sorgu | +| Kuveyt POS
TDV2.0.0 | Kuveyt Türk | NonSecure
3DSecure | | +| Kuveyt POS
TDV2.0.0
SOAP API | Kuveyt Türk | | İptal
İade
Durum sorgulama
Özel Sorgu | | VakifKatilimPos | Vakıf Katılım | NonSecure (test edilmesi gerekiyor)
3DSecure
3DHost (test edilmesi gerekiyor) | İptal
İade
Durum sorgulama
Sipariş Tarihçesini sorgulama
Geçmiş İşlemleri sorgulama
Özel Sorgu | ### Ana başlıklar @@ -167,7 +169,8 @@ return [ 'banks' => [ 'akbank' => [ 'name' => 'AKBANK T.A.S.', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, // optional 'gateway_endpoints' => [ 'payment_api' => 'https://www.sanalakpos.com/fim/api', 'gateway_3d' => 'https://www.sanalakpos.com/fim/est3Dgate', @@ -179,6 +182,7 @@ return [ 'isbank' => [ // unique bir isim vermeniz gerekir. 'name' => 'İŞ BANKASI .A.S.', 'class' => \Mews\Pos\Gateways\EstV3Pos::class, // Altyapı sınıfı + 'lang' => \Mews\Pos\PosInterface::LANG_TR, // optional 'gateway_endpoints' => [ 'payment_api' => 'https://sanalpos.isbank.com.tr/fim/api', 'gateway_3d' => 'https://sanalpos.isbank.com.tr/fim/est3Dgate', diff --git a/config/pos_production.php b/config/pos_production.php index f0c8071c..38059dc5 100644 --- a/config/pos_production.php +++ b/config/pos_production.php @@ -7,7 +7,8 @@ 'banks' => [ 'akbank-pos' => [ 'name' => 'AKBANK T.A.S.', - 'class' => Mews\Pos\Gateways\AkbankPos::class, + 'class' => \Mews\Pos\Gateways\AkbankPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://api.akbank.com/api/v1/payment/virtualpos', 'gateway_3d' => 'https://virtualpospaymentgateway.akbank.com/securepay', @@ -15,100 +16,112 @@ ], ], 'akbankv3' => [ - 'name' => 'AKBANK T.A.S.', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ + 'name' => 'AKBANK T.A.S.', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ 'payment_api' => 'https://www.sanalakpos.com/fim/api', 'gateway_3d' => 'https://www.sanalakpos.com/fim/est3Dgate', 'gateway_3d_host' => 'https://sanalpos.sanalakpos.com.tr/fim/est3Dgate', ], ], 'akbank' => [ - 'name' => 'AKBANK T.A.S.', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ + 'name' => 'AKBANK T.A.S.', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ 'payment_api' => 'https://www.sanalakpos.com/fim/api', 'gateway_3d' => 'https://www.sanalakpos.com/fim/est3Dgate', 'gateway_3d_host' => 'https://sanalpos.sanalakpos.com.tr/fim/est3Dgate', ], ], - 'tosla' => [ - 'name' => 'AkÖde A.Ş.', - 'class' => Mews\Pos\Gateways\ToslaPos::class, - 'gateway_endpoints' => [ + 'tosla' => [ + 'name' => 'AkÖde A.Ş.', + 'class' => \Mews\Pos\Gateways\ToslaPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ 'payment_api' => 'https://entegrasyon.tosla.com/api/Payment', 'gateway_3d' => 'https://entegrasyon.tosla.com/api/Payment/ProcessCardForm', 'gateway_3d_host' => 'https://entegrasyon.tosla.com/api/Payment/threeDSecure', ], ], 'finansbank' => [ - 'name' => 'QNB Finansbank', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://www.fbwebpos.com/fim/api', - 'gateway_3d' => 'https://www.fbwebpos.com/fim/est3dgate', + 'name' => 'QNB Finansbank', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://www.fbwebpos.com/fim/api', + 'gateway_3d' => 'https://www.fbwebpos.com/fim/est3dgate', ], ], 'halkbank' => [ - 'name' => 'Halkbank', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalpos.halkbank.com.tr/fim/api', - 'gateway_3d' => 'https://sanalpos.halkbank.com.tr/fim/est3dgate', + 'name' => 'Halkbank', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://sanalpos.halkbank.com.tr/fim/api', + 'gateway_3d' => 'https://sanalpos.halkbank.com.tr/fim/est3dgate', ], ], 'teb' => [ - 'name' => 'TEB', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalpos.teb.com.tr/fim/api', - 'gateway_3d' => 'https://sanalpos.teb.com.tr/fim/est3Dgate', + 'name' => 'TEB', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://sanalpos.teb.com.tr/fim/api', + 'gateway_3d' => 'https://sanalpos.teb.com.tr/fim/est3Dgate', ], ], 'isbank' => [ - 'name' => 'İşbank T.A.S.', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalpos.isbank.com.tr/fim/api', - 'gateway_3d' => 'https://sanalpos.isbank.com.tr/fim/est3Dgate', + 'name' => 'İşbank T.A.S.', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://sanalpos.isbank.com.tr/fim/api', + 'gateway_3d' => 'https://sanalpos.isbank.com.tr/fim/est3Dgate', ], ], 'sekerbank' => [ - 'name' => 'Şeker Bank', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalpos.sekerbank.com.tr/fim/api', - 'gateway_3d' => 'https://sanalpos.sekerbank.com.tr/fim/est3Dgate', + 'name' => 'Şeker Bank', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://sanalpos.sekerbank.com.tr/fim/api', + 'gateway_3d' => 'https://sanalpos.sekerbank.com.tr/fim/est3Dgate', ], ], 'yapikredi' => [ - 'name' => 'Yapıkredi', - 'class' => Mews\Pos\Gateways\PosNet::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://posnet.yapikredi.com.tr/PosnetWebService/XML', - 'gateway_3d' => 'https://posnet.yapikredi.com.tr/3DSWebService/YKBPaymentService', + 'name' => 'Yapıkredi', + 'class' => \Mews\Pos\Gateways\PosNet::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://posnet.yapikredi.com.tr/PosnetWebService/XML', + 'gateway_3d' => 'https://posnet.yapikredi.com.tr/3DSWebService/YKBPaymentService', ], ], 'albaraka' => [ - 'name' => 'Albaraka', - 'class' => Mews\Pos\Gateways\PosNetV1Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://epos.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc', - 'gateway_3d' => 'https://epos.albarakaturk.com.tr/ALBSecurePaymentUI/SecureProcess/SecureVerification.aspx', + 'name' => 'Albaraka', + 'class' => \Mews\Pos\Gateways\PosNetV1Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://epos.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc', + 'gateway_3d' => 'https://epos.albarakaturk.com.tr/ALBSecurePaymentUI/SecureProcess/SecureVerification.aspx', ], ], 'garanti' => [ - 'name' => 'Garanti', - 'class' => Mews\Pos\Gateways\GarantiPos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalposprov.garanti.com.tr/VPServlet', - 'gateway_3d' => 'https://sanalposprov.garanti.com.tr/servlet/gt3dengine', + 'name' => 'Garanti', + 'class' => \Mews\Pos\Gateways\GarantiPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://sanalposprov.garanti.com.tr/VPServlet', + 'gateway_3d' => 'https://sanalposprov.garanti.com.tr/servlet/gt3dengine', ], ], 'qnbfinansbank-payfor' => [ - 'name' => 'QNBFinansbank-PayFor', - 'class' => Mews\Pos\Gateways\PayForPos::class, - 'gateway_endpoints' => [ + 'name' => 'QNBFinansbank-PayFor', + 'class' => \Mews\Pos\Gateways\PayForPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ 'payment_api' => 'https://vpos.qnbfinansbank.com/Gateway/XMLGate.aspx', 'gateway_3d' => 'https://vpos.qnbfinansbank.com/Gateway/Default.aspx', 'gateway_3d_host' => 'https://vpos.qnbfinansbank.com/Gateway/3DHost.aspx', @@ -116,7 +129,8 @@ ], 'ziraat-katilim-payfor' => [ 'name' => 'ZiraatKatilim-PayFor', - 'class' => Mews\Pos\Gateways\PayForPos::class, + 'class' => \Mews\Pos\Gateways\PayForPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_configs' => [ // Ziraat Katilim için hash kontrolü çalışmıyor. O yüzden devre dışı bırakıyoruz. 'disable_3d_hash_check' => true, @@ -128,60 +142,74 @@ ], ], 'vakifbank' => [ - 'name' => 'VakifBank-VPOS', - 'class' => Mews\Pos\Gateways\PayFlexV4Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://onlineodeme.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', - 'gateway_3d' => 'https://3dsecure.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspx', - 'query_api' => 'https://onlineodeme.vakifbank.com.tr:4443/UIService/Search.aspx', + 'name' => 'VakifBank-VPOS', + 'class' => \Mews\Pos\Gateways\PayFlexV4Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://onlineodeme.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + 'gateway_3d' => 'https://3dsecure.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspx', + 'query_api' => 'https://onlineodeme.vakifbank.com.tr:4443/UIService/Search.aspx', ], ], 'ziraat-vpos' => [ - 'name' => 'Ziraat Bankası', - 'class' => Mews\Pos\Gateways\PayFlexV4Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalpos.ziraatbank.com.tr/v4/v3/Vposreq.aspx', - 'gateway_3d' => 'https://mpi.ziraatbank.com.tr/Enrollment.aspx', - 'query_api' => 'https://sanalpos.ziraatbank.com.tr/v4/UIWebService/Search.aspx', + 'name' => 'Ziraat Bankası', + 'class' => \Mews\Pos\Gateways\PayFlexV4Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://sanalpos.ziraatbank.com.tr/v4/v3/Vposreq.aspx', + 'gateway_3d' => 'https://mpi.ziraatbank.com.tr/Enrollment.aspx', + 'query_api' => 'https://sanalpos.ziraatbank.com.tr/v4/UIWebService/Search.aspx', ], ], - 'ziraat-estpos' => [ - 'name' => 'Ziraat Bankası Payten', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalpos2.ziraatbank.com.tr/fim/api', - 'gateway_3d' => 'https://sanalpos2.ziraatbank.com.tr/fim/est3Dgate', + 'ziraat-estpos' => [ + 'name' => 'Ziraat Bankası Payten', + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://sanalpos2.ziraatbank.com.tr/fim/api', + 'gateway_3d' => 'https://sanalpos2.ziraatbank.com.tr/fim/est3Dgate', ], ], 'vakifbank-cp' => [ - 'name' => 'VakifBank-PayFlex-Common-Payment', - 'class' => Mews\Pos\Gateways\PayFlexCPV4Pos::class, - 'gateway_endpoints' => [ + 'name' => 'VakifBank-PayFlex-Common-Payment', + 'class' => \Mews\Pos\Gateways\PayFlexCPV4Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ 'payment_api' => 'https://cpweb.vakifbank.com.tr/CommonPayment/api/VposTransaction', 'gateway_3d' => 'https://cpweb.vakifbank.com.tr/CommonPayment/api/RegisterTransaction', ], ], 'denizbank' => [ - 'name' => 'DenizBank-InterPos', - 'class' => Mews\Pos\Gateways\InterPos::class, - 'gateway_endpoints' => [ + 'name' => 'DenizBank-InterPos', + 'class' => \Mews\Pos\Gateways\InterPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ 'payment_api' => 'https://inter-vpos.com.tr/mpi/Default.aspx', 'gateway_3d' => 'https://inter-vpos.com.tr/mpi/Default.aspx', 'gateway_3d_host' => 'https://inter-vpos.com.tr/mpi/3DHost.aspx', ], ], - 'kuveytpos' => [ + 'kuveytpos' => [ 'name' => 'kuveyt-pos', - 'class' => Mews\Pos\Gateways\KuveytPos::class, + 'class' => \Mews\Pos\Gateways\KuveytPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home', 'gateway_3d' => 'https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home/ThreeDModelPayGate', - 'query_api' => 'https://boa.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', ], ], - 'vakif-katilim' => [ + 'kuveytsoappos' => [ + 'name' => 'KuveytSoapApiPos', + 'class' => \Mews\Pos\Gateways\KuveytSoapApiPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'query_api' => 'https://boa.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + ], + 'vakif-katilim' => [ 'name' => 'Vakıf Katılım', - 'class' => Mews\Pos\Gateways\VakifKatilimPos::class, + 'class' => \Mews\Pos\Gateways\VakifKatilimPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home', 'gateway_3d' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', @@ -190,11 +218,18 @@ ], 'param-pos' => [ 'name' => 'TURK Elektronik Para A.Ş', - 'class' => Mews\Pos\Gateways\ParamPos::class, + 'class' => \Mews\Pos\Gateways\ParamPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://posws.param.com.tr/turkpos.ws/service_turkpos_prod.asmx', + ], + ], + 'param-3d-host-pos' => [ + 'name' => 'TURK Elektronik Para A.Ş', + 'class' => \Mews\Pos\Gateways\Param3DHostPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ - 'payment_api' => 'https://posws.param.com.tr/turkpos.ws/service_turkpos_prod.asmx', - // API URL for 3D host payment - 'payment_api_2' => 'https://pos.param.com.tr/Tahsilat/to.ws/Service_Odeme.asmx', + 'payment_api' => 'https://pos.param.com.tr/Tahsilat/to.ws/Service_Odeme.asmx', 'gateway_3d_host' => 'https://pos.param.com.tr/Tahsilat/Default.aspx', ], ], diff --git a/config/pos_test.php b/config/pos_test.php index 0763ee7a..96179948 100644 --- a/config/pos_test.php +++ b/config/pos_test.php @@ -4,7 +4,8 @@ 'banks' => [ 'akbank-pos' => [ 'name' => 'AKBANK T.A.S.', - 'class' => Mews\Pos\Gateways\AkbankPos::class, + 'class' => \Mews\Pos\Gateways\AkbankPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://apipre.akbank.com/api/v1/payment/virtualpos', 'gateway_3d' => 'https://virtualpospaymentgatewaypre.akbank.com/securepay', @@ -13,17 +14,25 @@ ], 'param-pos' => [ 'name' => 'TURK Elektronik Para A.Ş', - 'class' => Mews\Pos\Gateways\ParamPos::class, + 'class' => \Mews\Pos\Gateways\ParamPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', - // API URL for 3D host payment - 'payment_api_2' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', + ], + ], + 'param-3d-host-pos' => [ + 'name' => 'TURK Elektronik Para A.Ş', + 'class' => \Mews\Pos\Gateways\Param3DHostPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'payment_api' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', 'gateway_3d_host' => 'https://test-pos.param.com.tr/default.aspx', ], ], 'payten_v3_hash' => [ 'name' => 'AKBANK T.A.S.', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://entegrasyon.asseco-see.com.tr/fim/api', 'gateway_3d' => 'https://entegrasyon.asseco-see.com.tr/fim/est3Dgate', @@ -31,7 +40,8 @@ ], 'akbank' => [ 'name' => 'AKBANK T.A.S.', - 'class' => Mews\Pos\Gateways\EstV3Pos::class, + 'class' => \Mews\Pos\Gateways\EstV3Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://entegrasyon.asseco-see.com.tr/fim/api', 'gateway_3d' => 'https://entegrasyon.asseco-see.com.tr/fim/est3Dgate', @@ -39,7 +49,8 @@ ], 'tosla' => [ 'name' => 'AkÖde A.Ş.', - 'class' => Mews\Pos\Gateways\ToslaPos::class, + 'class' => \Mews\Pos\Gateways\ToslaPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://prepentegrasyon.tosla.com/api/Payment', 'gateway_3d' => 'https://prepentegrasyon.tosla.com/api/Payment/ProcessCardForm', @@ -48,7 +59,8 @@ ], 'yapikredi' => [ 'name' => 'Yapıkredi', - 'class' => Mews\Pos\Gateways\PosNet::class, + 'class' => \Mews\Pos\Gateways\PosNet::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://setmpos.ykb.com/PosnetWebService/XML', 'gateway_3d' => 'https://setmpos.ykb.com/3DSWebService/YKBPaymentService', @@ -56,7 +68,8 @@ ], 'albaraka' => [ 'name' => 'Albaraka', - 'class' => Mews\Pos\Gateways\PosNetV1Pos::class, + 'class' => \Mews\Pos\Gateways\PosNetV1Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc', 'gateway_3d' => 'https://epostest.albarakaturk.com.tr/ALBSecurePaymentUI/SecureProcess/SecureVerification.aspx', @@ -64,7 +77,8 @@ ], 'garanti' => [ 'name' => 'Garanti', - 'class' => Mews\Pos\Gateways\GarantiPos::class, + 'class' => \Mews\Pos\Gateways\GarantiPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_configs' => [ // GarantiPos'u test ortamda test edebilmek için zorunlu. 'test_mode' => true, @@ -76,7 +90,8 @@ ], 'qnbfinansbank-payfor' => [ 'name' => 'QNBFinansbank-PayFor', - 'class' => Mews\Pos\Gateways\PayForPos::class, + 'class' => \Mews\Pos\Gateways\PayForPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', 'gateway_3d' => 'https://vpostest.qnbfinansbank.com/Gateway/Default.aspx', @@ -85,7 +100,8 @@ ], 'ziraat-katilim-payfor' => [ 'name' => 'ZiraatKatilim-PayFor', - 'class' => Mews\Pos\Gateways\PayForPos::class, + 'class' => \Mews\Pos\Gateways\PayForPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_configs' => [ // Ziraat Katilim için hash kontrolü çalışmıyor. O yüzden devre dışı bırakıyoruz. 'disable_3d_hash_check' => true, @@ -98,7 +114,8 @@ ], 'vakifbank' => [ 'name' => 'VakifBank-VPOS', - 'class' => Mews\Pos\Gateways\PayFlexV4Pos::class, + 'class' => \Mews\Pos\Gateways\PayFlexV4Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', 'gateway_3d' => 'https://3dsecuretest.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspx', @@ -107,7 +124,8 @@ ], 'ziraat-vpos' => [ 'name' => 'Ziraat Bankası', - 'class' => Mews\Pos\Gateways\PayFlexV4Pos::class, + 'class' => \Mews\Pos\Gateways\PayFlexV4Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://preprod.payflex.com.tr/Ziraatbank/VposWeb/v3/Vposreq.aspx', 'gateway_3d' => 'https://preprod.payflex.com.tr/ZiraatBank/MpiWeb/MPI_Enrollment.aspx', @@ -116,7 +134,8 @@ ], 'vakifbank-cp' => [ 'name' => 'VakifBank-PayFlex-Common-Payment', - 'class' => Mews\Pos\Gateways\PayFlexCPV4Pos::class, + 'class' => \Mews\Pos\Gateways\PayFlexCPV4Pos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', 'gateway_3d' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/RegisterTransaction', @@ -124,7 +143,8 @@ ], 'denizbank' => [ 'name' => 'DenizBank-InterPos', - 'class' => Mews\Pos\Gateways\InterPos::class, + 'class' => \Mews\Pos\Gateways\InterPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', 'gateway_3d' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', @@ -133,7 +153,8 @@ ], 'kuveytpos' => [ 'name' => 'kuveyt-pos', - 'class' => Mews\Pos\Gateways\KuveytPos::class, + 'class' => \Mews\Pos\Gateways\KuveytPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_configs' => [ // testinizi SSL olmayan ortamda yapıyorsanız bu değeri true yapmanız gerekir. 'test_mode' => true, @@ -141,12 +162,20 @@ 'gateway_endpoints' => [ 'payment_api' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home', 'gateway_3d' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate', - 'query_api' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + ], + 'kuveytsoappos' => [ + 'name' => 'KuveytSoapApiPos', + 'class' => \Mews\Pos\Gateways\KuveytSoapApiPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, + 'gateway_endpoints' => [ + 'query_api' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', ], ], 'vakif-katilim' => [ 'name' => 'Vakıf Katılım', - 'class' => Mews\Pos\Gateways\VakifKatilimPos::class, + 'class' => \Mews\Pos\Gateways\VakifKatilimPos::class, + 'lang' => \Mews\Pos\PosInterface::LANG_TR, 'gateway_endpoints' => [ 'payment_api' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home', 'gateway_3d' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', diff --git a/docs/CANCEL-EXAMPLE.md b/docs/CANCEL-EXAMPLE.md index 538c99b1..bea03d07 100644 --- a/docs/CANCEL-EXAMPLE.md +++ b/docs/CANCEL-EXAMPLE.md @@ -20,8 +20,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', \Mews\Pos\PosInterface::MODEL_NON_SECURE, - '', // bankaya göre zorunlu - \Mews\Pos\PosInterface::LANG_TR + '' // bankaya göre zorunlu ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); @@ -53,7 +52,7 @@ function createCancelOrder(string $gatewayClass, array $lastResponse, string $ip if (\Mews\Pos\Gateways\GarantiPos::class === $gatewayClass) { $cancelOrder['amount'] = $lastResponse['amount']; - } elseif (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + } elseif (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $cancelOrder['remote_order_id'] = $lastResponse['remote_order_id']; // banka tarafındaki order id $cancelOrder['auth_code'] = $lastResponse['auth_code']; $cancelOrder['transaction_id'] = $lastResponse['transaction_id']; diff --git a/docs/HISTORY-EXAMPLE.md b/docs/HISTORY-EXAMPLE.md index 218a9902..6b6e8f53 100644 --- a/docs/HISTORY-EXAMPLE.md +++ b/docs/HISTORY-EXAMPLE.md @@ -20,8 +20,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', \Mews\Pos\PosInterface::MODEL_NON_SECURE, - '', // bankaya göre zorunlu - \Mews\Pos\PosInterface::LANG_TR + '' // bankaya göre zorunlu ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); diff --git a/docs/NON-SECURE-PAYMENT-EXAMPLE.md b/docs/NON-SECURE-PAYMENT-EXAMPLE.md index 1e9c6aa6..01eee52c 100644 --- a/docs/NON-SECURE-PAYMENT-EXAMPLE.md +++ b/docs/NON-SECURE-PAYMENT-EXAMPLE.md @@ -23,8 +23,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', $paymentModel, - '', // bankaya göre zorunlu - \Mews\Pos\PosInterface::LANG_TR + '' // bankaya göre zorunlu ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); @@ -53,8 +52,8 @@ $order = [ 'currency' => \Mews\Pos\PosInterface::CURRENCY_TRY, //optional. default: TRY 'installment' => 0, //0 ya da 1'den büyük değer, optional. default: 0 - //lang degeri verilmezse account (EstPosAccount) dili kullanılacak - 'lang' => \Mews\Pos\Gateways\PosInterface::LANG_TR, // Kullanıcının yönlendirileceği banka gateway sayfasının ve gateway'den dönen mesajların dili. + // lang degeri verilmezse config'de tanimlanan dil veya default olarak LANG_TR kullanılacak. + 'lang' => \Mews\Pos\Gateways\PosInterface::LANG_TR, // Kullanıcının yönlendirileceği banka gateway sayfasının ve gateway'den dönen mesajların dili. ]; // Kredi kartı bilgileri diff --git a/docs/ORDER-HISTORY-EXAMPLE.md b/docs/ORDER-HISTORY-EXAMPLE.md index 0b1f9623..d32344bf 100644 --- a/docs/ORDER-HISTORY-EXAMPLE.md +++ b/docs/ORDER-HISTORY-EXAMPLE.md @@ -20,8 +20,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', \Mews\Pos\PosInterface::MODEL_NON_SECURE, - '', // bankaya göre zorunlu - \Mews\Pos\PosInterface::LANG_TR + '' // bankaya göre zorunlu ); $eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher(); diff --git a/docs/PRE-AUTH-POST-EXAMPLE.md b/docs/PRE-AUTH-POST-EXAMPLE.md index 75ea6b9f..1de188f1 100644 --- a/docs/PRE-AUTH-POST-EXAMPLE.md +++ b/docs/PRE-AUTH-POST-EXAMPLE.md @@ -32,8 +32,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', $paymentModel, - '', // bankaya göre zorunlu - \Mews\Pos\PosInterface::LANG_TR + '' // bankaya göre zorunlu ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); @@ -64,7 +63,8 @@ $order = [ 'amount' => 1.01, 'currency' => \Mews\Pos\PosInterface::CURRENCY_TRY, //optional. default: TRY 'installment' => 0, //0 ya da 1'den büyük değer, optional. default: 0 - // lang degeri verilmezse account (EstPosAccount) dili kullanılacak + + // lang degeri verilmezse config'de tanimlanan dil veya default olarak LANG_TR kullanılacak. 'lang' => \Mews\Pos\Gateways\PosInterface::LANG_TR, // Kullanıcının yönlendirileceği banka gateway sayfasının ve gateway'den dönen mesajların dili. ]; if ($pos instanceof \Mews\Pos\Gateways\ParamPos diff --git a/docs/QR-CODE-PAYMENT-EXAMPLE.md b/docs/QR-CODE-PAYMENT-EXAMPLE.md index ac1eecd8..be3037af 100644 --- a/docs/QR-CODE-PAYMENT-EXAMPLE.md +++ b/docs/QR-CODE-PAYMENT-EXAMPLE.md @@ -40,8 +40,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createPayForAccount( 'userCode', 'userPassword', $paymentModel, - 'merchantPass', - \Mews\Pos\PosInterface::LANG_TR + 'merchantPass' ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); @@ -75,7 +74,7 @@ $order = [ 'success_url' => 'https://example.com/response.php', 'fail_url' => 'https://example.com/response.php', - //lang degeri verilmezse account (EstPosAccount) dili kullanılacak + // lang degeri verilmezse config'de tanimlanan dil veya default olarak LANG_TR kullanılacak. 'lang' => \Mews\Pos\Gateways\PosInterface::LANG_TR, // Kullanıcının yönlendirileceği banka gateway sayfasının ve gateway'den dönen mesajların dili. ]; diff --git a/docs/REFUND-EXAMPLE.md b/docs/REFUND-EXAMPLE.md index 2193c110..3d3c718c 100644 --- a/docs/REFUND-EXAMPLE.md +++ b/docs/REFUND-EXAMPLE.md @@ -20,8 +20,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', \Mews\Pos\PosInterface::MODEL_NON_SECURE, - '', // bankaya göre zorunlu - \Mews\Pos\PosInterface::LANG_TR + '' // bankaya göre zorunlu ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); @@ -56,7 +55,7 @@ function createRefundOrder(string $gatewayClass, array $lastResponse, string $ip 'ip' => filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? $ip : '127.0.0.1', ]; - if (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + if (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $refundOrder['remote_order_id'] = $lastResponse['remote_order_id']; // banka tarafındaki order id $refundOrder['auth_code'] = $lastResponse['auth_code']; $refundOrder['transaction_id'] = $lastResponse['transaction_id']; diff --git a/docs/STATUS-EXAMPLE.md b/docs/STATUS-EXAMPLE.md index df61a735..4eadc220 100644 --- a/docs/STATUS-EXAMPLE.md +++ b/docs/STATUS-EXAMPLE.md @@ -20,8 +20,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', \Mews\Pos\PosInterface::MODEL_NON_SECURE, - '', // bankaya göre zorunlu - \Mews\Pos\PosInterface::LANG_TR + '' // bankaya göre zorunlu ); $eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher(); @@ -49,7 +48,7 @@ function createStatusOrder(string $gatewayClass, array $lastResponse, string $ip 'currency' => $lastResponse['currency'], 'ip' => filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? $ip : '127.0.0.1', ]; - if (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + if (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $statusOrder['remote_order_id'] = $lastResponse['remote_order_id']; // OrderId } if (\Mews\Pos\Gateways\PosNetV1Pos::class === $gatewayClass || \Mews\Pos\Gateways\PosNet::class === $gatewayClass) { diff --git a/docs/THREED-PAYMENT-EXAMPLE.md b/docs/THREED-PAYMENT-EXAMPLE.md index aa91c3dd..870cb312 100644 --- a/docs/THREED-PAYMENT-EXAMPLE.md +++ b/docs/THREED-PAYMENT-EXAMPLE.md @@ -40,8 +40,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', $paymentModel, - 'yourStoreKey', - \Mews\Pos\PosInterface::LANG_TR + 'yourStoreKey' ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); @@ -75,7 +74,7 @@ $order = [ 'success_url' => 'https://example.com/response.php', 'fail_url' => 'https://example.com/response.php', - //lang degeri verilmezse account (EstPosAccount) dili kullanılacak + // lang degeri verilmezse config'de tanimlanan dil veya default olarak LANG_TR kullanılacak. 'lang' => \Mews\Pos\Gateways\PosInterface::LANG_TR, // Kullanıcının yönlendirileceği banka gateway sayfasının ve gateway'den dönen mesajların dili. ]; diff --git a/docs/THREED-SECURE-AND-PAY-PAYMENT-IN-MODALBOX-EXAMPLE.md b/docs/THREED-SECURE-AND-PAY-PAYMENT-IN-MODALBOX-EXAMPLE.md index 2ab07dc6..6db50a6f 100644 --- a/docs/THREED-SECURE-AND-PAY-PAYMENT-IN-MODALBOX-EXAMPLE.md +++ b/docs/THREED-SECURE-AND-PAY-PAYMENT-IN-MODALBOX-EXAMPLE.md @@ -38,8 +38,7 @@ $account = \Mews\Pos\Factory\AccountFactory::createEstPosAccount( 'yourKullaniciAdi', 'yourSifre', $paymentModel, - 'yourStoreKey', - \Mews\Pos\PosInterface::LANG_TR + 'yourStoreKey' ); $eventDispatcher = new Symfony\Component\EventDispatcher\EventDispatcher(); @@ -101,7 +100,7 @@ $order = [ 'success_url' => 'https://example.com/response.php', 'fail_url' => 'https://example.com/response.php', - //lang degeri verilmezse account (EstPosAccount) dili kullanılacak + // lang degeri verilmezse config'de tanimlanan dil veya default olarak LANG_TR kullanılacak. 'lang' => \Mews\Pos\Gateways\PosInterface::LANG_TR, // Kullanıcının yönlendirileceği banka gateway sayfasının ve gateway'den dönen mesajların dili. ]; diff --git a/examples/_common-codes/regular/cancel.php b/examples/_common-codes/regular/cancel.php index 65332e52..b5a7a43c 100644 --- a/examples/_common-codes/regular/cancel.php +++ b/examples/_common-codes/regular/cancel.php @@ -26,7 +26,7 @@ function createCancelOrder(string $gatewayClass, array $lastResponse, string $ip $cancelOrder['amount'] = $lastResponse['amount']; // on otorizasyon islemin iptali icin PosInterface::TX_TYPE_PAY_PRE_AUTH saglanmasi gerekiyor $cancelOrder['transaction_type'] = $lastResponse['transaction_type'] ?? PosInterface::TX_TYPE_PAY_AUTH; - } elseif (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + } elseif (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $cancelOrder['remote_order_id'] = $lastResponse['remote_order_id']; // banka tarafındaki order id $cancelOrder['auth_code'] = $lastResponse['auth_code']; $cancelOrder['transaction_id'] = $lastResponse['transaction_id']; diff --git a/examples/_common-codes/regular/refund.php b/examples/_common-codes/regular/refund.php index 66e2ca4f..c8840dc5 100644 --- a/examples/_common-codes/regular/refund.php +++ b/examples/_common-codes/regular/refund.php @@ -25,7 +25,7 @@ function createRefundOrder(string $gatewayClass, array $lastResponse, string $ip 'ip' => filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? $ip : '127.0.0.1', ]; - if (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + if (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $refundOrder['remote_order_id'] = $lastResponse['remote_order_id']; // banka tarafındaki order id $refundOrder['auth_code'] = $lastResponse['auth_code']; $refundOrder['transaction_id'] = $lastResponse['transaction_id']; diff --git a/examples/_common-codes/regular/status.php b/examples/_common-codes/regular/status.php index 144355b6..4c248f65 100644 --- a/examples/_common-codes/regular/status.php +++ b/examples/_common-codes/regular/status.php @@ -17,7 +17,7 @@ function createStatusOrder(string $gatewayClass, array $lastResponse, string $ip 'currency' => $lastResponse['currency'], 'ip' => filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) ? $ip : '127.0.0.1', ]; - if (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + if (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $statusOrder['remote_order_id'] = $lastResponse['remote_order_id']; // OrderId } if (\Mews\Pos\Gateways\PosNetV1Pos::class === $gatewayClass || \Mews\Pos\Gateways\PosNet::class === $gatewayClass) { diff --git a/examples/_templates/_credit_card_form.php b/examples/_templates/_credit_card_form.php index a6324da7..8813b8f3 100644 --- a/examples/_templates/_credit_card_form.php +++ b/examples/_templates/_credit_card_form.php @@ -27,7 +27,7 @@ @@ -36,7 +36,7 @@ diff --git a/examples/_templates/_header.php b/examples/_templates/_header.php index a171fe0a..3b6ed6aa 100644 --- a/examples/_templates/_header.php +++ b/examples/_templates/_header.php @@ -31,6 +31,9 @@ + @@ -58,6 +61,9 @@ + diff --git a/examples/akbankpos/3d-host/_config.php b/examples/akbankpos/3d-host/_config.php index 04469014..5aa3de72 100644 --- a/examples/akbankpos/3d-host/_config.php +++ b/examples/akbankpos/3d-host/_config.php @@ -10,8 +10,7 @@ 'akbank-pos', '2023090417500272654BD9A49CF07574', '2023090417500284633D137A249DBBEB', - '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f', - PosInterface::LANG_TR + '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f' ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/akbankpos/3d-pay/_config.php b/examples/akbankpos/3d-pay/_config.php index 7f5a9b87..bf2d324e 100644 --- a/examples/akbankpos/3d-pay/_config.php +++ b/examples/akbankpos/3d-pay/_config.php @@ -10,8 +10,7 @@ 'akbank-pos', '2023090417500272654BD9A49CF07574', '2023090417500284633D137A249DBBEB', - '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f', - PosInterface::LANG_TR + '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f' ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/akbankpos/3d/_config.php b/examples/akbankpos/3d/_config.php index 2b0e3dc0..0edfd163 100644 --- a/examples/akbankpos/3d/_config.php +++ b/examples/akbankpos/3d/_config.php @@ -10,8 +10,7 @@ 'akbank-pos', '2023090417500272654BD9A49CF07574', '2023090417500284633D137A249DBBEB', - '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f', - PosInterface::LANG_TR, + '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f' ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/akbankpos/regular/_config.php b/examples/akbankpos/regular/_config.php index 156929bf..3f989e71 100644 --- a/examples/akbankpos/regular/_config.php +++ b/examples/akbankpos/regular/_config.php @@ -10,8 +10,7 @@ 'akbank-pos', '2023090417500272654BD9A49CF07574', '2023090417500284633D137A249DBBEB', - '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f', - PosInterface::LANG_TR + '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f' ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/finansbank-payfor/3d-host/_config.php b/examples/finansbank-payfor/3d-host/_config.php index eacace38..0a4bba40 100644 --- a/examples/finansbank-payfor/3d-host/_config.php +++ b/examples/finansbank-payfor/3d-host/_config.php @@ -13,7 +13,6 @@ 'UcBN0', PosInterface::MODEL_3D_HOST, '12345678', - PosInterface::LANG_TR, \Mews\Pos\Entity\Account\PayForAccount::MBR_ID_FINANSBANK // ya da PayForAccount::MBR_ID_ZIRAAT_KATILIM ); diff --git a/examples/finansbank-payfor/3d-pay/_config.php b/examples/finansbank-payfor/3d-pay/_config.php index 82b15e71..7aefc061 100644 --- a/examples/finansbank-payfor/3d-pay/_config.php +++ b/examples/finansbank-payfor/3d-pay/_config.php @@ -13,7 +13,6 @@ 'UcBN0', PosInterface::MODEL_3D_PAY, '12345678', - PosInterface::LANG_TR, \Mews\Pos\Entity\Account\PayForAccount::MBR_ID_FINANSBANK // ya da PayForAccount::MBR_ID_ZIRAAT_KATILIM ); diff --git a/examples/finansbank-payfor/3d/_config.php b/examples/finansbank-payfor/3d/_config.php index b80c3e2b..7b085026 100644 --- a/examples/finansbank-payfor/3d/_config.php +++ b/examples/finansbank-payfor/3d/_config.php @@ -13,7 +13,6 @@ 'UcBN0', PosInterface::MODEL_3D_SECURE, '12345678', - PosInterface::LANG_TR, \Mews\Pos\Entity\Account\PayForAccount::MBR_ID_FINANSBANK // ya da PayForAccount::MBR_ID_ZIRAAT_KATILIM ); diff --git a/examples/finansbank-payfor/qr/_config.php b/examples/finansbank-payfor/qr/_config.php index d839bcbe..e7827c91 100644 --- a/examples/finansbank-payfor/qr/_config.php +++ b/examples/finansbank-payfor/qr/_config.php @@ -14,7 +14,6 @@ 'IGhq8', PosInterface::MODEL_3D_HOST, '88921532', - PosInterface::LANG_TR, \Mews\Pos\Entity\Account\PayForAccount::MBR_ID_FINANSBANK // ya da PayForAccount::MBR_ID_ZIRAAT_KATILIM ); diff --git a/examples/finansbank-payfor/regular/_config.php b/examples/finansbank-payfor/regular/_config.php index e55d4843..cf9926fa 100644 --- a/examples/finansbank-payfor/regular/_config.php +++ b/examples/finansbank-payfor/regular/_config.php @@ -13,7 +13,6 @@ 'UcBN0', PosInterface::MODEL_NON_SECURE, null, - PosInterface::LANG_TR, \Mews\Pos\Entity\Account\PayForAccount::MBR_ID_FINANSBANK // ya da PayForAccount::MBR_ID_ZIRAAT_KATILIM ); diff --git a/examples/interpos/3d-host/_config.php b/examples/interpos/3d-host/_config.php index 3bf641f1..21fb5610 100644 --- a/examples/interpos/3d-host/_config.php +++ b/examples/interpos/3d-host/_config.php @@ -18,8 +18,7 @@ $userCode, $userPass, PosInterface::MODEL_3D_HOST, - $merchantPass, - PosInterface::LANG_TR + $merchantPass ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/interpos/3d-pay/_config.php b/examples/interpos/3d-pay/_config.php index 9b6747ae..d11e6620 100644 --- a/examples/interpos/3d-pay/_config.php +++ b/examples/interpos/3d-pay/_config.php @@ -16,8 +16,7 @@ $userCode, $userPass, PosInterface::MODEL_3D_PAY, - $merchantPass, - PosInterface::LANG_TR + $merchantPass ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/interpos/3d/_config.php b/examples/interpos/3d/_config.php index def6f3ec..21bf03da 100644 --- a/examples/interpos/3d/_config.php +++ b/examples/interpos/3d/_config.php @@ -16,8 +16,7 @@ $userCode, $userPass, PosInterface::MODEL_3D_SECURE, - $merchantPass, - PosInterface::LANG_TR + $merchantPass ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/kuveytsoappos/_payment_config.php b/examples/kuveytsoappos/_payment_config.php new file mode 100644 index 00000000..5230911b --- /dev/null +++ b/examples/kuveytsoappos/_payment_config.php @@ -0,0 +1,6 @@ + [ 'number' => '5456165456165454', - 'year' => '26', - 'month' => '12', - 'cvv' => '000', - 'name' => 'John Doe', + 'year' => '26', + 'month' => '12', + 'cvv' => '000', + 'name' => 'John Doe', ], // 'visa1' => [ // non secure USD/doviz odeme karti // 'number' => '4546711234567894', diff --git a/examples/payten/3d-host/_config.php b/examples/payten/3d-host/_config.php index b1974014..fee7bd43 100644 --- a/examples/payten/3d-host/_config.php +++ b/examples/payten/3d-host/_config.php @@ -12,8 +12,7 @@ 'ISBANKAPI', 'ISBANK07', PosInterface::MODEL_3D_HOST, - 'TRPS0200', - PosInterface::LANG_TR + 'TRPS0200' ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/payten/3d-pay-hosting/_config.php b/examples/payten/3d-pay-hosting/_config.php index 30ec43d8..5e91050f 100644 --- a/examples/payten/3d-pay-hosting/_config.php +++ b/examples/payten/3d-pay-hosting/_config.php @@ -12,8 +12,7 @@ 'ISBANKAPI', 'ISBANK07', PosInterface::MODEL_3D_PAY_HOSTING, - 'TRPS0200', - PosInterface::LANG_TR + 'TRPS0200' ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/payten/3d-pay/_config.php b/examples/payten/3d-pay/_config.php index 03b6bb5b..95ce5665 100644 --- a/examples/payten/3d-pay/_config.php +++ b/examples/payten/3d-pay/_config.php @@ -12,8 +12,7 @@ 'ISBANKAPI', 'ISBANK07', PosInterface::MODEL_3D_PAY, - 'TRPS0200', - PosInterface::LANG_TR + 'TRPS0200' ); $pos = getGateway($account, $eventDispatcher); diff --git a/examples/payten/3d/_config.php b/examples/payten/3d/_config.php index aa0e717e..dc5802b8 100644 --- a/examples/payten/3d/_config.php +++ b/examples/payten/3d/_config.php @@ -12,8 +12,7 @@ 'ISBANKAPI', 'ISBANK07', PosInterface::MODEL_3D_SECURE, - 'TRPS0200', - PosInterface::LANG_TR + 'TRPS0200' ); $pos = getGateway($account, $eventDispatcher); diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 00000000..360c9491 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,34 @@ + + + Mews Pos coding standard + + src + tests + + + + + + + + + + */tests/* + + + */tests/* + + + */tests/* + + + */tests/* + + + + + */tests/* + */src/* + + + diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 72f6f8ab..3c937cc7 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,17 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Parameter \#1 \$body of method Psr\\Http\\Message\\MessageInterface\:\:withBody\(\) expects Psr\\Http\\Message\\StreamInterface, Psr\\Http\\Message\\StreamInterface\|null given\.$#' - identifier: argument.type - count: 1 - path: src/Client/HttpClient.php - - - - message: '#^Parameter \#1 \$content of method Psr\\Http\\Message\\StreamFactoryInterface\:\:createStream\(\) expects string, array\\|string given\.$#' - identifier: argument.type - count: 1 - path: src/Client/HttpClient.php - - message: '#^Default value of the parameter \#3 \$order \(array\{\}\) of method Mews\\Pos\\Crypt\\PosNetCrypt\:\:createHash\(\) is incompatible with type array\{amount\: int, currency\: string, id\: string\}\.$#' identifier: parameter.defaultValue @@ -25,16 +13,16 @@ parameters: path: src/Crypt/PosNetV1PosCrypt.php - - message: '#^Parameter \#1 \$currency of method Mews\\Pos\\DataMapper\\RequestDataMapper\\AkbankPosRequestDataMapper\:\:mapCurrency\(\) expects ''EUR''\|''GBP''\|''JPY''\|''RUB''\|''TRY''\|''USD'', string given\.$#' + message: '#^Parameter \#1 \$installment of method Mews\\Pos\\DataMapper\\RequestValueFormatter\\ParamPosRequestValueFormatter\:\:formatInstallment\(\) expects int\<0, max\>, int given\.$#' identifier: argument.type - count: 5 - path: src/DataMapper/RequestDataMapper/AkbankPosRequestDataMapper.php + count: 1 + path: src/DataMapper/RequestDataMapper/Param3DHostPosRequestDataMapper.php - - message: '#^Parameter \#1 \$currency of method Mews\\Pos\\DataMapper\\RequestDataMapper\\EstPosRequestDataMapper\:\:mapCurrency\(\) expects ''EUR''\|''GBP''\|''JPY''\|''RUB''\|''TRY''\|''USD'', string given\.$#' + message: '#^Parameter \#1 \$installment of method Mews\\Pos\\DataMapper\\RequestValueFormatter\\ParamPosRequestValueFormatter\:\:formatInstallment\(\) expects int\<0, max\>, int given\.$#' identifier: argument.type - count: 1 - path: src/DataMapper/RequestDataMapper/EstPosRequestDataMapper.php + count: 2 + path: src/DataMapper/RequestDataMapper/ParamPosRequestDataMapper.php - message: '#^Default value of the parameter \#7 \$extraData \(array\{\}\) of method Mews\\Pos\\DataMapper\\RequestDataMapper\\PayFlexCPV4PosRequestDataMapper\:\:create3DFormData\(\) is incompatible with type array\{CommonPaymentUrl\: string, PaymentToken\: string\}\.$#' @@ -90,12 +78,6 @@ parameters: count: 1 path: src/DataMapper/RequestDataMapper/PosNetRequestDataMapper.php - - - message: '#^Method Mews\\Pos\\DataMapper\\RequestDataMapper\\PosNetRequestDataMapper\:\:create3DEnrollmentCheckRequestData\(\) return type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/DataMapper/RequestDataMapper/PosNetRequestDataMapper.php - - message: '#^Method Mews\\Pos\\DataMapper\\RequestDataMapper\\PosNetV1PosRequestDataMapper\:\:create3DFormData\(\) has parameter \$extraData with no type specified\.$#' identifier: missingType.parameter @@ -108,12 +90,6 @@ parameters: count: 1 path: src/DataMapper/ResponseDataMapper/AbstractResponseDataMapper.php - - - message: '#^Possibly invalid array key type string\|null\.$#' - identifier: offsetAccess.invalidOffset - count: 1 - path: src/DataMapper/ResponseDataMapper/EstPosResponseDataMapper.php - - message: '#^Offset ''ErrorMsg'' might not exist on array\\|string\.$#' identifier: offsetAccess.notFound @@ -138,30 +114,6 @@ parameters: count: 1 path: src/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapper.php - - - message: '#^Property Mews\\Pos\\DataMapper\\ResponseDataMapper\\AbstractResponseDataMapper\:\:\$secureTypeMappings \(array\\) does not accept non\-empty\-array\<1\|2\|3\|string, ''3d''\|''3d_host''\|''3d_pay''\|''3d_pay_hosting''\|''regular''\>\.$#' - identifier: assign.propertyType - count: 1 - path: src/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapper.php - - - - message: '#^Possibly invalid array key type string\|null\.$#' - identifier: offsetAccess.invalidOffset - count: 1 - path: src/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapper.php - - - - message: '#^Property Mews\\Pos\\DataMapper\\ResponseDataMapper\\AbstractResponseDataMapper\:\:\$currencyMappings \(array\\) does not accept non\-empty\-array\<392\|643\|826\|840\|949\|978\|string, ''EUR''\|''GBP''\|''JPY''\|''RUB''\|''TRY''\|''USD''\>\.$#' - identifier: assign.propertyType - count: 1 - path: src/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapper.php - - - - message: '#^Possibly invalid array key type string\|null\.$#' - identifier: offsetAccess.invalidOffset - count: 2 - path: src/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapper.php - - message: '#^Strict comparison using \=\=\= between ''3d_host'' and ''3d_host'' will always evaluate to true\.$#' identifier: identical.alwaysTrue diff --git a/src/Client/AbstractHttpClient.php b/src/Client/AbstractHttpClient.php new file mode 100644 index 00000000..1e4713b2 --- /dev/null +++ b/src/Client/AbstractHttpClient.php @@ -0,0 +1,236 @@ +baseApiUrl = $baseApiUrl; + $this->psrClient = $psrClient; + $this->requestFactory = $requestFactory; + $this->streamFactory = $streamFactory; + $this->serializer = $serializer; + $this->logger = $logger; + } + + /** + * @param PosInterface::TX_TYPE_*|null $txType + * @param PosInterface::MODEL_* |null $paymentModel + * @param PosInterface::TX_TYPE_PAY_*|null $orderTxType + * + * @return non-empty-string + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string + { + return $this->baseApiUrl; + } + + /** + * @inheritDoc + * + * @throws \Exception + */ + public function request( + string $txType, + string $paymentModel, + array $requestData, + array $order, + ?string $url = null, + ?AbstractPosAccount $account = null + ) { + $content = $this->serializer->encode($requestData, $txType); + + return $this->doRequest( + $txType, + $paymentModel, + $content, + $order, + $url, + $account + ); + } + + /** + * @param PosInterface::TX_TYPE_* $txType + * @param PosInterface::MODEL_* $paymentModel + * @param EncodedData $content + * @param array $order + * @param non-empty-string|null $url + * @param AbstractPosAccount|null $account + * + * @return ($decode is true ? array : string) + * + * @throws UnsupportedTransactionTypeException + * @throws NotEncodableValueException + * @throws ClientExceptionInterface + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + public function doRequest( + string $txType, + string $paymentModel, + EncodedData $content, + array $order, + ?string $url = null, + ?AbstractPosAccount $account = null, + bool $decode = true + ) { + + try { + $url ??= $this->getApiURL($txType, $paymentModel, $order['transaction_type'] ?? null); + } catch (\Exception $e) { + $msg = \sprintf('%s işlemi için API URL oluşturulamadı! API URL sağlayıp deneyiniz.', $txType); + $this->logger->error($msg, [ + 'api_url' => $url, + 'txType' => $txType, + 'paymentModel' => $paymentModel, + 'orderTxType' => $order['transaction_type'] ?? null, + 'exception' => $e, + ]); + + throw $e; + } + + $request = $this->createRequest($url, $content, $txType, $account); + + $this->logger->debug('sending request', ['url' => $url]); + + $response = $this->psrClient->sendRequest($request); + + $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); + + if ($response->getStatusCode() === 204) { + $this->logger->warning('Response from api is empty', [ + 'url' => $url, + 'tx_type' => $txType, + 'status_code' => $response->getStatusCode(), + ]); + + return []; + } + + $this->checkFailResponse($txType, $response, $order); + $response->getBody()->rewind(); + + if ($decode) { + try { + $decodedData = $this->serializer->decode($response->getBody()->getContents(), $txType); + } catch (NotEncodableValueException $notEncodableValueException) { + $response->getBody()->rewind(); + $this->logger->error('parsing bank response failed', [ + 'status_code' => $response->getStatusCode(), + 'response' => $response->getBody()->getContents(), + 'message' => $notEncodableValueException->getMessage(), + ]); + + throw $notEncodableValueException; + } + $this->checkFailResponseData($txType, $response, $decodedData, $order); + + return $decodedData; + } + + return $response->getBody()->getContents(); + } + + /** + * @param non-empty-string $url + * @param EncodedData $content + * @param PosInterface::TX_TYPE_* $txType + * @param AbstractPosAccount|null $account + * + * @return RequestInterface + */ + abstract protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface; + + /** + * Checks API response before decoding it. + * + * @param PosInterface::TX_TYPE_* $txType + * @param ResponseInterface $response + * @param array $order + * + * @throws \RuntimeException when request fails + */ + protected function checkFailResponse(string $txType, ResponseInterface $response, array $order): void + { + if ($response->getStatusCode() >= 500) { + $this->logger->error('Api request failed!', [ + 'status_code' => $response->getStatusCode(), + 'response' => $response->getBody()->getContents(), + 'tx_type' => $txType, + 'order' => $order, + ]); + throw new \RuntimeException('İstek Başarısız!', $response->getStatusCode()); + } + } + + + /** + * Checks API response data after decoding it. + * + * @param PosInterface::TX_TYPE_* $txType + * @param ResponseInterface $response + * @param array $responseData + * @param array $order + * + * @throws \RuntimeException when response is not successful + */ + protected function checkFailResponseData(string $txType, ResponseInterface $response, array $responseData, array $order): void + { + } +} diff --git a/src/Client/AkbankPosHttpClient.php b/src/Client/AkbankPosHttpClient.php new file mode 100644 index 00000000..ab09f030 --- /dev/null +++ b/src/Client/AkbankPosHttpClient.php @@ -0,0 +1,128 @@ +crypt = $crypt; + } + + /** + * @inheritDoc + */ + public function supportsTx(string $txType, string $paymentModel, ?string $orderTxType = null): bool + { + return true; + } + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass, string $apiName): bool + { + return AkbankPos::class === $gatewayClass && HttpClientInterface::API_NAME_PAYMENT_API === $apiName; + } + + /** + * @inheritDoc + * + * @throws \InvalidArgumentException when a transaction type is not provided + */ + public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string + { + if (null !== $txType) { + return $this->baseApiUrl.'/'.$this->getRequestURIByTransactionType($txType); + } + + throw new \InvalidArgumentException('Transaction type is required to generate API URL'); + } + + /** + * @inheritDoc + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + if (!$account instanceof AbstractPosAccount) { + throw new \InvalidArgumentException('Account is required to create request hash'); + } + + $body = $this->streamFactory->createStream($content->getData()); + $hash = $this->crypt->hashString($content->getData(), $account->getStoreKey()); + + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'application/json') + ->withHeader('auth-hash', $hash) + ->withBody($body); + } + + /** + * @inheritDoc + */ + protected function checkFailResponseData(string $txType, ResponseInterface $response, array $responseData, array $order): void + { + // when the data is sent fails validation checks we get 400 error + if ($response->getStatusCode() >= 400) { + $this->logger->error('api error', [ + 'status_code' => $response->getStatusCode(), + 'order' => $order, + 'tx_type' => $txType, + 'response' => $response->getBody()->getContents(), + ]); + + $response->getBody()->rewind(); + + throw new \RuntimeException($responseData['message'], $responseData['code']); + } + } + + /** + * @param PosInterface::TX_TYPE_* $txType + * + * @return string + */ + private function getRequestURIByTransactionType(string $txType): string + { + $arr = [ + PosInterface::TX_TYPE_HISTORY => 'portal/report/transaction', + ]; + + return $arr[$txType] ?? 'transaction/process'; + } +} diff --git a/src/Client/EstPosHttpClient.php b/src/Client/EstPosHttpClient.php new file mode 100644 index 00000000..ddd173ed --- /dev/null +++ b/src/Client/EstPosHttpClient.php @@ -0,0 +1,44 @@ +streamFactory->createStream($content->getData()); + + return $this->requestFactory->createRequest('POST', $url) + ->withBody($body); + } +} diff --git a/src/Client/GarantiPosHttpClient.php b/src/Client/GarantiPosHttpClient.php new file mode 100644 index 00000000..5fbe5390 --- /dev/null +++ b/src/Client/GarantiPosHttpClient.php @@ -0,0 +1,42 @@ +streamFactory->createStream($content->getData()); + + return $this->requestFactory->createRequest('POST', $url) + ->withBody($body); + } +} diff --git a/src/Client/GenericPosHttpClientStrategy.php b/src/Client/GenericPosHttpClientStrategy.php new file mode 100644 index 00000000..dd129b4b --- /dev/null +++ b/src/Client/GenericPosHttpClientStrategy.php @@ -0,0 +1,37 @@ + + */ + private array $clients; + + /** + * @param array $clients + */ + public function __construct(array $clients) + { + $this->clients = $clients; + } + + /** + * @inheritDoc + */ + public function getClient(string $txType, string $paymentModel): HttpClientInterface + { + foreach ($this->clients as $client) { + if ($client->supportsTx($txType, $paymentModel)) { + return $client; + } + } + + throw new \InvalidArgumentException("No HTTP client configured for transaction type: $txType"); + } +} diff --git a/src/Client/HttpClient.php b/src/Client/HttpClient.php deleted file mode 100644 index 518facec..00000000 --- a/src/Client/HttpClient.php +++ /dev/null @@ -1,110 +0,0 @@ -|string, headers?: array, form_params?: array} - * PSR18 HTTP Client wrapper - */ -class HttpClient -{ - protected ClientInterface $client; - - protected RequestFactoryInterface $requestFactory; - - protected StreamFactoryInterface $streamFactory; - - /** - * @param ClientInterface $client - * @param RequestFactoryInterface $requestFactory - * @param StreamFactoryInterface $streamFactory - */ - public function __construct( - ClientInterface $client, - RequestFactoryInterface $requestFactory, - StreamFactoryInterface $streamFactory - ) { - $this->client = $client; - $this->requestFactory = $requestFactory; - $this->streamFactory = $streamFactory; - } - - /** - * @phpstan-param PostPayload|null $payload - * - * @param string $path - * @param array|null $payload - * - * @return ResponseInterface - * - * @throws ClientExceptionInterface - */ - public function post(string $path, ?array $payload = []): ResponseInterface - { - return $this->send('POST', $path, $payload); - } - - /** - * @phpstan-param PostPayload|null $payload - * - * @param string $method - * @param string $path - * @param array|null $payload - * - * @return ResponseInterface - * - * @throws ClientExceptionInterface - */ - private function send(string $method, string $path, ?array $payload = []): ResponseInterface - { - $request = $this->createRequest($method, $path, $payload); - - return $this->client->sendRequest($request); - } - - /** - * @phpstan-param PostPayload|null $payload - * - * @param array|null $payload - * - * @return RequestInterface - */ - private function createRequest(string $method, string $url, ?array $payload = []): RequestInterface - { - $request = $this->requestFactory->createRequest($method, $url); - - if ('POST' === $method) { - $body = null; - if (isset($payload['form_params'])) { - $request = $request->withHeader('Content-Type', 'application/x-www-form-urlencoded'); - $payload['body'] = \http_build_query($payload['form_params']); - } - - if (isset($payload['body'])) { - $body = $this->streamFactory->createStream($payload['body']); - } - - $request = $request->withBody($body); - } - - - if (isset($payload['headers'])) { - foreach ($payload['headers'] as $key => $value) { - $request = $request->withHeader($key, $value); - } - } - - return $request; - } -} diff --git a/src/Client/HttpClientInterface.php b/src/Client/HttpClientInterface.php new file mode 100644 index 00000000..ebebc491 --- /dev/null +++ b/src/Client/HttpClientInterface.php @@ -0,0 +1,68 @@ + $gatewayClass + * @param self::API_NAME_* $apiName + * + * @return bool + */ + public static function supports(string $gatewayClass, string $apiName): bool; + + /** + * @param PosInterface::TX_TYPE_* $txType + * @param PosInterface::MODEL_* $paymentModel + * @param array $requestData + * @param array $order + * @param non-empty-string|null $url + * @param AbstractPosAccount|null $account + * + * @return array|string + * + * @throws UnsupportedTransactionTypeException + * @throws NotEncodableValueException + * @throws ClientExceptionInterface + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + public function request(string $txType, string $paymentModel, array $requestData, array $order, ?string $url = null, ?AbstractPosAccount $account = null); +} diff --git a/src/Client/HttpClientStrategyInterface.php b/src/Client/HttpClientStrategyInterface.php new file mode 100644 index 00000000..86e6a467 --- /dev/null +++ b/src/Client/HttpClientStrategyInterface.php @@ -0,0 +1,20 @@ +streamFactory->createStream($content->getData()); + + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'application/x-www-form-urlencoded') + ->withBody($body); + } +} diff --git a/src/Client/KuveytPos3DFormHttpClient.php b/src/Client/KuveytPos3DFormHttpClient.php new file mode 100644 index 00000000..40dc043a --- /dev/null +++ b/src/Client/KuveytPos3DFormHttpClient.php @@ -0,0 +1,68 @@ +serializer->encode($requestData, $txType); + + return $this->doRequest( + $txType, + $paymentModel, + $content, + $order, + $url, + $account, + false, + ); + } + + /** + * @return RequestInterface + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'text/xml; charset=UTF-8') + ->withBody($body); + } +} diff --git a/src/Client/KuveytPosHttpClient.php b/src/Client/KuveytPosHttpClient.php new file mode 100644 index 00000000..bc7d3615 --- /dev/null +++ b/src/Client/KuveytPosHttpClient.php @@ -0,0 +1,94 @@ +getRequestURIByTransactionType($txType, $paymentModel); + } catch (UnsupportedTransactionTypeException $e) { + return false; + } + + return true; + } + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass, string $apiName): bool + { + return KuveytPos::class === $gatewayClass && HttpClientInterface::API_NAME_PAYMENT_API === $apiName; + } + + /** + * @inheritDoc + * + * @throws UnsupportedTransactionTypeException + * @throws \InvalidArgumentException when a transaction type is not provided + */ + public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string + { + if (null !== $txType && null !== $paymentModel) { + return $this->baseApiUrl.'/'.$this->getRequestURIByTransactionType($txType, $paymentModel); + } + + throw new \InvalidArgumentException('Transaction type is required to generate API URL'); + } + + /** + * @return RequestInterface + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'text/xml; charset=UTF-8') + ->withBody($body); + } + + /** + * @phpstan-param PosInterface::TX_TYPE_* $txType + * @phpstan-param PosInterface::MODEL_* $paymentModel + * + * @return string + * + * @throws UnsupportedTransactionTypeException + */ + private function getRequestURIByTransactionType(string $txType, string $paymentModel): string + { + $arr = [ + PosInterface::TX_TYPE_PAY_AUTH => [ + PosInterface::MODEL_NON_SECURE => 'Non3DPayGate', + PosInterface::MODEL_3D_SECURE => 'ThreeDModelProvisionGate', + ], + ]; + + if (!isset($arr[$txType])) { + throw new UnsupportedTransactionTypeException(); + } + + if (!isset($arr[$txType][$paymentModel])) { + throw new UnsupportedTransactionTypeException(); + } + + return $arr[$txType][$paymentModel]; + } +} diff --git a/src/Client/KuveytSoapApiPosHttpClient.php b/src/Client/KuveytSoapApiPosHttpClient.php new file mode 100644 index 00000000..00615142 --- /dev/null +++ b/src/Client/KuveytSoapApiPosHttpClient.php @@ -0,0 +1,125 @@ +requestValueMapper = $requestValueMapper; + } + + /** + * @inheritDoc + */ + public function supportsTx(string $txType, string $paymentModel, ?string $orderTxType = null): bool + { + return \in_array($txType, [ + PosInterface::TX_TYPE_STATUS, + PosInterface::TX_TYPE_CANCEL, + PosInterface::TX_TYPE_REFUND, + PosInterface::TX_TYPE_REFUND_PARTIAL, + ], true); + } + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass, string $apiName): bool + { + return KuveytSoapApiPos::class === $gatewayClass && HttpClientInterface::API_NAME_QUERY_API === $apiName; + } + + /** + * @return RequestInterface + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + $soapActionHeader = 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/'.$this->requestValueMapper->mapTxType($txType); + + return $request->withHeader('Content-Type', 'text/xml; charset=UTF-8') + ->withHeader('SOAPAction', $soapActionHeader) + ->withBody($body); + } + + /** + * @inheritDoc + */ + protected function checkFailResponse(string $txType, ResponseInterface $response, array $order): void + { + $responseContent = $response->getBody()->getContents(); + if ('' === $responseContent) { + $this->logger->error('Api request failed!', [ + 'status_code' => $response->getStatusCode(), + 'tx_type' => $txType, + 'order' => $order, + ]); + + throw new \RuntimeException('Bankaya istek başarısız!', $response->getStatusCode()); + } + } + + + /** + * @inheritDoc + */ + protected function checkFailResponseData(string $txType, ResponseInterface $response, array $responseData, array $order): void + { + if (isset($responseData['s:Fault'])) { + $this->logger->error('soap error response', [ + 'status_code' => $response->getStatusCode(), + 'response' => $responseData, + 'tx_type' => $txType, + 'order' => $order, + ]); + + throw new \RuntimeException( + $responseData['s:Fault']['faultstring']['#'] ?? 'Bankaya istek başarısız!', + $response->getStatusCode() + ); + } + } +} diff --git a/src/Client/ParamPosHttpClient.php b/src/Client/ParamPosHttpClient.php new file mode 100644 index 00000000..e16b9178 --- /dev/null +++ b/src/Client/ParamPosHttpClient.php @@ -0,0 +1,64 @@ +streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'text/xml') + ->withBody($body); + } + + /** + * @inheritDoc + */ + protected function checkFailResponseData(string $txType, ResponseInterface $response, array $responseData, array $order): void + { + if (isset($responseData['soap:Fault'])) { + $this->logger->error('soap error response', [ + 'status_code' => $response->getStatusCode(), + 'response' => $responseData, + 'order' => $order, + 'tx_type' => $txType, + ]); + + throw new \RuntimeException($responseData['soap:Fault']['faultstring'] ?? 'Bankaya istek başarısız!'); + } + } +} diff --git a/src/Client/PayFlexCPV4Pos3DFormHttpClient.php b/src/Client/PayFlexCPV4Pos3DFormHttpClient.php new file mode 100644 index 00000000..c6ffb8b8 --- /dev/null +++ b/src/Client/PayFlexCPV4Pos3DFormHttpClient.php @@ -0,0 +1,45 @@ +requestFactory->createRequest('POST', $url); + $body = $this->streamFactory->createStream($content->getData()); + + return $request->withHeader('Content-Type', 'application/x-www-form-urlencoded') + ->withHeader('Accept', 'text/xml') + ->withBody($body); + } +} diff --git a/src/Client/PayFlexCPV4PosHttpClient.php b/src/Client/PayFlexCPV4PosHttpClient.php new file mode 100644 index 00000000..46ae57eb --- /dev/null +++ b/src/Client/PayFlexCPV4PosHttpClient.php @@ -0,0 +1,45 @@ +requestFactory->createRequest('POST', $url); + $body = $this->streamFactory->createStream($content->getData()); + + return $request->withHeader('Content-Type', 'application/x-www-form-urlencoded') + ->withHeader('Accept', 'text/xml') + ->withBody($body); + } +} diff --git a/src/Client/PayFlexV4Pos3DFormHttpClient.php b/src/Client/PayFlexV4Pos3DFormHttpClient.php new file mode 100644 index 00000000..713b4747 --- /dev/null +++ b/src/Client/PayFlexV4Pos3DFormHttpClient.php @@ -0,0 +1,71 @@ +doRequest( + $txType, + $paymentModel, + $content, + $order, + $url, + $account + ); + } + + /** + * @inheritDoc + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'application/x-www-form-urlencoded') + ->withBody($body); + } +} diff --git a/src/Client/PayFlexV4PosHttpClient.php b/src/Client/PayFlexV4PosHttpClient.php new file mode 100644 index 00000000..d351e582 --- /dev/null +++ b/src/Client/PayFlexV4PosHttpClient.php @@ -0,0 +1,72 @@ +serializer->encode($requestData, $txType); + $content = new EncodedData( + \http_build_query(['prmstr' => $content->getData()]), + SerializerInterface::FORMAT_FORM + ); + + return $this->doRequest( + $txType, + $paymentModel, + $content, + $order, + $url, + $account + ); + } + + /** + * @inheritDoc + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'application/x-www-form-urlencoded') + ->withBody($body); + } +} diff --git a/src/Client/PayFlexV4PosSearchApiHttpClient.php b/src/Client/PayFlexV4PosSearchApiHttpClient.php new file mode 100644 index 00000000..88c01d29 --- /dev/null +++ b/src/Client/PayFlexV4PosSearchApiHttpClient.php @@ -0,0 +1,72 @@ +serializer->encode($requestData, $txType); + $content = new EncodedData( + \http_build_query(['prmstr' => $content->getData()]), + SerializerInterface::FORMAT_FORM + ); + + return $this->doRequest( + $txType, + $paymentModel, + $content, + $order, + $url, + $account + ); + } + + /** + * @inheritDoc + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'application/x-www-form-urlencoded') + ->withBody($body); + } +} diff --git a/src/Client/PayForPosHttpClient.php b/src/Client/PayForPosHttpClient.php new file mode 100644 index 00000000..bd8f7e73 --- /dev/null +++ b/src/Client/PayForPosHttpClient.php @@ -0,0 +1,44 @@ +streamFactory->createStream($content->getData()); + + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'text/xml; charset=UTF-8') + ->withBody($body); + } +} diff --git a/src/Client/PosNetPosHttpClient.php b/src/Client/PosNetPosHttpClient.php new file mode 100644 index 00000000..2b01595f --- /dev/null +++ b/src/Client/PosNetPosHttpClient.php @@ -0,0 +1,71 @@ +serializer->encode($requestData, $txType); + $content = new EncodedData( + \sprintf('xmldata=%s', $content->getData()), + SerializerInterface::FORMAT_FORM + ); + + return $this->doRequest( + $txType, + $paymentModel, + $content, + $order, + $url, + $account + ); + } + + /** + * @inheritDoc + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'application/x-www-form-urlencoded') + ->withBody($body); + } +} diff --git a/src/Client/PosNetV1PosHttpClient.php b/src/Client/PosNetV1PosHttpClient.php new file mode 100644 index 00000000..c44e4fd8 --- /dev/null +++ b/src/Client/PosNetV1PosHttpClient.php @@ -0,0 +1,114 @@ +requestValueMapper = $requestValueMapper; + } + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass, string $apiName): bool + { + return PosNetV1Pos::class === $gatewayClass && HttpClientInterface::API_NAME_PAYMENT_API === $apiName; + } + + /** + * @inheritDoc + */ + public function supportsTx(string $txType, string $paymentModel, ?string $orderTxType = null): bool + { + try { + $this->getRequestURIByTransactionType($txType); + } catch (UnsupportedTransactionTypeException $e) { + return false; + } + + return true; + } + + /** + * @inheritDoc + * + * @throws UnsupportedTransactionTypeException + * @throws \InvalidArgumentException when a transaction type is not provided + */ + public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string + { + if (null !== $txType) { + return $this->baseApiUrl.'/'.$this->getRequestURIByTransactionType($txType); + } + + throw new \InvalidArgumentException('Transaction type is required to generate API URL'); + } + + + /** + * @inheritDoc + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request + ->withHeader('Content-Type', 'application/json') + ->withBody($body); + } + + /** + * @phpstan-param PosInterface::TX_TYPE_* $txType + * + * @return string + * + * @throws UnsupportedTransactionTypeException + */ + private function getRequestURIByTransactionType(string $txType): string + { + return $this->requestValueMapper->mapTxType($txType); + } +} diff --git a/src/Client/ToslaPosHttpClient.php b/src/Client/ToslaPosHttpClient.php new file mode 100644 index 00000000..92b6ade8 --- /dev/null +++ b/src/Client/ToslaPosHttpClient.php @@ -0,0 +1,110 @@ +getRequestURIByTransactionType($txType, $paymentModel); + } catch (UnsupportedTransactionTypeException $e) { + return false; + } + + return true; + } + + /** + * @inheritDoc + * + * @throws UnsupportedTransactionTypeException + * @throws \InvalidArgumentException when a transaction type or payment model are not provided + */ + public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string + { + if (null !== $txType && null !== $paymentModel) { + return $this->baseApiUrl.'/'.$this->getRequestURIByTransactionType($txType, $paymentModel); + } + + throw new \InvalidArgumentException('Transaction type and payment model are required to generate API URL'); + } + + /** + * @inheritDoc + */ + protected function createRequest(string $url, EncodedData $content, string $txType, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'application/json') + ->withBody($body); + } + + /** + * @phpstan-param PosInterface::TX_TYPE_* $txType + * @phpstan-param PosInterface::MODEL_* $paymentModel + * + * @return string + * + * @throws UnsupportedTransactionTypeException + */ + private function getRequestURIByTransactionType(string $txType, string $paymentModel): string + { + $arr = [ + PosInterface::TX_TYPE_PAY_AUTH => [ + PosInterface::MODEL_NON_SECURE => 'Payment', + PosInterface::MODEL_3D_PAY => 'threeDPayment', + PosInterface::MODEL_3D_HOST => 'threeDPayment', + ], + PosInterface::TX_TYPE_PAY_PRE_AUTH => [ + PosInterface::MODEL_3D_PAY => 'threeDPreAuth', + PosInterface::MODEL_3D_HOST => 'threeDPreAuth', + ], + PosInterface::TX_TYPE_PAY_POST_AUTH => 'postAuth', + PosInterface::TX_TYPE_CANCEL => 'void', + PosInterface::TX_TYPE_REFUND => 'refund', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'refund', + PosInterface::TX_TYPE_STATUS => 'inquiry', + PosInterface::TX_TYPE_ORDER_HISTORY => 'history', + ]; + + if (!isset($arr[$txType])) { + throw new UnsupportedTransactionTypeException(); + } + + if (\is_string($arr[$txType])) { + return $arr[$txType]; + } + + if (!isset($arr[$txType][$paymentModel])) { + throw new UnsupportedTransactionTypeException(); + } + + return $arr[$txType][$paymentModel]; + } +} diff --git a/src/Client/VakifKatilimPos3DFormHttpClient.php b/src/Client/VakifKatilimPos3DFormHttpClient.php new file mode 100644 index 00000000..b7c8ad84 --- /dev/null +++ b/src/Client/VakifKatilimPos3DFormHttpClient.php @@ -0,0 +1,69 @@ +serializer->encode($requestData, $txType); + + return $this->doRequest( + $txType, + $paymentModel, + $content, + $order, + $url, + $account, + false, + ); + } + + /** + * @return RequestInterface + */ + protected function createRequest(string $url, EncodedData $content, ?string $txType = null, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'text/xml; charset=UTF-8') + ->withBody($body); + } +} diff --git a/src/Client/VakifKatilimPosHttpClient.php b/src/Client/VakifKatilimPosHttpClient.php new file mode 100644 index 00000000..4edd0163 --- /dev/null +++ b/src/Client/VakifKatilimPosHttpClient.php @@ -0,0 +1,137 @@ +getRequestURIByTransactionType($txType, $paymentModel); + } catch (UnsupportedTransactionTypeException $e) { + return false; + } + + return true; + } + + /** + * @inheritDoc + * + * @throws UnsupportedTransactionTypeException + * @throws \InvalidArgumentException when a transaction type or a payment model are not provided + */ + public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string + { + if (null !== $txType && null !== $paymentModel) { + return $this->baseApiUrl.'/'.$this->getRequestURIByTransactionType($txType, $paymentModel, $orderTxType); + } + + throw new \InvalidArgumentException('Transaction type and payment model are required to generate API URL'); + } + + /** + * @return RequestInterface + */ + protected function createRequest(string $url, EncodedData $content, ?string $txType = null, ?AbstractPosAccount $account = null): RequestInterface + { + $body = $this->streamFactory->createStream($content->getData()); + $request = $this->requestFactory->createRequest('POST', $url); + + return $request->withHeader('Content-Type', 'text/xml; charset=UTF-8') + ->withBody($body); + } + + /** + * @phpstan-param PosInterface::TX_TYPE_* $txType + * @phpstan-param PosInterface::MODEL_* $paymentModel + * @phpstan-param PosInterface::TX_TYPE_PAY_* $orderTxType + * + * @return non-empty-string + * + * @throws UnsupportedTransactionTypeException + */ + private function getRequestURIByTransactionType(string $txType, string $paymentModel, ?string $orderTxType = null): string + { + $orderTxType ??= PosInterface::TX_TYPE_PAY_AUTH; + + $arr = [ + PosInterface::TX_TYPE_PAY_AUTH => [ + PosInterface::MODEL_NON_SECURE => 'Non3DPayGate', + PosInterface::MODEL_3D_SECURE => 'ThreeDModelProvisionGate', + ], + PosInterface::TX_TYPE_PAY_PRE_AUTH => [ + PosInterface::MODEL_NON_SECURE => 'PreAuthorizaten', + ], + PosInterface::TX_TYPE_PAY_POST_AUTH => 'PreAuthorizatenClose', + PosInterface::TX_TYPE_CANCEL => [ + PosInterface::MODEL_NON_SECURE => [ + PosInterface::TX_TYPE_PAY_AUTH => 'SaleReversal', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuthorizationReversal', + ], + ], + PosInterface::TX_TYPE_REFUND => [ + PosInterface::MODEL_NON_SECURE => [ + PosInterface::TX_TYPE_PAY_AUTH => 'DrawBack', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuthorizationDrawBack', + ], + ], + PosInterface::TX_TYPE_REFUND_PARTIAL => [ + PosInterface::MODEL_NON_SECURE => [ + PosInterface::TX_TYPE_PAY_AUTH => 'PartialDrawBack', + ], + ], + PosInterface::TX_TYPE_STATUS => 'SelectOrderByMerchantOrderId', + PosInterface::TX_TYPE_ORDER_HISTORY => 'SelectOrder', + PosInterface::TX_TYPE_HISTORY => 'SelectOrder', + ]; + + if (!isset($arr[$txType])) { + throw new UnsupportedTransactionTypeException(); + } + + if (\is_string($arr[$txType])) { + return $arr[$txType]; + } + + if (!isset($arr[$txType][$paymentModel])) { + throw new UnsupportedTransactionTypeException(); + } + + if (\is_string($arr[$txType][$paymentModel])) { + return $arr[$txType][$paymentModel]; + } + + if (!isset($arr[$txType][$paymentModel][$orderTxType])) { + throw new UnsupportedTransactionTypeException(); + } + + return $arr[$txType][$paymentModel][$orderTxType]; + } +} diff --git a/src/Crypt/AbstractCrypt.php b/src/Crypt/AbstractCrypt.php index 572dae9b..d848f92d 100644 --- a/src/Crypt/AbstractCrypt.php +++ b/src/Crypt/AbstractCrypt.php @@ -96,7 +96,7 @@ protected function buildHashString(array $data, array $paramNames, string $separ $paramsVal = \implode($separator, $this->buildHashData($data, $paramNames)); if (null !== $storeKey) { - $paramsVal = $this->concatenateHashKey($storeKey, $paramsVal); + return $this->concatenateHashKey($storeKey, $paramsVal); } return $paramsVal; diff --git a/src/Crypt/AkbankPosCrypt.php b/src/Crypt/AkbankPosCrypt.php index a025371e..2112f7fd 100644 --- a/src/Crypt/AkbankPosCrypt.php +++ b/src/Crypt/AkbankPosCrypt.php @@ -8,12 +8,21 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; class AkbankPosCrypt extends AbstractCrypt { /** @var string */ protected const HASH_ALGORITHM = 'sha512'; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return AkbankPos::class === $gatewayClass; + } + /** * returns base16 string * @inheritDoc diff --git a/src/Crypt/CryptInterface.php b/src/Crypt/CryptInterface.php index b57fb389..070851d6 100644 --- a/src/Crypt/CryptInterface.php +++ b/src/Crypt/CryptInterface.php @@ -7,9 +7,17 @@ namespace Mews\Pos\Crypt; use Mews\Pos\Entity\Account\AbstractPosAccount; +use Mews\Pos\PosInterface; interface CryptInterface { + /** + * @param class-string $gatewayClass + * + * @return bool + */ + public static function supports(string $gatewayClass): bool; + /** * @param string $str * @param string|null $encryptionKey diff --git a/src/Crypt/EstPosCrypt.php b/src/Crypt/EstPosCrypt.php index 87a53544..985e842b 100644 --- a/src/Crypt/EstPosCrypt.php +++ b/src/Crypt/EstPosCrypt.php @@ -8,9 +8,18 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\EstPos; class EstPosCrypt extends AbstractCrypt { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return EstPos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/EstV3PosCrypt.php b/src/Crypt/EstV3PosCrypt.php index e6b7e050..add7697f 100644 --- a/src/Crypt/EstV3PosCrypt.php +++ b/src/Crypt/EstV3PosCrypt.php @@ -8,6 +8,7 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\EstV3Pos; class EstV3PosCrypt extends AbstractCrypt { @@ -17,6 +18,14 @@ class EstV3PosCrypt extends AbstractCrypt /** @var string */ protected const HASH_SEPARATOR = '|'; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return EstV3Pos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/GarantiPosCrypt.php b/src/Crypt/GarantiPosCrypt.php index 37e0e92a..02cc09e0 100644 --- a/src/Crypt/GarantiPosCrypt.php +++ b/src/Crypt/GarantiPosCrypt.php @@ -8,12 +8,21 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\GarantiPosAccount; +use Mews\Pos\Gateways\GarantiPos; class GarantiPosCrypt extends AbstractCrypt { /** @var string */ protected const HASH_ALGORITHM = 'sha512'; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return GarantiPos::class === $gatewayClass; + } + /** * @param GarantiPosAccount $posAccount * {@inheritDoc} @@ -30,7 +39,11 @@ public function create3DHash(AbstractPosAccount $posAccount, array $formInputs): $formInputs['txntype'], $formInputs['txninstallmentcount'], $posAccount->getStoreKey(), - $this->createSecurityData($posAccount, $formInputs['terminalid'], $formInputs['txntype']), + $this->createSecurityData( + $posAccount, + (string) $formInputs['terminalid'], + (string) $formInputs['txntype'] + ), ]; return $this->hashStringUpperCase(\implode(static::HASH_SEPARATOR, $map), self::HASH_ALGORITHM); diff --git a/src/Crypt/InterPosCrypt.php b/src/Crypt/InterPosCrypt.php index ec9f6a00..4f1cf403 100644 --- a/src/Crypt/InterPosCrypt.php +++ b/src/Crypt/InterPosCrypt.php @@ -8,9 +8,18 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\InterPos; class InterPosCrypt extends AbstractCrypt { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return InterPos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/KuveytPosCrypt.php b/src/Crypt/KuveytPosCrypt.php index a67ea7b4..557ed5dc 100644 --- a/src/Crypt/KuveytPosCrypt.php +++ b/src/Crypt/KuveytPosCrypt.php @@ -8,9 +8,23 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\KuveytPos; +use Mews\Pos\Gateways\KuveytSoapApiPos; +use Mews\Pos\Gateways\VakifKatilimPos; class KuveytPosCrypt extends AbstractCrypt { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return KuveytPos::class === $gatewayClass + || KuveytSoapApiPos::class === $gatewayClass + || VakifKatilimPos::class === $gatewayClass + ; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/NullCrypt.php b/src/Crypt/NullCrypt.php index 14109cc1..eea77b40 100644 --- a/src/Crypt/NullCrypt.php +++ b/src/Crypt/NullCrypt.php @@ -13,6 +13,14 @@ */ class NullCrypt extends AbstractCrypt { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return true; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/ParamPosCrypt.php b/src/Crypt/ParamPosCrypt.php index 3493fbae..43f70a45 100644 --- a/src/Crypt/ParamPosCrypt.php +++ b/src/Crypt/ParamPosCrypt.php @@ -8,9 +8,20 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\Param3DHostPos; +use Mews\Pos\Gateways\ParamPos; class ParamPosCrypt extends AbstractCrypt { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return ParamPos::class === $gatewayClass + || Param3DHostPos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/PayFlexCPV4Crypt.php b/src/Crypt/PayFlexCPV4Crypt.php index ab9a15a6..cb570d19 100644 --- a/src/Crypt/PayFlexCPV4Crypt.php +++ b/src/Crypt/PayFlexCPV4Crypt.php @@ -8,9 +8,18 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\PayFlexCPV4Pos; class PayFlexCPV4Crypt extends AbstractCrypt { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayFlexCPV4Pos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/PayForPosCrypt.php b/src/Crypt/PayForPosCrypt.php index 9b886100..58743c0e 100644 --- a/src/Crypt/PayForPosCrypt.php +++ b/src/Crypt/PayForPosCrypt.php @@ -8,9 +8,18 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\PayForPos; class PayForPosCrypt extends AbstractCrypt { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayForPos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/PosNetCrypt.php b/src/Crypt/PosNetCrypt.php index 9ac781e9..39210480 100644 --- a/src/Crypt/PosNetCrypt.php +++ b/src/Crypt/PosNetCrypt.php @@ -9,6 +9,7 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PosNetAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\PosNet; class PosNetCrypt extends AbstractCrypt { @@ -18,6 +19,14 @@ class PosNetCrypt extends AbstractCrypt /** @var string */ protected const HASH_SEPARATOR = ';'; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PosNet::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/PosNetV1PosCrypt.php b/src/Crypt/PosNetV1PosCrypt.php index 77c53f40..adfe6169 100644 --- a/src/Crypt/PosNetV1PosCrypt.php +++ b/src/Crypt/PosNetV1PosCrypt.php @@ -7,6 +7,7 @@ namespace Mews\Pos\Crypt; use Mews\Pos\Entity\Account\AbstractPosAccount; +use Mews\Pos\Gateways\PosNetV1Pos; class PosNetV1PosCrypt extends AbstractCrypt { @@ -16,6 +17,14 @@ class PosNetV1PosCrypt extends AbstractCrypt /** @var string */ protected const HASH_SEPARATOR = ''; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PosNetV1Pos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/Crypt/ToslaPosCrypt.php b/src/Crypt/ToslaPosCrypt.php index 8ab275ab..b8fe1bc9 100644 --- a/src/Crypt/ToslaPosCrypt.php +++ b/src/Crypt/ToslaPosCrypt.php @@ -8,12 +8,21 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\ToslaPos; class ToslaPosCrypt extends AbstractCrypt { /** @var string */ protected const HASH_ALGORITHM = 'sha512'; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return ToslaPos::class === $gatewayClass; + } + /** * {@inheritDoc} */ diff --git a/src/DataMapper/RequestDataMapper/AbstractRequestDataMapper.php b/src/DataMapper/RequestDataMapper/AbstractRequestDataMapper.php index 0a981552..e5045b6b 100644 --- a/src/DataMapper/RequestDataMapper/AbstractRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/AbstractRequestDataMapper.php @@ -7,9 +7,8 @@ namespace Mews\Pos\DataMapper\RequestDataMapper; use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\Entity\Account\AbstractPosAccount; -use Mews\Pos\Entity\Card\CreditCardInterface; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; +use Mews\Pos\DataMapper\RequestValueFormatter\RequestValueFormatterInterface; +use Mews\Pos\DataMapper\RequestValueMapper\RequestValueMapperInterface; use Mews\Pos\PosInterface; use Psr\EventDispatcher\EventDispatcherInterface; @@ -20,63 +19,36 @@ abstract class AbstractRequestDataMapper implements RequestDataMapperInterface { protected EventDispatcherInterface $eventDispatcher; - /** @var array */ - protected array $secureTypeMappings = []; + protected RequestValueMapperInterface $valueMapper; - /** - * Transaction Types - * - * @var array> - */ - protected array $txTypeMappings = []; + protected RequestValueFormatterInterface $valueFormatter; - /** @var array */ - protected array $cardTypeMapping = []; - - /** @var array */ - protected array $langMappings = [ - PosInterface::LANG_TR => 'tr', - PosInterface::LANG_EN => 'en', - ]; - - /** - * default olarak ISO 4217 kodlar tanimliyoruz. - * fakat bazi banklar ISO standarti kullanmiyorlar. - * Currency mapping - * - * @var non-empty-array - */ - protected array $currencyMappings = [ - PosInterface::CURRENCY_TRY => '949', - PosInterface::CURRENCY_USD => '840', - PosInterface::CURRENCY_EUR => '978', - PosInterface::CURRENCY_GBP => '826', - PosInterface::CURRENCY_JPY => '392', - PosInterface::CURRENCY_RUB => '643', - ]; - - /** - * period mapping for recurring orders - * @var array<'DAY'|'WEEK'|'MONTH'|'YEAR', string> - */ - protected array $recurringOrderFrequencyMapping = []; + protected CryptInterface $crypt; protected bool $testMode = false; - protected CryptInterface $crypt; - - /** - * @param EventDispatcherInterface $eventDispatcher - * @param CryptInterface $crypt - * @param array $currencyMappings - */ - public function __construct(EventDispatcherInterface $eventDispatcher, CryptInterface $crypt, array $currencyMappings = []) - { + /** @var PosInterface::LANG_* */ + protected string $defaultLang; + + /** + * @param RequestValueMapperInterface $valueMapper + * @param RequestValueFormatterInterface $valueFormatter + * @param EventDispatcherInterface $eventDispatcher + * @param CryptInterface $crypt + * @param PosInterface::LANG_* $defaultLang + */ + public function __construct( + RequestValueMapperInterface $valueMapper, + RequestValueFormatterInterface $valueFormatter, + EventDispatcherInterface $eventDispatcher, + CryptInterface $crypt, + string $defaultLang = PosInterface::LANG_TR + ) { + $this->valueMapper = $valueMapper; + $this->valueFormatter = $valueFormatter; $this->eventDispatcher = $eventDispatcher; $this->crypt = $crypt; - if ([] !== $currencyMappings) { - $this->currencyMappings = $currencyMappings; - } + $this->defaultLang = $defaultLang; } /** @@ -95,39 +67,6 @@ public function isTestMode(): bool return $this->testMode; } - /** - * @return array - */ - public function getCardTypeMapping(): array - { - return $this->cardTypeMapping; - } - - /** - * @return array - */ - public function getSecureTypeMappings(): array - { - return $this->secureTypeMappings; - } - - /** - * @return array> - */ - public function getTxTypeMappings(): array - { - return $this->txTypeMappings; - } - - /** - * @return non-empty-array - */ - public function getCurrencyMappings(): array - { - return $this->currencyMappings; - } - - /** * @inheritDoc */ @@ -137,100 +76,18 @@ public function setTestMode(bool $testMode): void } /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * @phpstan-param PosInterface::MODEL_*|null $paymentModel - * - * @param string $txType - * @param string|null $paymentModel - * - * @return string - * - * @throws UnsupportedTransactionTypeException - * @throws \InvalidArgumentException - */ - public function mapTxType(string $txType, ?string $paymentModel = null): string - { - if (!$this->isSupportedTxType($txType, $paymentModel)) { - throw new UnsupportedTransactionTypeException(); - } - - if (\is_string($this->txTypeMappings[$txType])) { - return $this->txTypeMappings[$txType]; - } - - if (null === $paymentModel) { - throw new \InvalidArgumentException( - sprintf('$paymentModel must be provided for the transaction type %s', $txType) - ); - } - - return $this->txTypeMappings[$txType][$paymentModel]; - } - - /** - * @return array<'DAY'|'WEEK'|'MONTH'|'YEAR', string> - */ - public function getRecurringOrderFrequencyMapping(): array - { - return $this->recurringOrderFrequencyMapping; - } - - /** - * formats installment - * @param int $installment - * - * @return string|int - */ - abstract protected function mapInstallment(int $installment); - - /** - * @phpstan-param PosInterface::CURRENCY_* $currency - * - * @param string $currency - * - * @return string|int currency code that is accepted by bank - */ - protected function mapCurrency(string $currency) - { - return $this->currencyMappings[$currency] ?? $currency; - } - - /** - * @param float $amount - * - * @return int|string|float - */ - protected function formatAmount(float $amount) - { - return $amount; - } - - /** - * @param string $period - * - * @return string - */ - protected function mapRecurringFrequency(string $period): string - { - return $this->recurringOrderFrequencyMapping[$period] ?? $period; - } - - /** - * bank returns error messages for specified language value - * usually accepted values are tr,en + * according to the language value, the POS UI will be displayed in the selected language + * and error messages will be returned in the selected language * - * @param AbstractPosAccount $posAccount * @param array $order * - * @return string if language mapping is not available it returns default LANG_TR or as is. + * @return string if language mapping is not available, it returns default LANG_TR or as is. */ - protected function getLang(AbstractPosAccount $posAccount, array $order): string + protected function getLang(array $order): string { - $lang = $order['lang'] ?? $posAccount->getLang(); + $lang = $order['lang'] ?? $this->defaultLang; - return $this->langMappings[$lang] - ?? $this->langMappings[PosInterface::LANG_TR] - ?? $lang; + return $this->valueMapper->mapLang($lang); } /** @@ -316,34 +173,4 @@ protected function prepareOrderHistoryOrder(array $order): array { return $order; } - - /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * @phpstan-param PosInterface::MODEL_*|null $paymentModel - * - * @param string $txType - * @param string|null $paymentModel - * - * @return bool - * - * @throws \InvalidArgumentException - */ - private function isSupportedTxType(string $txType, ?string $paymentModel = null): bool - { - if (!isset($this->txTypeMappings[$txType])) { - return false; - } - - if (\is_array($this->txTypeMappings[$txType])) { - if (null === $paymentModel) { - throw new \InvalidArgumentException( - sprintf('$paymentModel must be provided for the transaction type %s', $txType) - ); - } - - return isset($this->txTypeMappings[$txType][$paymentModel]); - } - - return true; - } } diff --git a/src/DataMapper/RequestDataMapper/AkbankPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/AkbankPosRequestDataMapper.php index ba034c00..c1a223ae 100644 --- a/src/DataMapper/RequestDataMapper/AkbankPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/AkbankPosRequestDataMapper.php @@ -20,72 +20,15 @@ */ class AkbankPosRequestDataMapper extends AbstractRequestDataMapper { - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'my'; - public const API_VERSION = '1.00'; /** - * Not: Güvenli Ödeme 3D Model isteklerinde opsiyonel - * {@inheritDoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => [ - PosInterface::MODEL_NON_SECURE => '1000', - PosInterface::MODEL_3D_SECURE => '3000', - PosInterface::MODEL_3D_PAY => '3000', - PosInterface::MODEL_3D_HOST => '3000', - ], - PosInterface::TX_TYPE_PAY_PRE_AUTH => [ - PosInterface::MODEL_NON_SECURE => '1004', - PosInterface::MODEL_3D_SECURE => '3004', - PosInterface::MODEL_3D_PAY => '3004', - PosInterface::MODEL_3D_HOST => '3004', - ], - PosInterface::TX_TYPE_PAY_POST_AUTH => '1005', - PosInterface::TX_TYPE_REFUND => '1002', - PosInterface::TX_TYPE_REFUND_PARTIAL => '1002', - PosInterface::TX_TYPE_CANCEL => '1003', - PosInterface::TX_TYPE_ORDER_HISTORY => '1010', - PosInterface::TX_TYPE_HISTORY => '1009', - ]; - - /** - * {@inheritdoc} - */ - protected array $recurringOrderFrequencyMapping = [ - 'DAY' => 'D', - 'WEEK' => 'W', - 'MONTH' => 'M', - 'YEAR' => 'Y', - ]; - - /** - * {@inheritdoc} - */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3D', - PosInterface::MODEL_3D_PAY => '3D_PAY', - PosInterface::MODEL_3D_HOST => '3D_PAY_HOSTING', - PosInterface::MODEL_NON_SECURE => 'PAY_HOSTING', - ]; - - /** @var array */ - protected array $langMappings = [ - PosInterface::LANG_TR => 'TR', - PosInterface::LANG_EN => 'EN', - ]; - - /** - * @var non-empty-array + * @inheritDoc */ - protected array $currencyMappings = [ - PosInterface::CURRENCY_TRY => 949, - PosInterface::CURRENCY_USD => 840, - PosInterface::CURRENCY_EUR => 978, - PosInterface::CURRENCY_JPY => 392, - PosInterface::CURRENCY_RUB => 643, - ]; + public static function supports(string $gatewayClass): bool + { + return AkbankPos::class === $gatewayClass; + } /** * @param AkbankPosAccount $posAccount @@ -98,17 +41,17 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array return $this->getRequestAccountData($posAccount) + [ 'version' => self::API_VERSION, - 'txnCode' => $this->mapTxType($txType, PosInterface::MODEL_NON_SECURE), - 'requestDateTime' => $this->formatRequestDateTime($order['transaction_time']), + 'txnCode' => $this->valueMapper->mapTxType($txType, PosInterface::MODEL_NON_SECURE), + 'requestDateTime' => $this->valueFormatter->formatDateTime($order['transaction_time'], 'requestDateTime'), 'randomNumber' => $this->crypt->generateRandomString(), 'order' => [ 'orderId' => (string) $order['id'], ], 'transaction' => [ - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency((string) $order['currency']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'motoInd' => 0, - 'installCount' => $this->mapInstallment((int) $order['installment']), + 'installCount' => $this->valueFormatter->formatInstallment($order['installment']), ], 'secureTransaction' => [ 'secureId' => $responseData['secureId'], @@ -133,19 +76,19 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount $requestData = $this->getRequestAccountData($posAccount) + [ 'version' => self::API_VERSION, - 'txnCode' => $this->mapTxType($txType, PosInterface::MODEL_NON_SECURE), - 'requestDateTime' => $this->formatRequestDateTime($order['transaction_time']), + 'txnCode' => $this->valueMapper->mapTxType($txType, PosInterface::MODEL_NON_SECURE), + 'requestDateTime' => $this->valueFormatter->formatDateTime($order['transaction_time'], 'requestDateTime'), 'randomNumber' => $this->crypt->generateRandomString(), 'card' => [ 'cardNumber' => $creditCard->getNumber(), 'cvv2' => $creditCard->getCvv(), - 'expireDate' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'expireDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'expireDate'), ], 'transaction' => [ - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency((string) $order['currency']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'motoInd' => 0, - 'installCount' => $this->mapInstallment((int) $order['installment']), + 'installCount' => $this->valueFormatter->formatInstallment($order['installment']), ], 'customer' => [ 'ipAddress' => $order['ip'], @@ -181,15 +124,15 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po return $this->getRequestAccountData($posAccount) + [ 'version' => self::API_VERSION, - 'txnCode' => $this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), - 'requestDateTime' => $this->formatRequestDateTime($order['transaction_time']), + 'txnCode' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), + 'requestDateTime' => $this->valueFormatter->formatDateTime($order['transaction_time'], 'requestDateTime'), 'randomNumber' => $this->crypt->generateRandomString(), 'order' => [ 'orderId' => (string) $order['id'], ], 'transaction' => [ - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency((string) $order['currency']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), ], 'customer' => [ 'ipAddress' => $order['ip'], @@ -217,9 +160,9 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o $order = $this->prepareCancelOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'txnCode' => $this->mapTxType(PosInterface::TX_TYPE_CANCEL), + 'txnCode' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL), 'version' => self::API_VERSION, - 'requestDateTime' => $this->formatRequestDateTime($order['transaction_time']), + 'requestDateTime' => $this->valueFormatter->formatDateTime($order['transaction_time'], 'requestDateTime'), 'randomNumber' => $this->crypt->generateRandomString(), ]; @@ -269,12 +212,12 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o $requestData = $this->getRequestAccountData($posAccount) + [ 'version' => self::API_VERSION, - 'txnCode' => $this->mapTxType($refundTxType), - 'requestDateTime' => $this->formatRequestDateTime($order['transaction_time']), + 'txnCode' => $this->valueMapper->mapTxType($refundTxType), + 'requestDateTime' => $this->valueFormatter->formatDateTime($order['transaction_time'], 'requestDateTime'), 'randomNumber' => $this->crypt->generateRandomString(), 'transaction' => [ - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency((string) $order['currency']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), ], ]; @@ -310,8 +253,8 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar $result = $this->getRequestAccountData($posAccount) + [ 'version' => self::API_VERSION, - 'txnCode' => $this->mapTxType(PosInterface::TX_TYPE_ORDER_HISTORY, PosInterface::MODEL_NON_SECURE), - 'requestDateTime' => $this->formatRequestDateTime($order['transaction_time']), + 'txnCode' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_ORDER_HISTORY, PosInterface::MODEL_NON_SECURE), + 'requestDateTime' => $this->valueFormatter->formatDateTime($order['transaction_time'], 'requestDateTime'), 'randomNumber' => $this->crypt->generateRandomString(), 'order' => [], ]; @@ -347,8 +290,8 @@ public function createHistoryRequestData(AbstractPosAccount $posAccount, array $ ]; } elseif (isset($order['start_date'], $order['end_date'])) { $requestData['report'] = [ - 'startDateTime' => $this->formatRequestDateTime($order['start_date']), - 'endDateTime' => $this->formatRequestDateTime($order['end_date']), + 'startDateTime' => $this->valueFormatter->formatDateTime($order['start_date'], 'startDateTime'), + 'endDateTime' => $this->valueFormatter->formatDateTime($order['end_date'], 'endDateTime'), ]; } @@ -367,19 +310,19 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s $order = $this->preparePaymentOrder($order); $inputs = [ - 'paymentModel' => $this->secureTypeMappings[$paymentModel], - 'txnCode' => $this->mapTxType($txType, $paymentModel), + 'paymentModel' => $this->valueMapper->mapSecureType($paymentModel), + 'txnCode' => $this->valueMapper->mapTxType($txType, $paymentModel), 'merchantSafeId' => $posAccount->getClientId(), 'terminalSafeId' => $posAccount->getTerminalId(), 'orderId' => (string) $order['id'], - 'lang' => $this->getLang($posAccount, $order), - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => (string) $this->mapCurrency((string) $order['currency']), - 'installCount' => (string) $this->mapInstallment((int) $order['installment']), + 'lang' => $this->getLang($order), + 'amount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'installCount' => (string) $this->valueFormatter->formatInstallment($order['installment']), 'okUrl' => (string) $order['success_url'], 'failUrl' => (string) $order['fail_url'], 'randomNumber' => $this->crypt->generateRandomString(), - 'requestDateTime' => $this->formatRequestDateTime($order['transaction_time']), + 'requestDateTime' => $this->valueFormatter->formatDateTime($order['transaction_time'], 'requestDateTime'), ]; if (null !== $posAccount->getSubMerchantId()) { @@ -388,7 +331,7 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s if ($creditCard instanceof CreditCardInterface) { $inputs['creditCard'] = $creditCard->getNumber(); - $inputs['expiredDate'] = $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT); + $inputs['expiredDate'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'expiredDate'); $inputs['cvv'] = $creditCard->getCvv(); } @@ -420,26 +363,21 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s */ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, array $requestData): array { + if (isset($requestData['requestDateTime'])) { + $dateTime = $requestData['requestDateTime']; + } else { + $dateTime = $this->valueFormatter->formatDateTime($this->createDateTime(), 'requestDateTime'); + } + return $requestData + $this->getRequestAccountData($posAccount) + [ - 'version' => self::API_VERSION, - 'requestDateTime' => $requestData['requestDateTime'] ?? $this->formatRequestDateTime($this->createDateTime()), - 'randomNumber' => $this->crypt->generateRandomString(), + 'version' => self::API_VERSION, + 'requestDateTime' => $dateTime, + 'randomNumber' => $this->crypt->generateRandomString(), ]; } - /** - * 0 => 1 - * 1 => 1 - * 2 => 2 - * @inheritDoc - */ - protected function mapInstallment(int $installment): int - { - return \max($installment, 1); - } - /** * @inheritDoc */ @@ -515,26 +453,6 @@ protected function prepareCancelOrder(array $order): array ]); } - /** - * @param float $amount - * - * @return string - */ - protected function formatAmount(float $amount): string - { - return \number_format($amount, 2, '.', ''); - } - - /** - * @inheritDoc - * - * @return int - */ - protected function mapCurrency(string $currency): int - { - return $this->currencyMappings[$currency]; - } - /** * prepares history request * @@ -592,7 +510,7 @@ private function createRecurringData(array $recurringData): array // Periyodik İşlem Frekansı 'frequencyInterval' => $recurringData['frequency'], // D|W|M|Y - 'frequencyCycle' => $this->mapRecurringFrequency($recurringData['frequencyType']), + 'frequencyCycle' => $this->valueMapper->mapRecurringFrequency($recurringData['frequencyType']), 'numberOfPayments' => $recurringData['installment'], ], ]; @@ -605,14 +523,4 @@ private function createDateTime(): \DateTimeImmutable { return new \DateTimeImmutable('now', new \DateTimeZone('Europe/Istanbul')); } - - /** - * @param DateTimeInterface $dateTime - * - * @return string example 2024-04-14T16:45:30.000 - */ - private function formatRequestDateTime(\DateTimeInterface $dateTime): string - { - return $dateTime->format('Y-m-d\TH:i:s').'.000'; - } } diff --git a/src/DataMapper/RequestDataMapper/EstPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/EstPosRequestDataMapper.php index dd2917f3..25280a3c 100644 --- a/src/DataMapper/RequestDataMapper/EstPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/EstPosRequestDataMapper.php @@ -19,49 +19,13 @@ */ class EstPosRequestDataMapper extends AbstractRequestDataMapper { - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'm/y'; - - /** @var string */ - public const CREDIT_CARD_EXP_MONTH_FORMAT = 'm'; - - /** @var string */ - public const CREDIT_CARD_EXP_YEAR_FORMAT = 'y'; - - /** - * {@inheritDoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Auth', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'PostAuth', - PosInterface::TX_TYPE_CANCEL => 'Void', - PosInterface::TX_TYPE_REFUND => 'Credit', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'Credit', - PosInterface::TX_TYPE_STATUS => 'ORDERSTATUS', - PosInterface::TX_TYPE_HISTORY => 'ORDERHISTORY', - ]; - /** - * {@inheritdoc} - */ - protected array $recurringOrderFrequencyMapping = [ - 'DAY' => 'D', - 'WEEK' => 'W', - 'MONTH' => 'M', - 'YEAR' => 'Y', - ]; - - /** - * {@inheritdoc} + * @inheritDoc */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3d', - PosInterface::MODEL_3D_PAY => '3d_pay', - PosInterface::MODEL_3D_PAY_HOSTING => '3d_pay_hosting', - PosInterface::MODEL_3D_HOST => '3d_host', - PosInterface::MODEL_NON_SECURE => 'regular', - ]; + public static function supports(string $gatewayClass): bool + { + return EstPos::class === $gatewayClass; + } /** * {@inheritDoc} @@ -73,12 +37,12 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array $order = $this->preparePaymentOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'Type' => $this->mapTxType($txType), + 'Type' => $this->valueMapper->mapTxType($txType), 'IPAddress' => (string) $order['ip'], 'OrderId' => (string) $order['id'], - 'Total' => (string) $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), - 'Taksit' => $this->mapInstallment((int) $order['installment']), + 'Total' => $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => $this->valueMapper->mapCurrency($order['currency']), + 'Taksit' => $this->valueFormatter->formatInstallment($order['installment']), 'Number' => $responseData['md'], 'PayerTxnId' => $responseData['xid'], 'PayerSecurityLevel' => $responseData['eci'], @@ -102,14 +66,14 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount $order = $this->preparePaymentOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'Type' => $this->mapTxType($txType), + 'Type' => $this->valueMapper->mapTxType($txType), 'IPAddress' => (string) $order['ip'], 'OrderId' => (string) $order['id'], - 'Total' => (string) $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), - 'Taksit' => $this->mapInstallment((int) $order['installment']), + 'Total' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'Taksit' => (string) $this->valueFormatter->formatInstallment($order['installment']), 'Number' => $creditCard->getNumber(), - 'Expires' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'Expires' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Expires'), 'Cvv2Val' => $creditCard->getCvv(), 'Mode' => 'P', ]; @@ -124,21 +88,21 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount /** * {@inheritDoc} * - * @return array{Type: string, OrderId: string, Name: string, Password: string, ClientId: string, Total: float|null} + * @return array{Type: string, OrderId: string, Name: string, Password: string, ClientId: string, Total: string|null} */ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $posAccount, array $order): array { $order = $this->preparePostPaymentOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'Type' => $this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), + 'Type' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), 'OrderId' => (string) $order['id'], - 'Total' => isset($order['amount']) ? (float) $this->formatAmount($order['amount']) : null, + 'Total' => isset($order['amount']) ? (string) $this->valueFormatter->formatAmount($order['amount']) : null, ]; if (isset($order['amount'], $order['pre_auth_amount']) && $order['pre_auth_amount'] < $order['amount']) { // when amount < pre_auth_amount then we need to send PREAMT value - $requestData['Extra']['PREAMT'] = $order['pre_auth_amount']; + $requestData['Extra']['PREAMT'] = (string) $this->valueFormatter->formatAmount($order['pre_auth_amount']); } return $requestData; @@ -151,7 +115,7 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o { $statusRequestData = $this->getRequestAccountData($posAccount) + [ 'Extra' => [ - $this->mapTxType(PosInterface::TX_TYPE_STATUS) => 'QUERY', + $this->valueMapper->mapTxType(PosInterface::TX_TYPE_STATUS) => 'QUERY', ], ]; @@ -193,7 +157,7 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o return $this->getRequestAccountData($posAccount) + [ 'OrderId' => $order['id'], - 'Type' => $this->mapTxType(PosInterface::TX_TYPE_CANCEL), + 'Type' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL), ]; } @@ -207,12 +171,12 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o $requestData = [ 'OrderId' => (string) $order['id'], - 'Currency' => $this->mapCurrency($order['currency']), - 'Type' => $this->mapTxType($refundTxType), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'Type' => $this->valueMapper->mapTxType($refundTxType), ]; if (isset($order['amount'])) { - $requestData['Total'] = (string) $order['amount']; + $requestData['Total'] = (string) $this->valueFormatter->formatAmount($order['amount']); } return $this->getRequestAccountData($posAccount) + $requestData; @@ -229,7 +193,7 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar $requestData = [ 'OrderId' => (string) $order['id'], 'Extra' => [ - $this->mapTxType(PosInterface::TX_TYPE_HISTORY) => 'QUERY', + $this->valueMapper->mapTxType(PosInterface::TX_TYPE_HISTORY) => 'QUERY', ], ]; @@ -282,12 +246,12 @@ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, arr * @phpstan-param PosInterface::MODEL_3D_* $paymentModel * @phpstan-param PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType * - * @param AbstractPosAccount $posAccount - * @param array $order - * @param string $paymentModel - * @param string $txType - * @param string $gatewayURL - * @param CreditCardInterface|null $creditCard + * @param AbstractPosAccount $posAccount + * @param array $order + * @param string $paymentModel + * @param string $txType + * @param string $gatewayURL + * @param CreditCardInterface|null $creditCard * * @return array{gateway: string, method: 'POST', inputs: array} * @@ -297,22 +261,22 @@ protected function create3DFormDataCommon(AbstractPosAccount $posAccount, array { $inputs = [ 'clientid' => $posAccount->getClientId(), - 'storetype' => $this->secureTypeMappings[$paymentModel], - 'amount' => (string) $order['amount'], + 'storetype' => $this->valueMapper->mapSecureType($paymentModel), + 'amount' => (string) $this->valueFormatter->formatAmount((float) $order['amount']), 'oid' => (string) $order['id'], 'okUrl' => (string) $order['success_url'], 'failUrl' => (string) $order['fail_url'], 'rnd' => $this->crypt->generateRandomString(), - 'lang' => $this->getLang($posAccount, $order), - 'currency' => $this->mapCurrency((string) $order['currency']), - 'taksit' => $this->mapInstallment((int) $order['installment']), - 'islemtipi' => $this->mapTxType($txType), + 'lang' => $this->getLang($order), + 'currency' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'taksit' => (string) $this->valueFormatter->formatInstallment($order['installment']), + 'islemtipi' => $this->valueMapper->mapTxType($txType), ]; if ($creditCard instanceof CreditCardInterface) { $inputs['pan'] = $creditCard->getNumber(); - $inputs['Ecom_Payment_Card_ExpDate_Month'] = $creditCard->getExpireMonth(self::CREDIT_CARD_EXP_MONTH_FORMAT); - $inputs['Ecom_Payment_Card_ExpDate_Year'] = $creditCard->getExpireYear(self::CREDIT_CARD_EXP_YEAR_FORMAT); + $inputs['Ecom_Payment_Card_ExpDate_Month'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Ecom_Payment_Card_ExpDate_Month'); + $inputs['Ecom_Payment_Card_ExpDate_Year'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Ecom_Payment_Card_ExpDate_Year'); $inputs['cv2'] = $creditCard->getCvv(); } @@ -323,16 +287,6 @@ protected function create3DFormDataCommon(AbstractPosAccount $posAccount, array ]; } - /** - * 0 => '' - * 1 => '' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : ''; - } /** * @inheritDoc @@ -380,16 +334,6 @@ protected function prepareOrderHistoryOrder(array $order): array ]; } - /** - * @inheritDoc - * - * @return string - */ - protected function mapCurrency(string $currency): string - { - return (string) ($this->currencyMappings[$currency] ?? $currency); - } - /** * @param AbstractPosAccount $posAccount * @@ -417,7 +361,7 @@ private function createRecurringData(array $recurringData): array // Periyodik İşlem Frekansı 'OrderFrequencyInterval' => (string) $recurringData['frequency'], // D|M|Y - 'OrderFrequencyCycle' => $this->mapRecurringFrequency($recurringData['frequencyType']), + 'OrderFrequencyCycle' => $this->valueMapper->mapRecurringFrequency($recurringData['frequencyType']), 'TotalNumberPayments' => (string) $recurringData['installment'], ], ]; diff --git a/src/DataMapper/RequestDataMapper/EstV3PosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/EstV3PosRequestDataMapper.php index 4aafbc3c..230e5247 100644 --- a/src/DataMapper/RequestDataMapper/EstV3PosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/EstV3PosRequestDataMapper.php @@ -16,6 +16,14 @@ */ class EstV3PosRequestDataMapper extends EstPosRequestDataMapper { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return EstV3Pos::class === $gatewayClass; + } + /** * {@inheritDoc} */ @@ -25,7 +33,7 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s $data = $this->create3DFormDataCommon($posAccount, $order, $paymentModel, $txType, $gatewayURL, $creditCard); - $data['inputs']['TranType'] = $this->mapTxType($txType); + $data['inputs']['TranType'] = $this->valueMapper->mapTxType($txType); unset($data['inputs']['islemtipi']); $data['inputs']['hashAlgorithm'] = 'ver3'; diff --git a/src/DataMapper/RequestDataMapper/GarantiPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/GarantiPosRequestDataMapper.php index bf1d3688..d3123c60 100644 --- a/src/DataMapper/RequestDataMapper/GarantiPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/GarantiPosRequestDataMapper.php @@ -23,15 +23,6 @@ class GarantiPosRequestDataMapper extends AbstractRequestDataMapper /** @var string */ public const API_VERSION = '512'; - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'my'; - - /** @var string */ - public const CREDIT_CARD_EXP_MONTH_FORMAT = 'm'; - - /** @var string */ - public const CREDIT_CARD_EXP_YEAR_FORMAT = 'y'; - /** * MotoInd; işlemin MAilOrder bir işlem olup olmadığı bilgisinin gönderildiği alandır. * Y (also E) ise işlem mail order bir işlemdir. @@ -40,37 +31,16 @@ class GarantiPosRequestDataMapper extends AbstractRequestDataMapper */ private const MOTO = 'N'; - /** - * {@inheritDoc} - */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3D', - PosInterface::MODEL_3D_PAY => '3D_PAY', - ]; + /** @var GarantiPosCrypt */ + protected CryptInterface $crypt; /** - * {@inheritDoc} + * @inheritDoc */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'sales', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'preauth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'postauth', - PosInterface::TX_TYPE_CANCEL => 'void', - PosInterface::TX_TYPE_REFUND => 'refund', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'refund', - PosInterface::TX_TYPE_ORDER_HISTORY => 'orderhistoryinq', - PosInterface::TX_TYPE_HISTORY => 'orderlistinq', - PosInterface::TX_TYPE_STATUS => 'orderinq', - ]; - - protected array $recurringOrderFrequencyMapping = [ - 'DAY' => 'D', - 'WEEK' => 'W', - 'MONTH' => 'M', - ]; - - /** @var GarantiPosCrypt */ - protected CryptInterface $crypt; + public static function supports(string $gatewayClass): bool + { + return GarantiPos::class === $gatewayClass; + } /** * @param GarantiPosAccount $posAccount @@ -93,7 +63,7 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array ], 'Transaction' => [ 'Type' => $responseData['txntype'], - 'InstallmentCnt' => $this->mapInstallment($order['installment']), + 'InstallmentCnt' => $this->valueFormatter->formatInstallment($order['installment']), 'Amount' => $responseData['txnamount'], 'CurrencyCode' => $responseData['txncurrencycode'], 'CardholderPresentCode' => '13', //13 for 3D secure payment @@ -137,10 +107,10 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount 'OrderID' => $order['id'], ], 'Transaction' => [ - 'Type' => $this->mapTxType($txType), - 'InstallmentCnt' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Type' => $this->valueMapper->mapTxType($txType), + 'InstallmentCnt' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'CardholderPresentCode' => '0', 'MotoInd' => self::MOTO, ], @@ -175,9 +145,9 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po 'OrderID' => $order['id'], ], 'Transaction' => [ - 'Type' => $this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), - 'Amount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Type' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'OriginalRetrefNum' => $order['ref_ret_num'], ], ]; @@ -207,10 +177,10 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o 'OrderID' => $order['id'], ], 'Transaction' => [ - 'Type' => $this->mapTxType(PosInterface::TX_TYPE_STATUS), - 'InstallmentCnt' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Type' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_STATUS), + 'InstallmentCnt' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'CardholderPresentCode' => '0', 'MotoInd' => self::MOTO, ], @@ -241,10 +211,10 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o 'OrderID' => $order['id'], ], 'Transaction' => [ - 'Type' => $this->mapTxType(PosInterface::TX_TYPE_CANCEL), - 'InstallmentCnt' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Type' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL), + 'InstallmentCnt' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'CardholderPresentCode' => '0', 'MotoInd' => self::MOTO, 'OriginalRetrefNum' => $order['ref_ret_num'], @@ -276,10 +246,10 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o 'OrderID' => $order['id'], ], 'Transaction' => [ - 'Type' => $this->mapTxType($refundTxType), - 'InstallmentCnt' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek, - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Type' => $this->valueMapper->mapTxType($refundTxType), + 'InstallmentCnt' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek, + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'CardholderPresentCode' => '0', 'MotoInd' => self::MOTO, 'OriginalRetrefNum' => $order['ref_ret_num'], @@ -311,10 +281,10 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar 'OrderID' => $order['id'], ], 'Transaction' => [ - 'Type' => $this->mapTxType(PosInterface::TX_TYPE_ORDER_HISTORY), - 'InstallmentCnt' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Type' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_ORDER_HISTORY), + 'InstallmentCnt' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), //sabit olarak amount 100 gonderilecek + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'CardholderPresentCode' => '0', 'MotoInd' => self::MOTO, ], @@ -345,8 +315,8 @@ public function createHistoryRequestData(AbstractPosAccount $posAccount, array $ 'GroupID' => null, 'Description' => null, // Başlangıç ve bitiş tarihleri arasında en fazla 30 gün olabilir - 'StartDate' => $this->formatRequestDateTime($order['start_date']), - 'EndDate' => $this->formatRequestDateTime($order['end_date']), + 'StartDate' => $this->valueFormatter->formatDateTime($order['start_date'], 'StartDate'), + 'EndDate' => $this->valueFormatter->formatDateTime($order['end_date'], 'EndDate'), /** * 500 adetten fazla işlem olması durumunda ListPageNum alanında diğer 500 lü grupların görüntülenmesi * için sayfa numarası yazılır. @@ -354,9 +324,9 @@ public function createHistoryRequestData(AbstractPosAccount $posAccount, array $ 'ListPageNum' => $order['page'], ], 'Transaction' => [ - 'Type' => $this->mapTxType(PosInterface::TX_TYPE_HISTORY), - 'Amount' => $this->formatAmount(1), //sabit olarak amount 100 gonderilecek - 'CurrencyCode' => $this->mapCurrency(PosInterface::CURRENCY_TRY), + 'Type' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_HISTORY), + 'Amount' => $this->valueFormatter->formatAmount(1), //sabit olarak amount 100 gonderilecek + 'CurrencyCode' => $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY), 'CardholderPresentCode' => '0', 'MotoInd' => self::MOTO, ], @@ -380,17 +350,17 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s $order = $this->preparePaymentOrder($order); $inputs = [ - 'secure3dsecuritylevel' => $this->secureTypeMappings[$paymentModel], + 'secure3dsecuritylevel' => $this->valueMapper->mapSecureType($paymentModel), 'mode' => $this->getMode(), 'apiversion' => self::API_VERSION, 'terminalprovuserid' => $posAccount->getUsername(), 'terminaluserid' => $posAccount->getUsername(), 'terminalmerchantid' => $posAccount->getClientId(), 'terminalid' => $posAccount->getTerminalId(), - 'txntype' => $this->mapTxType($txType), - 'txnamount' => (string) $this->formatAmount($order['amount']), - 'txncurrencycode' => $this->mapCurrency($order['currency']), - 'txninstallmentcount' => $this->mapInstallment($order['installment']), + 'txntype' => $this->valueMapper->mapTxType($txType), + 'txnamount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'txncurrencycode' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'txninstallmentcount' => (string) $this->valueFormatter->formatInstallment($order['installment']), 'orderid' => (string) $order['id'], 'successurl' => (string) $order['success_url'], 'errorurl' => (string) $order['fail_url'], @@ -399,8 +369,8 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s if ($creditCard instanceof CreditCardInterface) { $inputs['cardnumber'] = $creditCard->getNumber(); - $inputs['cardexpiredatemonth'] = $creditCard->getExpireMonth(self::CREDIT_CARD_EXP_MONTH_FORMAT); - $inputs['cardexpiredateyear'] = $creditCard->getExpireYear(self::CREDIT_CARD_EXP_YEAR_FORMAT); + $inputs['cardexpiredatemonth'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'cardexpiredatemonth'); + $inputs['cardexpiredateyear'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'cardexpiredateyear'); $inputs['cardcvv2'] = $creditCard->getCvv(); } @@ -443,40 +413,6 @@ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, arr return $requestData; } - /** - * 0 => '' - * 1 => '' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : ''; - } - - /** - * Amount Formatter - * converts 100 to 10000, or 10.01 to 1001 - * - * @param float $amount - * - * @return int - */ - protected function formatAmount(float $amount): int - { - return (int) (\round($amount, 2) * 100); - } - - /** - * @inheritDoc - * - * @return string - */ - protected function mapCurrency(string $currency): string - { - return (string) ($this->currencyMappings[$currency] ?? $currency); - } - /** * @inheritDoc */ @@ -614,7 +550,7 @@ private function getCardData(CreditCardInterface $creditCard): array { return [ 'Number' => $creditCard->getNumber(), - 'ExpireDate' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'ExpireDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'ExpireDate'), 'CVV2' => $creditCard->getCvv(), ]; } @@ -644,20 +580,11 @@ private function createRecurringData(array $recurringData): array { return [ 'TotalPaymentNum' => (string) $recurringData['installment'], //kac kere tekrarlanacak - 'FrequencyType' => $this->mapRecurringFrequency($recurringData['frequencyType']), //Monthly, weekly, daily + 'FrequencyType' => $this->valueMapper->mapRecurringFrequency($recurringData['frequencyType']), //Monthly, weekly, daily 'FrequencyInterval' => (string) $recurringData['frequency'], 'Type' => 'R', // R:Sabit Tutarli G:Degisken Tuta + //todo use formatter 'StartDate' => isset($recurringData['startDate']) ? $recurringData['startDate']->format('Ymd') : '', ]; } - - /** - * @param \DateTimeInterface $dateTime - * - * @return string example 01/12/2010 11:11 - */ - private function formatRequestDateTime(\DateTimeInterface $dateTime): string - { - return $dateTime->format('d/m/Y H:i'); - } } diff --git a/src/DataMapper/RequestDataMapper/InterPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/InterPosRequestDataMapper.php index 1c06ec49..ebdd874a 100644 --- a/src/DataMapper/RequestDataMapper/InterPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/InterPosRequestDataMapper.php @@ -18,9 +18,6 @@ */ class InterPosRequestDataMapper extends AbstractRequestDataMapper { - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'my'; - /** * MOTO (Mail Order Telephone Order) 0 for false, 1 for true * @var string @@ -28,39 +25,12 @@ class InterPosRequestDataMapper extends AbstractRequestDataMapper protected const MOTO = '0'; /** - * {@inheritdoc} - */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3DModel', - PosInterface::MODEL_3D_PAY => '3DPay', - PosInterface::MODEL_3D_HOST => '3DHost', - PosInterface::MODEL_NON_SECURE => 'NonSecure', - ]; - - /** - * Transaction Types - * - * {@inheritdoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Auth', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'PostAuth', - PosInterface::TX_TYPE_CANCEL => 'Void', - PosInterface::TX_TYPE_REFUND => 'Refund', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', - PosInterface::TX_TYPE_STATUS => 'StatusHistory', - ]; - - /** - * {@inheritdoc} + * @inheritDoc */ - protected array $cardTypeMapping = [ - CreditCardInterface::CARD_TYPE_VISA => '0', - CreditCardInterface::CARD_TYPE_MASTERCARD => '1', - CreditCardInterface::CARD_TYPE_AMEX => '2', - CreditCardInterface::CARD_TYPE_TROY => '3', - ]; + public static function supports(string $gatewayClass): bool + { + return InterPos::class === $gatewayClass; + } /** * TODO tekrarlanan odemeler icin daha fazla bilgi lazim, Deniz bank dokumantasyonunda hic bir aciklama yok @@ -77,18 +47,18 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array $order = $this->preparePaymentOrder($order); return $this->getRequestAccountData($posAccount) + [ - 'TxnType' => $this->mapTxType($txType), - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], + 'TxnType' => $this->valueMapper->mapTxType($txType), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), 'OrderId' => (string) $order['id'], - 'PurchAmount' => (string) $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), - 'InstallmentCount' => $this->mapInstallment($order['installment']), + 'PurchAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => $this->valueMapper->mapCurrency($order['currency']), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), 'MD' => $responseData['MD'], 'PayerTxnId' => $responseData['PayerTxnId'], 'Eci' => $responseData['Eci'], 'PayerAuthenticationCode' => $responseData['PayerAuthenticationCode'], 'MOTO' => self::MOTO, - 'Lang' => $this->getLang($posAccount, $order), + 'Lang' => $this->getLang($order), ]; } @@ -100,17 +70,17 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount $order = $this->preparePaymentOrder($order); return $this->getRequestAccountData($posAccount) + [ - 'TxnType' => $this->mapTxType($txType), - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], + 'TxnType' => $this->valueMapper->mapTxType($txType), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), 'OrderId' => $order['id'], - 'PurchAmount' => $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), - 'InstallmentCount' => $this->mapInstallment((int) $order['installment']), + 'PurchAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => $this->valueMapper->mapCurrency($order['currency']), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), 'MOTO' => self::MOTO, - 'Lang' => $this->getLang($posAccount, $order), - 'CardType' => $creditCard->getType() !== null ? $this->cardTypeMapping[$creditCard->getType()] : null, + 'Lang' => $this->getLang($order), + 'CardType' => $creditCard->getType() !== null ? $this->valueMapper->mapCardType($creditCard->getType()) : null, 'Pan' => $creditCard->getNumber(), - 'Expiry' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'Expiry' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Expiry'), 'Cvv2' => $creditCard->getCvv(), ]; } @@ -124,12 +94,12 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po $order = $this->preparePostPaymentOrder($order); return $this->getRequestAccountData($posAccount) + [ - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), 'OrderId' => null, 'orgOrderId' => (string) $order['id'], - 'PurchAmount' => (string) $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), + 'PurchAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), 'MOTO' => self::MOTO, ]; } @@ -145,9 +115,9 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o return $this->getRequestAccountData($posAccount) + [ 'OrderId' => null, //todo buraya hangi deger verilecek? 'orgOrderId' => (string) $order['id'], - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_STATUS), - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], - 'Lang' => $this->getLang($posAccount, $order), + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_STATUS), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), + 'Lang' => $this->getLang($order), ]; } @@ -162,9 +132,9 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o return $this->getRequestAccountData($posAccount) + [ 'OrderId' => null, //todo buraya hangi deger verilecek? 'orgOrderId' => (string) $order['id'], - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_CANCEL), - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], - 'Lang' => $this->getLang($posAccount, $order), + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), + 'Lang' => $this->getLang($order), ]; } @@ -179,10 +149,10 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o return $this->getRequestAccountData($posAccount) + [ 'OrderId' => null, 'orgOrderId' => (string) $order['id'], - 'PurchAmount' => (string) $order['amount'], - 'TxnType' => $this->mapTxType($refundTxType), - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], - 'Lang' => $this->getLang($posAccount, $order), + 'PurchAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'TxnType' => $this->valueMapper->mapTxType($refundTxType), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), + 'Lang' => $this->getLang($order), 'MOTO' => self::MOTO, ]; } @@ -214,22 +184,22 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s $inputs = [ 'ShopCode' => $posAccount->getClientId(), - 'TxnType' => $this->mapTxType($txType), - 'SecureType' => $this->secureTypeMappings[$paymentModel], - 'PurchAmount' => $order['amount'], - 'OrderId' => $order['id'], - 'OkUrl' => $order['success_url'], - 'FailUrl' => $order['fail_url'], + 'TxnType' => $this->valueMapper->mapTxType($txType), + 'SecureType' => $this->valueMapper->mapSecureType($paymentModel), + 'PurchAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'OrderId' => (string) $order['id'], + 'OkUrl' => (string) $order['success_url'], + 'FailUrl' => (string) $order['fail_url'], 'Rnd' => $this->crypt->generateRandomString(), - 'Lang' => $this->getLang($posAccount, $order), - 'Currency' => $this->mapCurrency($order['currency']), - 'InstallmentCount' => $this->mapInstallment((int) $order['installment']), + 'Lang' => $this->getLang($order), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'InstallmentCount' => (string) $this->valueFormatter->formatInstallment($order['installment']), ]; if ($creditCard instanceof CreditCardInterface) { - $inputs['CardType'] = $creditCard->getType() !== null ? $this->cardTypeMapping[$creditCard->getType()] : ''; + $inputs['CardType'] = $creditCard->getType() !== null ? $this->valueMapper->mapCardType($creditCard->getType()) : ''; $inputs['Pan'] = $creditCard->getNumber(); - $inputs['Expiry'] = $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT); + $inputs['Expiry'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Expiry'); $inputs['Cvv2'] = $creditCard->getCvv(); } @@ -260,27 +230,6 @@ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, arr return $requestData + $this->getRequestAccountData($posAccount); } - /** - * 0 => '' - * 1 => '' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : ''; - } - - /** - * @inheritDoc - * - * @return string - */ - protected function mapCurrency(string $currency): string - { - return (string) ($this->currencyMappings[$currency] ?? $currency); - } - /** * @inheritDoc */ diff --git a/src/DataMapper/RequestDataMapper/KuveytPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/KuveytPosRequestDataMapper.php index bcb66946..3ff6adab 100644 --- a/src/DataMapper/RequestDataMapper/KuveytPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/KuveytPosRequestDataMapper.php @@ -13,6 +13,7 @@ use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; +use Mews\Pos\Gateways\KuveytPos; use Mews\Pos\PosInterface; /** @@ -23,53 +24,16 @@ class KuveytPosRequestDataMapper extends AbstractRequestDataMapper /** @var string */ public const API_VERSION = 'TDV2.0.0'; - /** @var string */ - public const CREDIT_CARD_EXP_YEAR_FORMAT = 'y'; - - /** @var string */ - public const CREDIT_CARD_EXP_MONTH_FORMAT = 'm'; - - /** - * {@inheritdoc} - */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3', - PosInterface::MODEL_NON_SECURE => '0', - ]; - - /** - * {@inheritDoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Sale', - PosInterface::TX_TYPE_CANCEL => 'SaleReversal', - PosInterface::TX_TYPE_STATUS => 'GetMerchantOrderDetail', - PosInterface::TX_TYPE_REFUND => 'DrawBack', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'PartialDrawback', - ]; - - /** - * {@inheritDoc} - */ - protected array $cardTypeMapping = [ - CreditCardInterface::CARD_TYPE_VISA => 'Visa', - CreditCardInterface::CARD_TYPE_MASTERCARD => 'MasterCard', - CreditCardInterface::CARD_TYPE_TROY => 'Troy', - ]; + /** @var KuveytPosCrypt */ + protected CryptInterface $crypt; /** - * Currency mapping - * - * {@inheritdoc} + * @inheritDoc */ - protected array $currencyMappings = [ - PosInterface::CURRENCY_TRY => '0949', - PosInterface::CURRENCY_USD => '0840', - PosInterface::CURRENCY_EUR => '0978', - ]; - - /** @var KuveytPosCrypt */ - protected CryptInterface $crypt; + public static function supports(string $gatewayClass): bool + { + return KuveytPos::class === $gatewayClass; + } /** * @param KuveytPosAccount $posAccount @@ -91,7 +55,7 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array 'Data' => $responseData['MD'], ], ], - 'TransactionType' => $this->mapTxType($txType), + 'TransactionType' => $this->valueMapper->mapTxType($txType), 'InstallmentCount' => $responseData['VPosMessage']['InstallmentCount'], 'Amount' => $responseData['VPosMessage']['Amount'], 'DisplayAmount' => $responseData['VPosMessage']['Amount'], @@ -115,7 +79,7 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array * @param string $txType * @param CreditCardInterface|null $creditCard * - * @return array|int|string> + * @return array|int|string|float> * * @throws UnsupportedTransactionTypeException */ @@ -125,13 +89,13 @@ public function create3DEnrollmentCheckRequestData(KuveytPosAccount $kuveytPosAc $requestData = $this->getRequestAccountData($kuveytPosAccount) + [ 'APIVersion' => self::API_VERSION, - 'TransactionType' => $this->mapTxType($txType), - 'TransactionSecurity' => $this->secureTypeMappings[$paymentModel], - 'InstallmentCount' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), + 'TransactionType' => $this->valueMapper->mapTxType($txType), + 'TransactionSecurity' => $this->valueMapper->mapSecureType($paymentModel), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => (int) $this->valueFormatter->formatAmount($order['amount']), //DisplayAmount: Amount değeri ile aynı olacak şekilde gönderilmelidir. - 'DisplayAmount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'DisplayAmount' => (int) $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'MerchantOrderId' => (string) $order['id'], 'OkUrl' => (string) $order['success_url'], 'FailUrl' => (string) $order['fail_url'], @@ -142,10 +106,10 @@ public function create3DEnrollmentCheckRequestData(KuveytPosAccount $kuveytPosAc if ($creditCard instanceof CreditCardInterface) { $requestData['CardHolderName'] = (string) $creditCard->getHolderName(); - $requestData['CardType'] = $creditCard->getType() !== null ? $this->cardTypeMapping[$creditCard->getType()] : ''; + $requestData['CardType'] = $creditCard->getType() !== null ? $this->valueMapper->mapCardType($creditCard->getType()) : ''; $requestData['CardNumber'] = $creditCard->getNumber(); - $requestData['CardExpireDateYear'] = $creditCard->getExpireYear(self::CREDIT_CARD_EXP_YEAR_FORMAT); - $requestData['CardExpireDateMonth'] = $creditCard->getExpireMonth(self::CREDIT_CARD_EXP_MONTH_FORMAT); + $requestData['CardExpireDateYear'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateYear'); + $requestData['CardExpireDateMonth'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateMonth'); $requestData['CardCVV2'] = $creditCard->getCvv(); } @@ -174,17 +138,17 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount $requestData = $this->getRequestAccountData($posAccount) + [ 'APIVersion' => self::API_VERSION, 'HashData' => '', - 'TransactionType' => $this->mapTxType($txType), + 'TransactionType' => $this->valueMapper->mapTxType($txType), 'TransactionSecurity' => '1', 'MerchantOrderId' => (string) $order['id'], - 'Amount' => $this->formatAmount($order['amount']), - 'DisplayAmount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), - 'InstallmentCount' => $this->mapInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'DisplayAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), 'CardHolderName' => $creditCard->getHolderName(), 'CardNumber' => $creditCard->getNumber(), - 'CardExpireDateYear' => $creditCard->getExpireYear(self::CREDIT_CARD_EXP_YEAR_FORMAT), - 'CardExpireDateMonth' => $creditCard->getExpireMonth(self::CREDIT_CARD_EXP_MONTH_FORMAT), + 'CardExpireDateYear' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateYear'), + 'CardExpireDateMonth' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateMonth'), 'CardCVV2' => $creditCard->getCvv(), ]; @@ -194,188 +158,54 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount } /** - * @param KuveytPosAccount $posAccount * {@inheritDoc} */ public function createStatusRequestData(AbstractPosAccount $posAccount, array $order): array { - $order = $this->prepareStatusOrder($order); - - $result = [ - 'IsFromExternalNetwork' => true, - 'BusinessKey' => 0, - 'ResourceId' => 0, - 'ActionId' => 0, - 'LanguageId' => 0, - 'CustomerId' => $posAccount->getCustomerId(), - 'MailOrTelephoneOrder' => true, - 'Amount' => 0, - 'MerchantId' => $posAccount->getClientId(), - 'MerchantOrderId' => $order['id'], - /** - * Eğer döndüğümüz orderid ile aratılırsa yalnızca aranan işlem gelir. - * 0 değeri girilirse tarih aralığındaki aynı merchanorderid'ye ait tüm siparişleri getirir. - * uniq değer orderid'dir, işlemi birebir yakalamak için orderid değeri atanmalıdır. - */ - 'OrderId' => $order['remote_order_id'] ?? 0, - /** - * Test ortamda denendiginde, StartDate ve EndDate her hangi bir tarih atandiginda istek calisiyor, - * siparisi buluyor. - * Ancak bu degerler gonderilmediginde veya gecersiz (orn. null) gonderildiginde SOAP server hata donuyor. - */ - 'StartDate' => $order['start_date']->format('Y-m-d\TH:i:s'), - 'EndDate' => $order['end_date']->format('Y-m-d\TH:i:s'), - 'TransactionType' => 0, - 'VPosMessage' => $this->getRequestAccountData($posAccount) + [ - 'APIVersion' => self::API_VERSION, - 'InstallmentMaturityCommisionFlag' => 0, - 'HashData' => '', - 'SubMerchantId' => 0, - 'CardType' => $this->cardTypeMapping[CreditCardInterface::CARD_TYPE_VISA], // Default gönderilebilir. - 'BatchID' => 0, - 'TransactionType' => $this->mapTxType(PosInterface::TX_TYPE_STATUS), - 'InstallmentCount' => 0, - 'Amount' => 0, - 'DisplayAmount' => 0, - 'CancelAmount' => 0, - 'MerchantOrderId' => $order['id'], - 'CurrencyCode' => $this->mapCurrency($order['currency']), - 'FECAmount' => 0, - 'QeryId' => 0, - 'DebtId' => 0, - 'SurchargeAmount' => 0, - 'SGKDebtAmount' => 0, - 'TransactionSecurity' => 1, - ], - ]; - - $result['VPosMessage']['HashData'] = $this->crypt->createHash($posAccount, $result['VPosMessage']); - - return [$this->mapTxType(PosInterface::TX_TYPE_STATUS) => ['request' => $result]]; + throw new NotImplementedException(); } /** - * @param KuveytPosAccount $posAccount * {@inheritDoc} */ public function createCancelRequestData(AbstractPosAccount $posAccount, array $order): array { - $order = $this->prepareCancelOrder($order); - - $result = [ - 'IsFromExternalNetwork' => true, - 'BusinessKey' => 0, - 'ResourceId' => 0, - 'ActionId' => 0, - 'LanguageId' => 0, - 'CustomerId' => $posAccount->getCustomerId(), - 'MailOrTelephoneOrder' => true, - 'Amount' => $this->formatAmount($order['amount']), - 'MerchantId' => $posAccount->getClientId(), - 'OrderId' => $order['remote_order_id'], - 'RRN' => $order['ref_ret_num'], - 'Stan' => $order['transaction_id'], - 'ProvisionNumber' => $order['auth_code'], - 'VPosMessage' => $this->getRequestAccountData($posAccount) + [ - 'APIVersion' => self::API_VERSION, - 'InstallmentMaturityCommisionFlag' => 0, - 'HashData' => '', - 'SubMerchantId' => 0, - 'CardType' => $this->cardTypeMapping[CreditCardInterface::CARD_TYPE_VISA], //Default gönderilebilir. - 'BatchID' => 0, - 'TransactionType' => $this->mapTxType(PosInterface::TX_TYPE_CANCEL), - 'InstallmentCount' => 0, - 'Amount' => $this->formatAmount($order['amount']), - 'DisplayAmount' => $this->formatAmount($order['amount']), - 'CancelAmount' => $this->formatAmount($order['amount']), - 'MerchantOrderId' => $order['id'], - 'FECAmount' => 0, - 'CurrencyCode' => $this->mapCurrency($order['currency']), - 'QeryId' => 0, - 'DebtId' => 0, - 'SurchargeAmount' => 0, - 'SGKDebtAmount' => 0, - 'TransactionSecurity' => 1, - ], - ]; - - $result['VPosMessage']['HashData'] = $this->crypt->createHash($posAccount, $result['VPosMessage']); - - return [$this->mapTxType(PosInterface::TX_TYPE_CANCEL) => ['request' => $result]]; + throw new NotImplementedException(); } /** - * @param KuveytPosAccount $posAccount * {@inheritDoc} */ public function createRefundRequestData(AbstractPosAccount $posAccount, array $order, string $refundTxType): array { - $order = $this->prepareRefundOrder($order); - - $result = [ - 'IsFromExternalNetwork' => true, - 'BusinessKey' => 0, - 'ResourceId' => 0, - 'ActionId' => 0, - 'LanguageId' => 0, - 'CustomerId' => $posAccount->getCustomerId(), - 'MailOrTelephoneOrder' => true, - 'Amount' => $this->formatAmount($order['amount']), - 'MerchantId' => $posAccount->getClientId(), - 'OrderId' => $order['remote_order_id'], - 'RRN' => $order['ref_ret_num'], - 'Stan' => $order['transaction_id'], - 'ProvisionNumber' => $order['auth_code'], - 'VPosMessage' => $this->getRequestAccountData($posAccount) + [ - 'APIVersion' => self::API_VERSION, - 'InstallmentMaturityCommisionFlag' => 0, - 'HashData' => '', - 'SubMerchantId' => 0, - 'CardType' => $this->cardTypeMapping[CreditCardInterface::CARD_TYPE_VISA], //Default gönderilebilir. - 'BatchID' => 0, - 'TransactionType' => $this->mapTxType($refundTxType), - 'InstallmentCount' => 0, - 'Amount' => $this->formatAmount($order['amount']), - 'DisplayAmount' => 0, - 'CancelAmount' => $this->formatAmount($order['amount']), - 'MerchantOrderId' => $order['id'], - 'FECAmount' => 0, - 'CurrencyCode' => $this->mapCurrency($order['currency']), - 'QeryId' => 0, - 'DebtId' => 0, - 'SurchargeAmount' => 0, - 'SGKDebtAmount' => 0, - 'TransactionSecurity' => 1, - ], - ]; - - $result['VPosMessage']['HashData'] = $this->crypt->createHash($posAccount, $result['VPosMessage']); - - return [$this->mapTxType($refundTxType) => ['request' => $result]]; + throw new NotImplementedException(); } /** + * @param KuveytPosAccount $posAccount + * * @inheritDoc */ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, array $requestData): array { - throw new NotImplementedException(); + $requestData += $this->getRequestAccountData($posAccount) + [ + 'APIVersion' => self::API_VERSION, + ]; + + if (!isset($requestData['HashData'])) { + $requestData['HashData'] = $this->crypt->createHash($posAccount, $requestData); + } + + return $requestData; } /** + * Küveyt Türk kendisi hazır HTML form gönderiyor. * {@inheritDoc} - * - * @param array $order Kuveyt bank'tan donen HTML cevaptan parse edilen form inputlar - * - * @return array{gateway: string, method: 'POST', inputs: array} */ - public function create3DFormData(AbstractPosAccount $posAccount, array $order, string $paymentModel, string $txType, string $gatewayURL, ?CreditCardInterface $creditCard = null): array + public function create3DFormData(AbstractPosAccount $posAccount, array $order, string $paymentModel, string $txType, string $gatewayURL, ?CreditCardInterface $creditCard = null) { - return [ - 'gateway' => $gatewayURL, - 'method' => 'POST', - 'inputs' => $order, - ]; + throw new NotImplementedException(); } /** @@ -394,30 +224,6 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar throw new NotImplementedException(); } - /** - * Amount Formatter - * converts 100 to 10000, or 10.01 to 1001 - * - * @param float $amount - * - * @return int - */ - protected function formatAmount(float $amount): int - { - return (int) (\round($amount, 2) * 100); - } - - /** - * 0 => '0' - * 1 => '0' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : '0'; - } - /** * @inheritDoc */ @@ -429,51 +235,6 @@ protected function preparePaymentOrder(array $order): array ]); } - /** - * @inheritDoc - */ - protected function prepareStatusOrder(array $order): array - { - return \array_merge($order, [ - 'id' => $order['id'], - 'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY, - 'start_date' => $order['start_date'] ?? date_create('-360 day'), - 'end_date' => $order['end_date'] ?? date_create(), - ]); - } - - /** - * @inheritDoc - */ - protected function prepareCancelOrder(array $order): array - { - return \array_merge($order, [ - 'id' => $order['id'], - 'remote_order_id' => $order['remote_order_id'], - 'ref_ret_num' => $order['ref_ret_num'], - 'auth_code' => $order['auth_code'], - 'transaction_id' => $order['transaction_id'], - 'amount' => $order['amount'], - 'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY, - ]); - } - - /** - * @inheritDoc - */ - protected function prepareRefundOrder(array $order): array - { - return \array_merge($order, [ - 'id' => $order['id'], - 'remote_order_id' => $order['remote_order_id'], - 'ref_ret_num' => $order['ref_ret_num'], - 'auth_code' => $order['auth_code'], - 'transaction_id' => $order['transaction_id'], - 'amount' => $order['amount'], - 'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY, - ]); - } - /** * @param KuveytPosAccount $posAccount * diff --git a/src/DataMapper/RequestDataMapper/KuveytSoapApiPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/KuveytSoapApiPosRequestDataMapper.php new file mode 100644 index 00000000..4f6fe3d0 --- /dev/null +++ b/src/DataMapper/RequestDataMapper/KuveytSoapApiPosRequestDataMapper.php @@ -0,0 +1,314 @@ +prepareStatusOrder($order); + + $result = [ + 'IsFromExternalNetwork' => true, + 'BusinessKey' => 0, + 'ResourceId' => 0, + 'ActionId' => 0, + 'LanguageId' => 0, + 'CustomerId' => $posAccount->getCustomerId(), + 'MailOrTelephoneOrder' => true, + 'Amount' => 0, + 'MerchantId' => $posAccount->getClientId(), + 'MerchantOrderId' => $order['id'], + /** + * Eğer döndüğümüz orderid ile aratılırsa yalnızca aranan işlem gelir. + * 0 değeri girilirse tarih aralığındaki aynı merchanorderid'ye ait tüm siparişleri getirir. + * uniq değer orderid'dir, işlemi birebir yakalamak için orderid değeri atanmalıdır. + */ + 'OrderId' => $order['remote_order_id'] ?? 0, + /** + * Test ortamda denendiginde, StartDate ve EndDate her hangi bir tarih atandiginda istek calisiyor, + * siparisi buluyor. + * Ancak bu degerler gonderilmediginde veya gecersiz (orn. null) gonderildiginde SOAP server hata donuyor. + */ + 'StartDate' => $this->valueFormatter->formatDateTime($order['start_date'], 'StartDate'), + 'EndDate' => $this->valueFormatter->formatDateTime($order['end_date'], 'EndDate'), + 'TransactionType' => 0, + 'VPosMessage' => $this->getRequestAccountData($posAccount) + [ + 'APIVersion' => self::API_VERSION, + 'InstallmentMaturityCommisionFlag' => 0, + 'HashData' => '', + 'SubMerchantId' => 0, + 'CardType' => $this->valueMapper->mapCardType(CreditCardInterface::CARD_TYPE_VISA), //Default gönderilebilir. + 'BatchID' => 0, + 'TransactionType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_STATUS), + 'InstallmentCount' => 0, + 'Amount' => 0, + 'DisplayAmount' => 0, + 'CancelAmount' => 0, + 'MerchantOrderId' => $order['id'], + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'FECAmount' => 0, + 'QeryId' => 0, + 'DebtId' => 0, + 'SurchargeAmount' => 0, + 'SGKDebtAmount' => 0, + 'TransactionSecurity' => 1, + ], + ]; + + $result['VPosMessage']['HashData'] = $this->crypt->createHash($posAccount, $result['VPosMessage']); + + return [$result['VPosMessage']['TransactionType'] => ['request' => $result]]; + } + + /** + * @param KuveytPosAccount $posAccount + * {@inheritDoc} + */ + public function createCancelRequestData(AbstractPosAccount $posAccount, array $order): array + { + $order = $this->prepareCancelOrder($order); + + $result = [ + 'IsFromExternalNetwork' => true, + 'BusinessKey' => 0, + 'ResourceId' => 0, + 'ActionId' => 0, + 'LanguageId' => 0, + 'CustomerId' => $posAccount->getCustomerId(), + 'MailOrTelephoneOrder' => true, + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'MerchantId' => $posAccount->getClientId(), + 'OrderId' => $order['remote_order_id'], + 'RRN' => $order['ref_ret_num'], + 'Stan' => $order['transaction_id'], + 'ProvisionNumber' => $order['auth_code'], + 'VPosMessage' => $this->getRequestAccountData($posAccount) + [ + 'APIVersion' => self::API_VERSION, + 'InstallmentMaturityCommisionFlag' => 0, + 'HashData' => '', + 'SubMerchantId' => 0, + 'CardType' => $this->valueMapper->mapCardType(CreditCardInterface::CARD_TYPE_VISA), //Default gönderilebilir. + 'BatchID' => 0, + 'TransactionType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL), + 'InstallmentCount' => 0, + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'DisplayAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'CancelAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'MerchantOrderId' => $order['id'], + 'FECAmount' => 0, + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'QeryId' => 0, + 'DebtId' => 0, + 'SurchargeAmount' => 0, + 'SGKDebtAmount' => 0, + 'TransactionSecurity' => 1, + ], + ]; + + $result['VPosMessage']['HashData'] = $this->crypt->createHash($posAccount, $result['VPosMessage']); + + return [$result['VPosMessage']['TransactionType'] => ['request' => $result]]; + } + + /** + * @param KuveytPosAccount $posAccount + * {@inheritDoc} + */ + public function createRefundRequestData(AbstractPosAccount $posAccount, array $order, string $refundTxType): array + { + $order = $this->prepareRefundOrder($order); + + $result = [ + 'IsFromExternalNetwork' => true, + 'BusinessKey' => 0, + 'ResourceId' => 0, + 'ActionId' => 0, + 'LanguageId' => 0, + 'CustomerId' => $posAccount->getCustomerId(), + 'MailOrTelephoneOrder' => true, + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'MerchantId' => $posAccount->getClientId(), + 'OrderId' => $order['remote_order_id'], + 'RRN' => $order['ref_ret_num'], + 'Stan' => $order['transaction_id'], + 'ProvisionNumber' => $order['auth_code'], + 'VPosMessage' => $this->getRequestAccountData($posAccount) + [ + 'APIVersion' => self::API_VERSION, + 'InstallmentMaturityCommisionFlag' => 0, + 'HashData' => '', + 'SubMerchantId' => 0, + 'CardType' => $this->valueMapper->mapCardType(CreditCardInterface::CARD_TYPE_VISA), //Default gönderilebilir. + 'BatchID' => 0, + 'TransactionType' => $this->valueMapper->mapTxType($refundTxType), + 'InstallmentCount' => 0, + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'DisplayAmount' => 0, + 'CancelAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'MerchantOrderId' => $order['id'], + 'FECAmount' => 0, + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'QeryId' => 0, + 'DebtId' => 0, + 'SurchargeAmount' => 0, + 'SGKDebtAmount' => 0, + 'TransactionSecurity' => 1, + ], + ]; + + $result['VPosMessage']['HashData'] = $this->crypt->createHash($posAccount, $result['VPosMessage']); + + return [$result['VPosMessage']['TransactionType'] => ['request' => $result]]; + } + + /** + * @inheritDoc + */ + public function createCustomQueryRequestData(AbstractPosAccount $posAccount, array $requestData): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function create3DFormData(AbstractPosAccount $posAccount, array $order, string $paymentModel, string $txType, string $gatewayURL, ?CreditCardInterface $creditCard = null) + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function createHistoryRequestData(AbstractPosAccount $posAccount, array $data = []): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, array $order): array + { + throw new NotImplementedException(); + } + + /** + * @inheritDoc + */ + protected function prepareStatusOrder(array $order): array + { + return \array_merge($order, [ + 'id' => $order['id'], + 'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY, + 'start_date' => $order['start_date'] ?? date_create('-360 day'), + 'end_date' => $order['end_date'] ?? date_create(), + ]); + } + + /** + * @inheritDoc + */ + protected function prepareCancelOrder(array $order): array + { + return \array_merge($order, [ + 'id' => $order['id'], + 'remote_order_id' => $order['remote_order_id'], + 'ref_ret_num' => $order['ref_ret_num'], + 'auth_code' => $order['auth_code'], + 'transaction_id' => $order['transaction_id'], + 'amount' => $order['amount'], + 'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY, + ]); + } + + /** + * @inheritDoc + */ + protected function prepareRefundOrder(array $order): array + { + return \array_merge($order, [ + 'id' => $order['id'], + 'remote_order_id' => $order['remote_order_id'], + 'ref_ret_num' => $order['ref_ret_num'], + 'auth_code' => $order['auth_code'], + 'transaction_id' => $order['transaction_id'], + 'amount' => $order['amount'], + 'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY, + ]); + } + + /** + * @param KuveytPosAccount $posAccount + * + * @return array{MerchantId: string, CustomerId: string, UserName: string} + */ + private function getRequestAccountData(AbstractPosAccount $posAccount): array + { + return [ + 'MerchantId' => $posAccount->getClientId(), + 'CustomerId' => $posAccount->getCustomerId(), + 'UserName' => $posAccount->getUsername(), + ]; + } +} diff --git a/src/DataMapper/RequestDataMapper/Param3DHostPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/Param3DHostPosRequestDataMapper.php new file mode 100644 index 00000000..03614889 --- /dev/null +++ b/src/DataMapper/RequestDataMapper/Param3DHostPosRequestDataMapper.php @@ -0,0 +1,227 @@ + + */ + public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array $order, string $txType, array $responseData): array + { + throw new NotImplementedException(); + } + + /** + * @param ParamPosAccount $posAccount + * @param array $order + * @param PosInterface::TX_TYPE_PAY_* $txType + * + * @return array + */ + public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccount, array $order, string $txType): array + { + $order = $this->preparePaymentOrder($order); + + $requestData = [ + '@xmlns' => 'https://turkodeme.com.tr/', + // Bu alan editable olsun istiyorsanız başına “e|”, + // readonly olsun istiyorsanız başına “r|” eklemelisiniz. + 'Borclu_Tutar' => 'r|'.$this->valueFormatter->formatAmount($order['amount'], $txType), + 'Borclu_Odeme_Tip' => 'r|Diğer', + 'Borclu_AdSoyad' => 'r|', + 'Borclu_Aciklama' => 'r|', + 'Return_URL' => 'r|'.$order['success_url'], + 'Islem_ID' => $this->crypt->generateRandomString(), + 'Borclu_Kisi_TC' => '', + 'Terminal_ID' => $posAccount->getClientId(), + 'Borclu_GSM' => 'r|', + // = 0 ise tüm taksitler listelenir. > 0 ise sadece o taksit seçeneği listelenir. + 'Taksit' => $this->valueFormatter->formatInstallment((int) $order['installment']), + ]; + + if (PosInterface::CURRENCY_TRY !== $order['currency']) { + $requestData['Doviz_Kodu'] = $this->valueMapper->mapCurrency($order['currency']); + } + + $soapAction = $this->valueMapper->mapTxType($txType, PosInterface::MODEL_3D_HOST); + + return $this->wrapSoapEnvelope([$soapAction => $requestData], $posAccount); + } + + /** + * {@inheritDoc} + * @return array> + */ + public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount, array $order, string $txType, CreditCardInterface $creditCard): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $posAccount, array $order): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function createStatusRequestData(AbstractPosAccount $posAccount, array $order): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function createCancelRequestData(AbstractPosAccount $posAccount, array $order): array + { + throw new NotImplementedException(); + } + + + /** + * {@inheritDoc} + */ + public function createRefundRequestData(AbstractPosAccount $posAccount, array $order, string $refundTxType): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, array $order): array + { + throw new NotImplementedException(); + } + + + /** + * {@inheritDoc} + */ + public function createHistoryRequestData(AbstractPosAccount $posAccount, array $data = []): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + * + * @param array $extraData + */ + public function create3DFormData( + ?AbstractPosAccount $posAccount, + ?array $order, + string $paymentModel, + string $txType, + ?string $gatewayURL = null, + ?CreditCardInterface $creditCard = null, + array $extraData = [] + ) { + if (PosInterface::MODEL_3D_HOST !== $paymentModel) { + throw new \InvalidArgumentException(); + } + if (null === $gatewayURL) { + throw new \InvalidArgumentException('Please provide $gatewayURL'); + } + + $decoded = \base64_decode($extraData['TO_Pre_Encrypting_OOSResponse']['TO_Pre_Encrypting_OOSResult'], true); + if (false === $decoded) { + throw new \RuntimeException($extraData['TO_Pre_Encrypting_OOSResponse']['TO_Pre_Encrypting_OOSResult']); + } + + $inputs = [ + 's' => (string) $extraData['TO_Pre_Encrypting_OOSResponse']['TO_Pre_Encrypting_OOSResult'], + ]; + + return [ + 'gateway' => $gatewayURL, + 'method' => 'GET', + 'inputs' => $inputs, + ]; + } + + /** + * @inheritDoc + */ + public function createCustomQueryRequestData(AbstractPosAccount $posAccount, array $requestData): array + { + throw new NotImplementedException(); + } + + /** + * @inheritDoc + */ + protected function preparePaymentOrder(array $order): array + { + return \array_merge($order, [ + 'installment' => $order['installment'] ?? 0, + 'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY, + 'amount' => $order['amount'], + 'ip' => $order['ip'], + ]); + } + + /** + * @param array $data + * @param AbstractPosAccount $posAccount + * + * @return array{"soap:Body": array, "soap:Header"?: array} + */ + private function wrapSoapEnvelope(array $data, AbstractPosAccount $posAccount): array + { + return [ + 'soap:Header' => [ + 'ServiceSecuritySoapHeader' => [ + '@xmlns' => 'https://turkodeme.com.tr/', + 'CLIENT_CODE' => $posAccount->getClientId(), + 'CLIENT_USERNAME' => $posAccount->getUsername(), + 'CLIENT_PASSWORD' => $posAccount->getPassword(), + ], + ], + 'soap:Body' => $data, + ]; + } +} diff --git a/src/DataMapper/RequestDataMapper/ParamPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/ParamPosRequestDataMapper.php index 7cad486f..7e2689d7 100644 --- a/src/DataMapper/RequestDataMapper/ParamPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/ParamPosRequestDataMapper.php @@ -6,85 +6,38 @@ namespace Mews\Pos\DataMapper\RequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\ParamPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueFormatter\RequestValueFormatterInterface; +use Mews\Pos\DataMapper\RequestValueMapper\ParamPosRequestValueMapper; +use Mews\Pos\DataMapper\RequestValueMapper\RequestValueMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\ParamPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\ParamPos; use Mews\Pos\PosInterface; /** - * Creates request data for ParamPoss Gateway requests + * Creates request data for ParamPos Gateway requests */ class ParamPosRequestDataMapper extends AbstractRequestDataMapper { - /** @var string */ - public const CREDIT_CARD_EXP_MONTH_FORMAT = 'm'; - - /** @var string */ - public const CREDIT_CARD_EXP_YEAR_FORMAT = 'Y'; - - /** - * {@inheritDoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => [ - PosInterface::MODEL_NON_SECURE => 'TP_WMD_UCD', - PosInterface::MODEL_3D_SECURE => 'TP_WMD_UCD', - PosInterface::MODEL_3D_PAY => 'Pos_Odeme', - PosInterface::MODEL_3D_HOST => 'TO_Pre_Encrypting_OOS', - ], - PosInterface::TX_TYPE_PAY_PRE_AUTH => [ - PosInterface::MODEL_NON_SECURE => 'TP_Islem_Odeme_OnProv_WMD', - PosInterface::MODEL_3D_SECURE => 'TP_Islem_Odeme_OnProv_WMD', - ], - PosInterface::TX_TYPE_PAY_POST_AUTH => 'TP_Islem_Odeme_OnProv_Kapa', - PosInterface::TX_TYPE_REFUND => 'TP_Islem_Iptal_Iade_Kismi2', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'TP_Islem_Iptal_Iade_Kismi2', - PosInterface::TX_TYPE_CANCEL => 'TP_Islem_Iptal_Iade_Kismi2', - PosInterface::TX_TYPE_STATUS => 'TP_Islem_Sorgulama4', - PosInterface::TX_TYPE_HISTORY => 'TP_Islem_Izleme', - ]; - /** - * {@inheritdoc} + * @var ParamPosRequestValueMapper */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3D', - PosInterface::MODEL_3D_PAY => '3D', - PosInterface::MODEL_NON_SECURE => 'NS', - ]; + protected RequestValueMapperInterface $valueMapper; /** - * {@inheritdoc} + * @var ParamPosRequestValueFormatter */ - protected array $currencyMappings = [ - PosInterface::CURRENCY_TRY => '1000', - PosInterface::CURRENCY_USD => '1001', - PosInterface::CURRENCY_EUR => '1002', - PosInterface::CURRENCY_GBP => '1003', - ]; + protected RequestValueFormatterInterface $valueFormatter; /** - * @param PosInterface::TX_TYPE_* $txType - * @param PosInterface::MODEL_*|null $paymentModel - * @param PosInterface::TX_TYPE_PAY_*|null $orderTxType - * @param PosInterface::CURRENCY_*|null $currency - * - * @return string - * - * @throws \Mews\Pos\Exceptions\UnsupportedTransactionTypeException + * @inheritDoc */ - public function mapTxType(string $txType, ?string $paymentModel = null, ?string $orderTxType = null, ?string $currency = null): string + public static function supports(string $gatewayClass): bool { - if (null !== $currency && PosInterface::CURRENCY_TRY !== $currency) { - return 'TP_Islem_Odeme_WD'; - } - - if (PosInterface::TX_TYPE_CANCEL === $txType && PosInterface::TX_TYPE_PAY_PRE_AUTH === $orderTxType) { - return 'TP_Islem_Iptal_OnProv'; - } - - return parent::mapTxType($txType, $paymentModel); + return ParamPos::class === $gatewayClass; } /** @@ -101,7 +54,7 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array 'Siparis_ID' => (string) $responseData['orderId'], ]; - return $this->wrapSoapEnvelope(['TP_WMD_Pay' => $requestData], $posAccount); + return $this->wrapSoapEnvelope(['TP_WMD_Pay' => $requestData]); } /** @@ -116,7 +69,7 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccount, array $order, ?CreditCardInterface $creditCard, string $txType, string $paymentModel): array { if (PosInterface::MODEL_3D_HOST === $paymentModel) { - return $this->create3DHostEnrollmentCheckRequestData($posAccount, $order, $txType); + throw new \InvalidArgumentException(); } if (!$creditCard instanceof \Mews\Pos\Entity\Card\CreditCardInterface) { @@ -127,73 +80,34 @@ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccoun $requestData = $this->getRequestAccountData($posAccount) + [ '@xmlns' => 'https://turkpos.com.tr/', - 'Islem_Guvenlik_Tip' => $this->secureTypeMappings[$paymentModel], + 'Islem_Guvenlik_Tip' => $this->valueMapper->mapSecureType($paymentModel), 'Islem_ID' => $this->crypt->generateRandomString(), 'IPAdr' => (string) $order['ip'], 'Siparis_ID' => (string) $order['id'], - 'Islem_Tutar' => $this->formatAmount($order['amount']), - 'Toplam_Tutar' => $this->formatAmount($order['amount']), + 'Islem_Tutar' => $this->valueFormatter->formatAmount($order['amount'], $txType), + 'Toplam_Tutar' => $this->valueFormatter->formatAmount($order['amount'], $txType), 'Basarili_URL' => (string) $order['success_url'], 'Hata_URL' => (string) $order['fail_url'], - 'Taksit' => $this->mapInstallment((int) $order['installment']), + 'Taksit' => $this->valueFormatter->formatInstallment((int) $order['installment']), 'KK_Sahibi' => $creditCard->getHolderName(), 'KK_No' => $creditCard->getNumber(), - 'KK_SK_Ay' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_MONTH_FORMAT), - 'KK_SK_Yil' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_YEAR_FORMAT), + 'KK_SK_Ay' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'KK_SK_Ay'), + 'KK_SK_Yil' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'KK_SK_Yil'), 'KK_CVC' => $creditCard->getCvv(), 'KK_Sahibi_GSM' => '', //optional olmasina ragmen hic gonderilmeyince hata aliniyor. ]; if (PosInterface::CURRENCY_TRY !== $order['currency']) { - $requestData['Doviz_Kodu'] = $this->mapCurrency($order['currency']); + $requestData['Doviz_Kodu'] = $this->valueMapper->mapCurrency($order['currency']); } - $soapAction = $this->mapTxType($txType, $paymentModel, null, $order['currency']); + $soapAction = $this->valueMapper->mapTxType($txType, $paymentModel, $order); $requestData = [$soapAction => $requestData]; $requestData[$soapAction]['Islem_Hash'] = $this->crypt->createHash($posAccount, $requestData); - return $this->wrapSoapEnvelope($requestData, $posAccount); - } - - /** - * @param AbstractPosAccount $posAccount - * @param array $order - * @param PosInterface::TX_TYPE_PAY_* $txType - * - * @return array - * - * @throws \Mews\Pos\Exceptions\UnsupportedTransactionTypeException - */ - public function create3DHostEnrollmentCheckRequestData(AbstractPosAccount $posAccount, array $order, string $txType): array - { - $order = $this->preparePaymentOrder($order); - - $requestData = [ - '@xmlns' => 'https://turkodeme.com.tr/', - // Bu alan editable olsun istiyorsanız başına “e|”, - // readonly olsun istiyorsanız başına “r|” eklemelisiniz. - 'Borclu_Tutar' => 'r|'.$this->formatAmount($order['amount']), - 'Borclu_Odeme_Tip' => 'r|Diğer', - 'Borclu_AdSoyad' => 'r|', - 'Borclu_Aciklama' => 'r|', - 'Return_URL' => 'r|'.$order['success_url'], - 'Islem_ID' => $this->crypt->generateRandomString(), - 'Borclu_Kisi_TC' => '', - 'Terminal_ID' => $posAccount->getClientId(), - 'Borclu_GSM' => 'r|', - // = 0 ise tüm taksitler listelenir. > 0 ise sadece o taksit seçeneği listelenir. - 'Taksit' => $this->mapInstallment((int) $order['installment']), - ]; - - if (PosInterface::CURRENCY_TRY !== $order['currency']) { - $requestData['Doviz_Kodu'] = $this->mapCurrency($order['currency']); - } - - $soapAction = $this->mapTxType($txType, PosInterface::MODEL_3D_HOST); - - return $this->wrapSoapEnvelope([$soapAction => $requestData], $posAccount); + return $this->wrapSoapEnvelope($requestData); } /** @@ -206,38 +120,38 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount $requestData = $this->getRequestAccountData($posAccount) + [ '@xmlns' => 'https://turkpos.com.tr/', - 'Islem_Guvenlik_Tip' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], + 'Islem_Guvenlik_Tip' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), 'Islem_ID' => $this->crypt->generateRandomString(), 'IPAdr' => (string) $order['ip'], 'Siparis_ID' => (string) $order['id'], - 'Islem_Tutar' => $this->formatAmount($order['amount']), - 'Toplam_Tutar' => $this->formatAmount($order['amount']), - 'Taksit' => $this->mapInstallment((int) $order['installment']), + 'Islem_Tutar' => $this->valueFormatter->formatAmount($order['amount'], $txType), + 'Toplam_Tutar' => $this->valueFormatter->formatAmount($order['amount'], $txType), + 'Taksit' => $this->valueFormatter->formatInstallment((int) $order['installment']), 'KK_Sahibi' => $creditCard->getHolderName(), 'KK_No' => $creditCard->getNumber(), - 'KK_SK_Ay' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_MONTH_FORMAT), - 'KK_SK_Yil' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_YEAR_FORMAT), + 'KK_SK_Ay' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'KK_SK_Ay'), + 'KK_SK_Yil' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'KK_SK_Yil'), 'KK_CVC' => $creditCard->getCvv(), 'KK_Sahibi_GSM' => '', //optional olmasina ragmen hic gonderilmeyince hata aliniyor. ]; if (PosInterface::CURRENCY_TRY !== $order['currency']) { - $requestData['Doviz_Kodu'] = $this->mapCurrency($order['currency']); + $requestData['Doviz_Kodu'] = $this->valueMapper->mapCurrency($order['currency']); $requestData['Basarili_URL'] = (string) $order['success_url']; $requestData['Hata_URL'] = (string) $order['fail_url']; } - $soapAction = $this->mapTxType($txType, PosInterface::MODEL_NON_SECURE, null, $order['currency']); + $soapAction = $this->valueMapper->mapTxType($txType, PosInterface::MODEL_NON_SECURE, $order); if (PosInterface::TX_TYPE_PAY_PRE_AUTH === $txType) { - $soapAction = $this->mapTxType($txType, PosInterface::MODEL_NON_SECURE); + $soapAction = $this->valueMapper->mapTxType($txType, PosInterface::MODEL_NON_SECURE); } $requestData = [$soapAction => $requestData]; $requestData[$soapAction]['Islem_Hash'] = $this->crypt->createHash($posAccount, $requestData); - return $this->wrapSoapEnvelope($requestData, $posAccount); + return $this->wrapSoapEnvelope($requestData); } /** @@ -250,13 +164,13 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po $requestData = $this->getRequestAccountData($posAccount) + [ '@xmlns' => 'https://turkpos.com.tr/', 'Prov_ID' => '', - 'Prov_Tutar' => $this->formatAmount($order['amount']), + 'Prov_Tutar' => $this->valueFormatter->formatAmount($order['amount'], PosInterface::TX_TYPE_PAY_POST_AUTH), 'Siparis_ID' => (string) $order['id'], ]; return $this->wrapSoapEnvelope([ - $this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH) => $requestData, - ], $posAccount); + $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH) => $requestData, + ]); } /** @@ -272,8 +186,8 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o ]; return $this->wrapSoapEnvelope([ - $this->mapTxType(PosInterface::TX_TYPE_STATUS) => $requestData, - ], $posAccount); + $this->valueMapper->mapTxType(PosInterface::TX_TYPE_STATUS) => $requestData, + ]); } /** @@ -294,13 +208,13 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o '@xmlns' => 'https://turkpos.com.tr/', 'Durum' => 'IPTAL', 'Siparis_ID' => $order['id'], - 'Tutar' => $order['amount'], + 'Tutar' => $this->valueFormatter->formatAmount($order['amount'], PosInterface::TX_TYPE_CANCEL), ]; } return $this->wrapSoapEnvelope([ - $this->mapTxType(PosInterface::TX_TYPE_CANCEL, null, $order['transaction_type']) => $requestData, - ], $posAccount); + $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL, null, $order) => $requestData, + ]); } @@ -315,10 +229,12 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o '@xmlns' => 'https://turkpos.com.tr/', 'Durum' => 'IADE', 'Siparis_ID' => $order['id'], - 'Tutar' => $order['amount'], + 'Tutar' => $this->valueFormatter->formatAmount($order['amount'], $refundTxType), ]; - return $this->wrapSoapEnvelope([$this->mapTxType($refundTxType) => $requestData], $posAccount); + return $this->wrapSoapEnvelope([ + $this->valueMapper->mapTxType($refundTxType) => $requestData, + ]); } /** @@ -339,8 +255,8 @@ public function createHistoryRequestData(AbstractPosAccount $posAccount, array $ $requestData = $this->getRequestAccountData($posAccount) + [ '@xmlns' => 'https://turkpos.com.tr/', - 'Tarih_Bas' => $this->formatRequestDateTime($order['start_date']), - 'Tarih_Bit' => $this->formatRequestDateTime($order['end_date']), + 'Tarih_Bas' => $this->valueFormatter->formatDateTime($order['start_date'], 'Tarih_Bas'), + 'Tarih_Bit' => $this->valueFormatter->formatDateTime($order['end_date'], 'Tarih_Bit'), ]; if (isset($data['order_status'])) { @@ -358,8 +274,8 @@ public function createHistoryRequestData(AbstractPosAccount $posAccount, array $ } return $this->wrapSoapEnvelope([ - $this->mapTxType(PosInterface::TX_TYPE_HISTORY) => $requestData, - ], $posAccount); + $this->valueMapper->mapTxType(PosInterface::TX_TYPE_HISTORY) => $requestData, + ]); } /** @@ -377,24 +293,7 @@ public function create3DFormData( array $extraData = [] ) { if (PosInterface::MODEL_3D_HOST === $paymentModel) { - if (null === $gatewayURL) { - throw new \InvalidArgumentException('Please provide $gatewayURL'); - } - - $decoded = \base64_decode($extraData['TO_Pre_Encrypting_OOSResponse']['TO_Pre_Encrypting_OOSResult'], true); - if (false === $decoded) { - throw new \RuntimeException($extraData['TO_Pre_Encrypting_OOSResponse']['TO_Pre_Encrypting_OOSResult']); - } - - $inputs = [ - 's' => (string) $extraData['TO_Pre_Encrypting_OOSResponse']['TO_Pre_Encrypting_OOSResult'], - ]; - - return [ - 'gateway' => $gatewayURL, - 'method' => 'GET', - 'inputs' => $inputs, - ]; + throw new \InvalidArgumentException(); } if (PosInterface::MODEL_3D_PAY === $paymentModel) { @@ -441,18 +340,7 @@ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, arr $soapAction = \array_key_first($requestData); $requestData[$soapAction] += $this->getRequestAccountData($posAccount); - return $this->wrapSoapEnvelope($requestData, $posAccount); - } - - /** - * 0 => '1' - * 1 => '1' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : '1'; + return $this->wrapSoapEnvelope($requestData); } /** @@ -492,28 +380,6 @@ protected function prepareRefundOrder(array $order): array ]; } - /** - * @inheritDoc - * - * @return string - */ - protected function mapCurrency(string $currency): string - { - return (string) ($this->currencyMappings[$currency] ?? $currency); - } - - /** - * 10.0 => 10,00 - * 1000.5 => 1000,50 - * @param float $amount - * - * @return string - */ - protected function formatAmount(float $amount): string - { - return \number_format($amount, 2, ',', ''); - } - /** * @inheritDoc */ @@ -543,38 +409,13 @@ private function getRequestAccountData(AbstractPosAccount $posAccount): array ]; } - /** - * @param \DateTimeInterface $dateTime - * - * @return string example 20.11.2018 15:00:00 - */ - private function formatRequestDateTime(\DateTimeInterface $dateTime): string - { - return $dateTime->format('d.m.Y H:i:s'); - } - /** * @param array $data - * @param AbstractPosAccount $posAccount * - * @return array{"soap:Body": array, "soap:Header"?: array} + * @return array{"soap:Body": array} */ - private function wrapSoapEnvelope(array $data, AbstractPosAccount $posAccount): array + private function wrapSoapEnvelope(array $data): array { - if (isset($data['TO_Pre_Encrypting_OOS'])) { - return [ - 'soap:Header' => [ - 'ServiceSecuritySoapHeader' => [ - '@xmlns' => 'https://turkodeme.com.tr/', - 'CLIENT_CODE' => $posAccount->getClientId(), - 'CLIENT_USERNAME' => $posAccount->getUsername(), - 'CLIENT_PASSWORD' => $posAccount->getPassword(), - ], - ], - 'soap:Body' => $data, - ]; - } - return [ 'soap:Body' => $data, ]; diff --git a/src/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapper.php index fcbb1f07..7ae9db6b 100644 --- a/src/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapper.php @@ -11,6 +11,7 @@ use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; +use Mews\Pos\Gateways\PayFlexCPV4Pos; use Mews\Pos\PosInterface; /** @@ -19,34 +20,12 @@ class PayFlexCPV4PosRequestDataMapper extends AbstractRequestDataMapper { /** - * {@inheritDoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Sale', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capture', - PosInterface::TX_TYPE_CANCEL => 'Cancel', - PosInterface::TX_TYPE_REFUND => 'Refund', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', - ]; - - /** - * {@inheritdoc} - */ - protected array $cardTypeMapping = [ - CreditCardInterface::CARD_TYPE_VISA => '100', - CreditCardInterface::CARD_TYPE_MASTERCARD => '200', - CreditCardInterface::CARD_TYPE_TROY => '300', - CreditCardInterface::CARD_TYPE_AMEX => '400', - ]; - - /** - * {@inheritdoc} + * @inheritDoc */ - protected array $langMappings = [ - PosInterface::LANG_TR => 'tr-TR', - PosInterface::LANG_EN => 'en-US', - ]; + public static function supports(string $gatewayClass): bool + { + return PayFlexCPV4Pos::class === $gatewayClass; + } /** * {@inheritDoc} @@ -95,9 +74,9 @@ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccoun 'HostMerchantId' => $posAccount->getClientId(), 'MerchantPassword' => $posAccount->getPassword(), 'HostTerminalId' => $posAccount->getTerminalId(), - 'TransactionType' => $this->mapTxType($txType), - 'AmountCode' => $this->mapCurrency($order['currency']), - 'Amount' => $this->formatAmount($order['amount']), + 'TransactionType' => $this->valueMapper->mapTxType($txType), + 'AmountCode' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'Amount' => (string) $this->valueFormatter->formatAmount($order['amount']), 'OrderID' => (string) $order['id'], 'IsSecure' => 'true', // Işlemin 3D yapılıp yapılmayacağına dair flag, alabileceği değerler: 'true', 'false' /** @@ -110,7 +89,7 @@ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccoun 'AllowNotEnrolledCard' => 'false', 'SuccessUrl' => (string) $order['success_url'], 'FailUrl' => (string) $order['fail_url'], - 'RequestLanguage' => $this->getLang($posAccount, $order), + 'RequestLanguage' => $this->getLang($order), /** * Bu alanda gönderilecek değer kart hamili * ektresinde işlem açıklamasında çıkacaktır. @@ -127,17 +106,17 @@ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccoun if ($creditCard instanceof CreditCardInterface) { $requestData += [ - 'BrandNumber' => $creditCard->getType() !== null ? $this->cardTypeMapping[$creditCard->getType()] : '', + 'BrandNumber' => $creditCard->getType() !== null ? $this->valueMapper->mapCardType($creditCard->getType()) : '', 'CVV' => $creditCard->getCvv(), 'PAN' => $creditCard->getNumber(), - 'ExpireMonth' => $creditCard->getExpireMonth(), - 'ExpireYear' => $creditCard->getExpireYear(), + 'ExpireMonth' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'ExpireMonth'), + 'ExpireYear' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'ExpireYear'), 'CardHoldersName' => (string) $creditCard->getHolderName(), ]; } if ($order['installment']) { - $requestData['InstallmentCount'] = $this->mapInstallment($order['installment']); + $requestData['InstallmentCount'] = (string) $this->valueFormatter->formatInstallment($order['installment']); } $requestData['HashedData'] = $this->crypt->createHash($posAccount, $requestData); @@ -237,39 +216,6 @@ public function create3DFormData( ]; } - /** - * Amount Formatter - * - * @param float $amount - * - * @return string ex: 10.1 => 10.10 - */ - protected function formatAmount(float $amount): string - { - return \number_format($amount, 2, '.', ''); - } - - /** - * 0 => '0' - * 1 => '0' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : '0'; - } - - /** - * @inheritDoc - * - * @return string - */ - protected function mapCurrency(string $currency): string - { - return (string) ($this->currencyMappings[$currency] ?? $currency); - } - /** * @inheritDoc */ diff --git a/src/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapper.php index 19369d1d..e7b446ca 100644 --- a/src/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapper.php @@ -12,6 +12,7 @@ use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; +use Mews\Pos\Gateways\PayFlexV4Pos; use Mews\Pos\PosInterface; /** @@ -19,43 +20,13 @@ */ class PayFlexV4PosRequestDataMapper extends AbstractRequestDataMapper { - /** @var string */ - public const CREDIT_CARD_EXP_DATE_LONG_FORMAT = 'Ym'; - - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'ym'; - - /** - * {@inheritDoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Sale', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capture', - PosInterface::TX_TYPE_CANCEL => 'Cancel', - PosInterface::TX_TYPE_REFUND => 'Refund', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', - PosInterface::TX_TYPE_STATUS => 'status', - ]; - - /** - * {@inheritdoc} - */ - protected array $cardTypeMapping = [ - CreditCardInterface::CARD_TYPE_VISA => '100', - CreditCardInterface::CARD_TYPE_MASTERCARD => '200', - CreditCardInterface::CARD_TYPE_TROY => '300', - CreditCardInterface::CARD_TYPE_AMEX => '400', - ]; - /** - * {@inheritdoc} + * @inheritDoc */ - protected array $recurringOrderFrequencyMapping = [ - 'DAY' => 'Day', - 'MONTH' => 'Month', - 'YEAR' => 'Year', - ]; + public static function supports(string $gatewayClass): bool + { + return PayFlexV4Pos::class === $gatewayClass; + } /** * @param PayFlexAccount $posAccount @@ -72,10 +43,10 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array $order = $this->preparePaymentOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'TransactionType' => $this->mapTxType($txType), + 'TransactionType' => $this->valueMapper->mapTxType($txType), 'TransactionId' => (string) $order['id'], - 'CurrencyAmount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'CurrencyAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'ECI' => $responseData['Eci'], 'CAVV' => $responseData['Cavv'], 'MpiTransactionId' => $responseData['VerifyEnrollmentRequestId'], @@ -85,11 +56,11 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array 'CardHoldersName' => $creditCard->getHolderName(), 'Cvv' => $creditCard->getCvv(), 'Pan' => $creditCard->getNumber(), - 'Expiry' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_LONG_FORMAT), + 'Expiry' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Expiry'), ]; if ($order['installment']) { - $requestData['NumberOfInstallments'] = $this->mapInstallment($order['installment']); + $requestData['NumberOfInstallments'] = $this->valueFormatter->formatInstallment($order['installment']); } return $requestData; @@ -110,18 +81,18 @@ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccoun 'MerchantId' => $posAccount->getClientId(), 'MerchantPassword' => $posAccount->getPassword(), 'MerchantType' => $posAccount->getMerchantType(), - 'PurchaseAmount' => $this->formatAmount($order['amount']), + 'PurchaseAmount' => $this->valueFormatter->formatAmount($order['amount']), 'VerifyEnrollmentRequestId' => $this->crypt->generateRandomString(), - 'Currency' => $this->mapCurrency($order['currency']), + 'Currency' => $this->valueMapper->mapCurrency($order['currency']), 'SuccessUrl' => $order['success_url'], 'FailureUrl' => $order['fail_url'], 'Pan' => $creditCard->getNumber(), - 'ExpiryDate' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), - 'BrandName' => $creditCard->getType() !== null ? $this->cardTypeMapping[$creditCard->getType()] : null, + 'ExpiryDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'ExpiryDate'), + 'BrandName' => $creditCard->getType() !== null ? $this->valueMapper->mapCardType($creditCard->getType()) : null, 'IsRecurring' => 'false', ]; if ($order['installment']) { - $requestData['InstallmentCount'] = $this->mapInstallment($order['installment']); + $requestData['InstallmentCount'] = $this->valueFormatter->formatInstallment($order['installment']); } if ($posAccount->isSubBranch()) { @@ -144,14 +115,14 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount $order = $this->preparePaymentOrder($order); return $this->getRequestAccountData($posAccount) + [ - 'TransactionType' => $this->mapTxType($txType), + 'TransactionType' => $this->valueMapper->mapTxType($txType), 'OrderId' => (string) $order['id'], - 'CurrencyAmount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'CurrencyAmount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'ClientIp' => (string) $order['ip'], 'TransactionDeviceSource' => '0', 'Pan' => $creditCard->getNumber(), - 'Expiry' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_LONG_FORMAT), + 'Expiry' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Expiry'), 'Cvv' => $creditCard->getCvv(), ]; } @@ -176,10 +147,10 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po $order = $this->preparePostPaymentOrder($order); return $this->getRequestAccountData($posAccount) + [ - 'TransactionType' => $this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), + 'TransactionType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), 'ReferenceTransactionId' => (string) $order['transaction_id'], - 'CurrencyAmount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'CurrencyAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => (string) $this->valueMapper->mapCurrency($order['currency']), 'ClientIp' => (string) $order['ip'], ]; } @@ -224,7 +195,7 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o return [ 'MerchantId' => $posAccount->getClientId(), 'Password' => $posAccount->getPassword(), - 'TransactionType' => $this->mapTxType(PosInterface::TX_TYPE_CANCEL), + 'TransactionType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL), 'ReferenceTransactionId' => (string) $order['transaction_id'], 'ClientIp' => (string) $order['ip'], ]; @@ -242,10 +213,10 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o return [ 'MerchantId' => $posAccount->getClientId(), 'Password' => $posAccount->getPassword(), - 'TransactionType' => $this->mapTxType($refundTxType), + 'TransactionType' => $this->valueMapper->mapTxType($refundTxType), 'ReferenceTransactionId' => (string) $order['transaction_id'], 'ClientIp' => (string) $order['ip'], - 'CurrencyAmount' => $this->formatAmount($order['amount']), + 'CurrencyAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), ]; } @@ -298,29 +269,6 @@ public function create3DFormData(?AbstractPosAccount $posAccount, ?array $order, ]; } - /** - * Amount Formatter - * - * @param float $amount - * - * @return string ex: 10.1 => 10.10 - */ - protected function formatAmount(float $amount): string - { - return \number_format($amount, 2, '.', ''); - } - - /** - * 0 => '0' - * 1 => '0' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : '0'; - } - /** * @inheritDoc */ @@ -381,16 +329,6 @@ protected function prepareCancelOrder(array $order): array ]; } - /** - * @inheritDoc - * - * @return string - */ - protected function mapCurrency(string $currency): string - { - return (string) ($this->currencyMappings[$currency] ?? $currency); - } - /** * @param PayFlexAccount $posAccount * @@ -428,14 +366,16 @@ private function createRecurringData(array $recurringData): array return [ 'IsRecurring' => 'true', 'RecurringFrequency' => (string) $recurringData['frequency'], // Periyodik İşlem Frekansı - 'RecurringFrequencyType' => $this->mapRecurringFrequency($recurringData['frequencyType']), // Day|Month|Year + 'RecurringFrequencyType' => $this->valueMapper->mapRecurringFrequency($recurringData['frequencyType']), // Day|Month|Year // recurring işlemin toplamda kaç kere tekrar edeceği bilgisini içerir 'RecurringInstallmentCount' => (string) $recurringData['installment'], /** * Bu alandaki tarih, kartın son kullanma tarihinden büyükse ACS sunucusu işlemi reddeder. */ - 'RecurringEndDate' => $recurringData['endDate']->format('Ymd'), - 'TriggerDate' => isset($recurringData['startDate']) ? $recurringData['startDate']->format('Ymd') : '', + 'RecurringEndDate' => $this->valueFormatter->formatDateTime($recurringData['endDate'], 'RecurringEndDate'), + 'TriggerDate' => isset($recurringData['startDate']) + ? $this->valueFormatter->formatDateTime($recurringData['startDate'], 'TriggerDate') + : '', ]; } } diff --git a/src/DataMapper/RequestDataMapper/PayForPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/PayForPosRequestDataMapper.php index fdc013e5..e252c975 100644 --- a/src/DataMapper/RequestDataMapper/PayForPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/PayForPosRequestDataMapper.php @@ -24,30 +24,13 @@ class PayForPosRequestDataMapper extends AbstractRequestDataMapper */ private const MOTO = '0'; - /** @var string */ - private const CREDIT_CARD_EXP_DATE_FORMAT = 'my'; - - /** {@inheritdoc} */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3DModel', - PosInterface::MODEL_3D_PAY => '3DPay', - PosInterface::MODEL_3D_HOST => '3DHost', - PosInterface::MODEL_NON_SECURE => 'NonSecure', - ]; - /** - * {@inheritDoc} + * @inheritDoc */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Auth', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'PostAuth', - PosInterface::TX_TYPE_CANCEL => 'Void', - PosInterface::TX_TYPE_REFUND => 'Refund', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', - PosInterface::TX_TYPE_HISTORY => 'TxnHistory', - PosInterface::TX_TYPE_STATUS => 'OrderInquiry', - ]; + public static function supports(string $gatewayClass): bool + { + return PayForPos::class === $gatewayClass; + } /** * {@inheritDoc} @@ -83,15 +66,15 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount return $this->getRequestAccountData($posAccount) + [ 'MOTO' => self::MOTO, 'OrderId' => (string) $order['id'], - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], - 'TxnType' => $this->mapTxType($txType), - 'PurchAmount' => (string) $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), - 'InstallmentCount' => $this->mapInstallment($order['installment']), - 'Lang' => $this->getLang($posAccount, $order), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), + 'TxnType' => $this->valueMapper->mapTxType($txType), + 'PurchAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'InstallmentCount' => (string) $this->valueFormatter->formatInstallment($order['installment']), + 'Lang' => $this->getLang($order), 'CardHolderName' => $creditCard->getHolderName(), 'Pan' => $creditCard->getNumber(), - 'Expiry' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'Expiry' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Expiry'), 'Cvv2' => $creditCard->getCvv(), ]; } @@ -109,11 +92,11 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po return $this->getRequestAccountData($posAccount) + [ 'OrgOrderId' => (string) $order['id'], - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), - 'PurchAmount' => (string) $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), - 'Lang' => $this->getLang($posAccount, $order), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH), + 'PurchAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'Lang' => $this->getLang($order), ]; } @@ -131,8 +114,8 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o return $this->getRequestAccountData($posAccount) + [ 'OrgOrderId' => (string) $order['id'], 'SecureType' => 'Inquiry', - 'Lang' => $this->getLang($posAccount, $order), - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_STATUS), + 'Lang' => $this->getLang($order), + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_STATUS), ]; } @@ -149,10 +132,10 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o return $this->getRequestAccountData($posAccount) + [ 'OrgOrderId' => (string) $order['id'], - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_CANCEL), - 'Currency' => $this->mapCurrency($order['currency']), - 'Lang' => $this->getLang($posAccount, $order), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'Lang' => $this->getLang($order), ]; } @@ -168,12 +151,12 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o $order = $this->prepareRefundOrder($order); return $this->getRequestAccountData($posAccount) + [ - 'SecureType' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], - 'Lang' => $this->getLang($posAccount, $order), + 'SecureType' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), + 'Lang' => $this->getLang($order), 'OrgOrderId' => (string) $order['id'], - 'TxnType' => $this->mapTxType($refundTxType), - 'PurchAmount' => (string) $order['amount'], - 'Currency' => $this->mapCurrency($order['currency']), + 'TxnType' => $this->valueMapper->mapTxType($refundTxType), + 'PurchAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), ]; } @@ -189,8 +172,8 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar $requestData = [ 'SecureType' => 'Report', 'OrderId' => $order['id'], - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_HISTORY), - 'Lang' => $this->getLang($posAccount, $order), + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_HISTORY), + 'Lang' => $this->getLang($order), ]; return $this->getRequestAccountData($posAccount) + $requestData; @@ -208,9 +191,9 @@ public function createHistoryRequestData(AbstractPosAccount $posAccount, array $ $requestData = [ 'SecureType' => 'Report', - 'ReqDate' => $data['transaction_date']->format('Ymd'), - 'TxnType' => $this->mapTxType(PosInterface::TX_TYPE_HISTORY), - 'Lang' => $this->getLang($posAccount, $order), + 'ReqDate' => $this->valueFormatter->formatDateTime($data['transaction_date'], 'ReqDate'), + 'TxnType' => $this->valueMapper->mapTxType(PosInterface::TX_TYPE_HISTORY), + 'Lang' => $this->getLang($order), ]; return $this->getRequestAccountData($posAccount) + $requestData; @@ -242,12 +225,12 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s 'MerchantID' => $posAccount->getClientId(), 'UserCode' => $posAccount->getUsername(), 'OrderId' => (string) $order['id'], - 'Lang' => $this->getLang($posAccount, $order), - 'SecureType' => $this->secureTypeMappings[$paymentModel], - 'TxnType' => $this->mapTxType($txType), - 'PurchAmount' => (string) $order['amount'], - 'InstallmentCount' => $this->mapInstallment($order['installment']), - 'Currency' => $this->mapCurrency($order['currency']), + 'Lang' => $this->getLang($order), + 'SecureType' => $this->valueMapper->mapSecureType($paymentModel), + 'TxnType' => $this->valueMapper->mapTxType($txType), + 'PurchAmount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'InstallmentCount' => (string) $this->valueFormatter->formatInstallment($order['installment']), + 'Currency' => (string) $this->valueMapper->mapCurrency($order['currency']), 'OkUrl' => (string) $order['success_url'], 'FailUrl' => (string) $order['fail_url'], 'Rnd' => $this->crypt->generateRandomString(), @@ -256,7 +239,7 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s if ($creditCard instanceof CreditCardInterface) { $inputs['CardHolderName'] = $creditCard->getHolderName() ?? ''; $inputs['Pan'] = $creditCard->getNumber(); - $inputs['Expiry'] = $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT); + $inputs['Expiry'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'Expiry'); $inputs['Cvv2'] = $creditCard->getCvv(); } @@ -279,17 +262,6 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s ]; } - /** - * 0 => '0' - * 1 => '0' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : '0'; - } - /** * @inheritDoc */ @@ -333,16 +305,6 @@ protected function prepareOrderHistoryOrder(array $order): array ]; } - /** - * @inheritDoc - * - * @return string - */ - protected function mapCurrency(string $currency): string - { - return (string) ($this->currencyMappings[$currency] ?? $currency); - } - /** * @param PayForAccount $posAccount * diff --git a/src/DataMapper/RequestDataMapper/PosNetRequestDataMapper.php b/src/DataMapper/RequestDataMapper/PosNetRequestDataMapper.php index 475bf016..d11401ee 100644 --- a/src/DataMapper/RequestDataMapper/PosNetRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/PosNetRequestDataMapper.php @@ -9,11 +9,14 @@ use InvalidArgumentException; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\Crypt\PosNetCrypt; +use Mews\Pos\DataMapper\RequestValueFormatter\PosNetRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueFormatter\RequestValueFormatterInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PosNetAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; +use Mews\Pos\Gateways\PosNet; use Mews\Pos\PosInterface; /** @@ -21,57 +24,21 @@ */ class PosNetRequestDataMapper extends AbstractRequestDataMapper { - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'ym'; - - /** - * PosNet requires order id with specific length - * @var int - */ - private const ORDER_ID_LENGTH = 20; - /** - * order id total length including prefix; - * @var int + * @var PosNetRequestValueFormatter */ - private const ORDER_ID_TOTAL_LENGTH = 24; + protected RequestValueFormatterInterface $valueFormatter; - /** @var string */ - private const ORDER_ID_3D_PREFIX = 'TDSC'; - - /** @var string */ - private const ORDER_ID_3D_PAY_PREFIX = ''; //? - - /** @var string */ - private const ORDER_ID_REGULAR_PREFIX = ''; //? - - /** - * {@inheritDoc} - */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Sale', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capt', - PosInterface::TX_TYPE_CANCEL => 'reverse', - PosInterface::TX_TYPE_REFUND => 'return', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'return', - PosInterface::TX_TYPE_STATUS => 'agreement', - ]; + /** @var PosNetCrypt */ + protected CryptInterface $crypt; /** - * {@inheritDoc} + * @inheritDoc */ - protected array $currencyMappings = [ - PosInterface::CURRENCY_TRY => 'TL', - PosInterface::CURRENCY_USD => 'US', - PosInterface::CURRENCY_EUR => 'EU', - PosInterface::CURRENCY_GBP => 'GB', - PosInterface::CURRENCY_JPY => 'JP', - PosInterface::CURRENCY_RUB => 'RU', - ]; - - /** @var PosNetCrypt */ - protected CryptInterface $crypt; + public static function supports(string $gatewayClass): bool + { + return PosNet::class === $gatewayClass; + } /** * @param PosNetAccount $posAccount @@ -84,9 +51,9 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array $order = $this->preparePaymentOrder($order); $mappedOrder = []; - $mappedOrder['id'] = self::formatOrderId($order['id']); - $mappedOrder['amount'] = $this->formatAmount($order['amount']); - $mappedOrder['currency'] = (string) $this->mapCurrency($order['currency']); + $mappedOrder['id'] = $this->valueFormatter->formatOrderId($order['id']); + $mappedOrder['amount'] = $this->valueFormatter->formatAmount($order['amount']); + $mappedOrder['currency'] = (string) $this->valueMapper->mapCurrency($order['currency']); $requestData = [ 'mid' => $posAccount->getClientId(), @@ -113,17 +80,19 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount { $order = $this->preparePaymentOrder($order); + $txType = $this->valueMapper->mapTxType($txType); + return [ - 'mid' => $posAccount->getClientId(), - 'tid' => $posAccount->getTerminalId(), - 'tranDateRequired' => '1', - strtolower($this->mapTxType($txType)) => [ - 'orderID' => self::formatOrderId($order['id']), - 'installment' => $this->mapInstallment($order['installment']), - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency($order['currency']), + 'mid' => $posAccount->getClientId(), + 'tid' => $posAccount->getTerminalId(), + 'tranDateRequired' => '1', + strtolower($txType) => [ + 'orderID' => $this->valueFormatter->formatOrderId($order['id']), + 'installment' => $this->valueFormatter->formatInstallment($order['installment']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'ccno' => $creditCard->getNumber(), - 'expDate' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'expDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'expDate'), 'cvc' => $creditCard->getCvv(), ], ]; @@ -138,15 +107,17 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po { $order = $this->preparePostPaymentOrder($order); + $txType = $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH); + return [ - 'mid' => $posAccount->getClientId(), - 'tid' => $posAccount->getTerminalId(), - 'tranDateRequired' => '1', - \strtolower($this->mapTxType(PosInterface::TX_TYPE_PAY_POST_AUTH)) => [ + 'mid' => $posAccount->getClientId(), + 'tid' => $posAccount->getTerminalId(), + 'tranDateRequired' => '1', + \strtolower($txType) => [ 'hostLogKey' => $order['ref_ret_num'], - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency($order['currency']), - 'installment' => $this->mapInstallment($order['installment']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'installment' => $this->valueFormatter->formatInstallment($order['installment']), ], ]; } @@ -160,13 +131,13 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o { $order = $this->prepareStatusOrder($order); - $txType = $this->mapTxType(PosInterface::TX_TYPE_STATUS); + $txType = $this->valueMapper->mapTxType(PosInterface::TX_TYPE_STATUS); return [ 'mid' => $posAccount->getClientId(), 'tid' => $posAccount->getTerminalId(), $txType => [ - 'orderID' => self::mapOrderIdToPrefixedOrderId($order['id'], $order['payment_model']), + 'orderID' => $this->valueFormatter->formatOrderId($order['id'], PosInterface::TX_TYPE_STATUS, $order['payment_model']), ], ]; } @@ -180,7 +151,7 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o { $order = $this->prepareCancelOrder($order); - $txType = $this->mapTxType(PosInterface::TX_TYPE_CANCEL); + $txType = $this->valueMapper->mapTxType(PosInterface::TX_TYPE_CANCEL); $requestData = [ 'mid' => $posAccount->getClientId(), 'tid' => $posAccount->getTerminalId(), @@ -198,7 +169,7 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o if (isset($order['ref_ret_num'])) { $requestData[$txType]['hostLogKey'] = $order['ref_ret_num']; } else { - $requestData[$txType]['orderID'] = self::mapOrderIdToPrefixedOrderId($order['id'], $order['payment_model']); + $requestData[$txType]['orderID'] = $this->valueFormatter->formatOrderId($order['id'], PosInterface::TX_TYPE_CANCEL, $order['payment_model']); } return $requestData; @@ -213,21 +184,21 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o { $order = $this->prepareRefundOrder($order); - $txType = $this->mapTxType($refundTxType); + $txType = $this->valueMapper->mapTxType($refundTxType); $requestData = [ 'mid' => $posAccount->getClientId(), 'tid' => $posAccount->getTerminalId(), 'tranDateRequired' => '1', $txType => [ - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency($order['currency']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), ], ]; if (isset($order['ref_ret_num'])) { $requestData[$txType]['hostLogKey'] = $order['ref_ret_num']; } else { - $requestData[$txType]['orderID'] = self::mapOrderIdToPrefixedOrderId($order['id'], $order['payment_model']); + $requestData[$txType]['orderID'] = $this->valueFormatter->formatOrderId($order['id'], $refundTxType, $order['payment_model']); } return $requestData; @@ -251,7 +222,7 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar /** - * @param PosNetAccount $posAccount + * @param PosNetAccount $posAccount * @param array{data1: string, data2: string, sign: string} $extraData * * @return array{gateway: string, method: 'POST', inputs: array} @@ -281,7 +252,7 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s * set edilir. Form içerisinde bulundurulması yeterlidir. */ 'url' => '', - 'lang' => $this->getLang($posAccount, $order), + 'lang' => $this->getLang($order), ]; return [ @@ -297,6 +268,9 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s * @param PosNetAccount $posAccount * @param array $order * @param string $txType + * @param CreditCardInterface $creditCard + * + * @return array|string> * * @throws UnsupportedTransactionTypeException */ @@ -304,6 +278,7 @@ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccoun { $order = $this->preparePaymentOrder($order); + // todo check if we can remove this code if (null === $creditCard->getHolderName() && isset($order['name'])) { $creditCard->setHolderName($order['name']); } @@ -314,14 +289,14 @@ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccoun 'oosRequestData' => [ 'posnetid' => $posAccount->getPosNetId(), 'ccno' => $creditCard->getNumber(), - 'expDate' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'expDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'expDate'), 'cvc' => $creditCard->getCvv(), - 'amount' => $this->formatAmount($order['amount']), - 'currencyCode' => $this->mapCurrency($order['currency']), - 'installment' => $this->mapInstallment($order['installment']), - 'XID' => self::formatOrderId($order['id']), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'installment' => $this->valueFormatter->formatInstallment($order['installment']), + 'XID' => $this->valueFormatter->formatOrderId($order['id']), 'cardHolderName' => $creditCard->getHolderName(), - 'tranType' => $this->mapTxType($txType), + 'tranType' => $this->valueMapper->mapTxType($txType), ], ]; } @@ -338,9 +313,9 @@ public function create3DResolveMerchantRequestData(AbstractPosAccount $posAccoun $order = $this->preparePaymentOrder($order); $mappedOrder = []; - $mappedOrder['id'] = self::formatOrderId($order['id']); - $mappedOrder['amount'] = $this->formatAmount($order['amount']); - $mappedOrder['currency'] = (string) $this->mapCurrency($order['currency']); + $mappedOrder['id'] = $this->valueFormatter->formatOrderId($order['id']); + $mappedOrder['amount'] = $this->valueFormatter->formatAmount($order['amount']); + $mappedOrder['currency'] = (string) $this->valueMapper->mapCurrency($order['currency']); $requestData = [ 'mid' => $posAccount->getClientId(), @@ -365,91 +340,11 @@ public function create3DResolveMerchantRequestData(AbstractPosAccount $posAccoun public function createCustomQueryRequestData(AbstractPosAccount $posAccount, array $requestData): array { return $requestData + [ - 'mid' => $posAccount->getClientId(), - 'tid' => $posAccount->getTerminalId(), - ]; + 'mid' => $posAccount->getClientId(), + 'tid' => $posAccount->getTerminalId(), + ]; } - /** - * Get PrefixedOrderId - * To check the status of an order or cancel/refund order Yapikredi - * - requires the order length to be 24 - * - and order id prefix which is "TDSC" for 3D payments - * - * @param string $orderId - * @param string $accountModel - * - * @return string - */ - public static function mapOrderIdToPrefixedOrderId(string $orderId, string $accountModel): string - { - $prefix = self::ORDER_ID_REGULAR_PREFIX; - if (PosInterface::MODEL_3D_SECURE === $accountModel) { - $prefix = self::ORDER_ID_3D_PREFIX; - } elseif (PosInterface::MODEL_3D_PAY === $accountModel) { - $prefix = self::ORDER_ID_3D_PAY_PREFIX; - } - - return $prefix.self::formatOrderId($orderId, self::ORDER_ID_TOTAL_LENGTH - strlen($prefix)); - } - - - /** - * formats order id by adding 0 pad to the left - * - * @param string $orderId - * @param int|null $padLength - * - * @return string - */ - public static function formatOrderId(string $orderId, ?int $padLength = null): string - { - if (null === $padLength) { - $padLength = self::ORDER_ID_LENGTH; - } - - if (\strlen($orderId) > $padLength) { - throw new InvalidArgumentException(\sprintf( - // Banka tarafindan belirlenen kisitlama - "Saglanan siparis ID'nin (%s) uzunlugu %d karakter. Siparis ID %d karakterden uzun olamaz!", - $orderId, - \strlen($orderId), - $padLength - )); - } - - return \str_pad($orderId, $padLength, '0', STR_PAD_LEFT); - } - - /** - * Get amount - * formats 10.01 to 1001 - * - * @param float $amount - * - * @return int - */ - protected function formatAmount(float $amount): int - { - return (int) (\round($amount, 2) * 100); - } - - /** - * 0 => '00' - * 1 => '00' - * 2 => '02' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - if ($installment > 1) { - return \str_pad((string) $installment, 2, '0', STR_PAD_LEFT); - } - - return '00'; - } - - /** * @inheritDoc */ diff --git a/src/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapper.php index d0d31a25..00c8c952 100644 --- a/src/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapper.php @@ -6,7 +6,8 @@ namespace Mews\Pos\DataMapper\RequestDataMapper; -use InvalidArgumentException; +use Mews\Pos\DataMapper\RequestValueFormatter\PosNetV1PosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueFormatter\RequestValueFormatterInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PosNetAccount; use Mews\Pos\Entity\Card\CreditCardInterface; @@ -23,54 +24,18 @@ class PosNetV1PosRequestDataMapper extends AbstractRequestDataMapper /** @var string */ public const API_VERSION = 'V100'; - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'ym'; - - /** - * PosNet requires order id with specific length - * @var int - */ - private const ORDER_ID_LENGTH = 20; - - /** - * order id total length including prefix; - * @var int - */ - private const ORDER_ID_TOTAL_LENGTH = 24; - - /** @var string */ - private const ORDER_ID_3D_PREFIX = 'TDS_'; - - /** @var string */ - private const ORDER_ID_3D_PAY_PREFIX = ''; //? - - /** @var string */ - private const ORDER_ID_REGULAR_PREFIX = ''; //? - /** - * {@inheritDoc} + * @var PosNetV1PosRequestValueFormatter */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => 'Sale', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', - PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capture', - PosInterface::TX_TYPE_CANCEL => 'Reverse', - PosInterface::TX_TYPE_REFUND => 'Return', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'Return', - PosInterface::TX_TYPE_STATUS => 'TransactionInquiry', - ]; + protected RequestValueFormatterInterface $valueFormatter; /** - * {@inheritDoc} + * @inheritDoc */ - protected array $currencyMappings = [ - PosInterface::CURRENCY_TRY => 'TL', - PosInterface::CURRENCY_USD => 'US', - PosInterface::CURRENCY_EUR => 'EU', - PosInterface::CURRENCY_GBP => 'GB', - PosInterface::CURRENCY_JPY => 'JP', - PosInterface::CURRENCY_RUB => 'RU', - ]; + public static function supports(string $gatewayClass): bool + { + return PosNetV1Pos::class === $gatewayClass; + } /** * @param PosNetAccount $posAccount @@ -98,11 +63,11 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array 'MD' => $responseData['MD'], ], 'MACParams' => 'MerchantNo:TerminalNo:SecureTransactionId:CavvData:Eci:MdStatus', - 'Amount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'PointAmount' => 0, - 'OrderId' => self::formatOrderId($order['id']), - 'InstallmentCount' => $this->mapInstallment($order['installment']), + 'OrderId' => $this->valueFormatter->formatOrderId($order['id']), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), 'InstallmentType' => 'N', ]; @@ -137,7 +102,7 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount 'AdditionalInfoData' => null, 'CardInformationData' => [ 'CardNo' => $creditCard->getNumber(), - 'ExpireDate' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'ExpireDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'ExpireDate'), 'Cvc2' => $creditCard->getCvv(), 'CardHolderName' => $creditCard->getHolderName(), ], @@ -146,10 +111,10 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount 'IsTDSecureMerchant' => null, 'PaymentInstrumentType' => 'CARD', 'ThreeDSecureData' => null, - 'Amount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), - 'OrderId' => self::formatOrderId($order['id']), - 'InstallmentCount' => $this->mapInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'OrderId' => $this->valueFormatter->formatOrderId($order['id']), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), 'InstallmentType' => 'N', 'KOICode' => null, 'MerchantMessageData' => null, @@ -188,10 +153,10 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po 'DealerData' => null, 'IsEncrypted' => null, 'PaymentFacilitatorData' => null, - 'Amount' => $this->formatAmount($order['amount']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'ReferenceCode' => $order['ref_ret_num'], - 'InstallmentCount' => $this->mapInstallment($order['installment']), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), 'InstallmentType' => 'N', ]; @@ -227,7 +192,7 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o 'DealerData' => null, 'IsEncrypted' => 'N', 'PaymentFacilitatorData' => null, - 'OrderId' => self::mapOrderIdToPrefixedOrderId($order['id'], $order['payment_model']), + 'OrderId' => $this->valueFormatter->formatOrderId($order['id'], PosInterface::TX_TYPE_STATUS, $order['payment_model']), ]; if (null === $posAccount->getStoreKey()) { throw new \LogicException('Account storeKey eksik!'); @@ -259,13 +224,13 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o 'PaymentFacilitatorData' => null, 'ReferenceCode' => null, 'OrderId' => null, - 'TransactionType' => $this->mapTxType($order['transaction_type']), + 'TransactionType' => $this->valueMapper->mapTxType($order['transaction_type']), ]; if (isset($order['ref_ret_num'])) { $requestData['ReferenceCode'] = $order['ref_ret_num']; } else { - $requestData['OrderId'] = self::mapOrderIdToPrefixedOrderId($order['id'], $order['payment_model']); + $requestData['OrderId'] = $this->valueFormatter->formatOrderId($order['id'], PosInterface::TX_TYPE_CANCEL, $order['payment_model']); } if (null === $posAccount->getStoreKey()) { @@ -298,18 +263,18 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o 'PaymentFacilitatorData' => null, 'ReferenceCode' => null, 'OrderId' => null, - 'TransactionType' => $this->mapTxType($order['transaction_type']), + 'TransactionType' => $this->valueMapper->mapTxType($order['transaction_type']), ]; if (isset($order['ref_ret_num'])) { $requestData['ReferenceCode'] = $order['ref_ret_num']; } else { - $requestData['OrderId'] = self::mapOrderIdToPrefixedOrderId($order['id'], $order['payment_model']); + $requestData['OrderId'] = $this->valueFormatter->formatOrderId($order['id'], $refundTxType, $order['payment_model']); } if ($order['payment_model'] === PosInterface::MODEL_NON_SECURE) { - $requestData['Amount'] = $this->formatAmount($order['amount']); - $requestData['CurrencyCode'] = $this->mapCurrency($order['currency']); + $requestData['Amount'] = $this->valueFormatter->formatAmount($order['amount']); + $requestData['CurrencyCode'] = $this->valueMapper->mapCurrency($order['currency']); } if (null === $posAccount->getStoreKey()) { @@ -378,13 +343,13 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s 'MerchantNo' => $posAccount->getClientId(), 'TerminalNo' => $posAccount->getTerminalId(), 'PosnetID' => $posAccount->getPosNetId(), - 'TransactionType' => $this->mapTxType($txType), - 'OrderId' => self::formatOrderId($order['id']), - 'Amount' => (string) $this->formatAmount($order['amount']), - 'CurrencyCode' => (string) $this->mapCurrency($order['currency']), + 'TransactionType' => $this->valueMapper->mapTxType($txType), + 'OrderId' => $this->valueFormatter->formatOrderId($order['id']), + 'Amount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'CurrencyCode' => (string) $this->valueMapper->mapCurrency($order['currency']), 'MerchantReturnURL' => (string) $order['success_url'], - 'InstallmentCount' => $this->mapInstallment($order['installment']), - 'Language' => $this->getLang($posAccount, $order), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), + 'Language' => $this->getLang($order), 'TxnState' => 'INITIAL', 'OpenNewWindow' => '0', ]; @@ -394,7 +359,7 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s 'CardNo' => $creditCard->getNumber(), // Kod calisiyor ancak burda bir tutarsizlik var: ExpireDate vs ExpiredDate // MacParams icinde ExpireDate olarak geciyor, gonderidigimizde ise ExpiredDate olarak istiyor. - 'ExpiredDate' => $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT), + 'ExpiredDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'ExpiredDate'), 'Cvv' => $creditCard->getCvv(), 'CardHolderName' => (string) $creditCard->getHolderName(), @@ -433,86 +398,6 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s ]; } - /** - * Get PrefixedOrderId - * To check the status of an order or cancel/refund order PosNet - * - requires the order length to be 24 - * - and order id prefix which is "TDS_" for 3D payments - * - * @param string $orderId - * @param string $accountModel - * - * @return string - */ - public static function mapOrderIdToPrefixedOrderId(string $orderId, string $accountModel): string - { - $prefix = self::ORDER_ID_REGULAR_PREFIX; - if (PosInterface::MODEL_3D_SECURE === $accountModel) { - $prefix = self::ORDER_ID_3D_PREFIX; - } elseif (PosInterface::MODEL_3D_PAY === $accountModel) { - $prefix = self::ORDER_ID_3D_PAY_PREFIX; - } - - return $prefix.self::formatOrderId($orderId, self::ORDER_ID_TOTAL_LENGTH - strlen($prefix)); - } - - - /** - * formats order id by adding 0 pad to the left - * - * @param string $orderId - * @param int|null $padLength - * - * @return string - */ - public static function formatOrderId(string $orderId, ?int $padLength = null): string - { - if (null === $padLength) { - $padLength = self::ORDER_ID_LENGTH; - } - - if (\strlen($orderId) > $padLength) { - throw new InvalidArgumentException(\sprintf( - // Banka tarafindan belirlenen kisitlama - "Saglanan siparis ID'nin (%s) uzunlugu %d karakter. Siparis ID %d karakterden uzun olamaz!", - $orderId, - \strlen($orderId), - $padLength - )); - } - - return \str_pad($orderId, $padLength, '0', STR_PAD_LEFT); - } - - /** - * Get amount - * formats 10.01 to 1001 - * - * @param float $amount - * - * @return int - */ - protected function formatAmount(float $amount): int - { - return (int) (\round($amount, 2) * 100); - } - - /** - * 0 => '0' - * 1 => '0' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - if ($installment > 1) { - return (string) $installment; - } - - return '0'; - } - - /** * @inheritDoc */ diff --git a/src/DataMapper/RequestDataMapper/RequestDataMapperInterface.php b/src/DataMapper/RequestDataMapper/RequestDataMapperInterface.php index 7acfb48f..93aedfa4 100644 --- a/src/DataMapper/RequestDataMapper/RequestDataMapperInterface.php +++ b/src/DataMapper/RequestDataMapper/RequestDataMapperInterface.php @@ -15,35 +15,11 @@ interface RequestDataMapperInterface { /** - * @return array - */ - public function getTxTypeMappings(): array; - - /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * - * @param string $txType + * @param class-string $gatewayClass * - * @return string - * - * @throws UnsupportedTransactionTypeException - */ - public function mapTxType(string $txType): string; - - /** - * @return non-empty-array - */ - public function getCurrencyMappings(): array; - - /** - * @return non-empty-array - */ - public function getSecureTypeMappings(): array; - - /** - * @return array + * @return bool */ - public function getCardTypeMapping(): array; + public static function supports(string $gatewayClass): bool; /** * @return bool diff --git a/src/DataMapper/RequestDataMapper/ToslaPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/ToslaPosRequestDataMapper.php index 668506cf..42199bfb 100644 --- a/src/DataMapper/RequestDataMapper/ToslaPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/ToslaPosRequestDataMapper.php @@ -10,6 +10,7 @@ use Mews\Pos\Entity\Account\ToslaPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\ToslaPos; use Mews\Pos\PosInterface; /** @@ -17,40 +18,33 @@ */ class ToslaPosRequestDataMapper extends AbstractRequestDataMapper { - /** @var string */ - public const CREDIT_CARD_EXP_DATE_FORMAT = 'm/y'; - /** - * {@inheritDoc} + * @inheritDoc */ - protected array $txTypeMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => '1', - PosInterface::TX_TYPE_PAY_PRE_AUTH => '2', - PosInterface::TX_TYPE_PAY_POST_AUTH => '3', - PosInterface::TX_TYPE_CANCEL => '4', - PosInterface::TX_TYPE_REFUND => '5', - PosInterface::TX_TYPE_REFUND_PARTIAL => '5', - ]; + public static function supports(string $gatewayClass): bool + { + return ToslaPos::class === $gatewayClass; + } /** * @param ToslaPosAccount $posAccount * @param array $order * - * @return array + * @return array */ public function create3DEnrollmentCheckRequestData(AbstractPosAccount $posAccount, array $order): array { $order = $this->preparePaymentOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'callbackUrl' => (string) $order['success_url'], - 'orderId' => (string) $order['id'], - 'amount' => $this->formatAmount($order['amount']), - 'currency' => (int) $this->mapCurrency($order['currency']), - 'installmentCount' => (int) $this->mapInstallment($order['installment']), - 'rnd' => $this->crypt->generateRandomString(), - 'timeSpan' => $order['time_span'], - ]; + 'callbackUrl' => (string) $order['success_url'], + 'orderId' => (string) $order['id'], + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currency' => (int) $this->valueMapper->mapCurrency($order['currency']), + 'installmentCount' => (int) $this->valueFormatter->formatInstallment($order['installment']), + 'rnd' => $this->crypt->generateRandomString(), + 'timeSpan' => $this->valueFormatter->formatDateTime($order['time_span'], 'timeSpan'), + ]; $requestData['hash'] = $this->crypt->createHash($posAccount, $requestData); @@ -73,17 +67,17 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount $order = $this->preparePaymentOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'orderId' => (string) $order['id'], - 'amount' => $this->formatAmount($order['amount']), - 'currency' => (int) $this->mapCurrency($order['currency']), - 'installmentCount' => (int) $this->mapInstallment($order['installment']), - 'rnd' => $this->crypt->generateRandomString(), - 'timeSpan' => $order['time_span'], - 'cardHolderName' => $creditCard->getHolderName(), - 'cardNo' => $creditCard->getNumber(), - 'expireDate' => $creditCard->getExpirationDate('my'), - 'cvv' => $creditCard->getCvv(), - ]; + 'orderId' => (string) $order['id'], + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'currency' => (int) $this->valueMapper->mapCurrency($order['currency']), + 'installmentCount' => (int) $this->valueFormatter->formatInstallment($order['installment']), + 'rnd' => $this->crypt->generateRandomString(), + 'timeSpan' => $this->valueFormatter->formatDateTime($order['time_span'], 'timeSpan'), + 'cardHolderName' => $creditCard->getHolderName(), + 'cardNo' => $creditCard->getNumber(), + 'expireDate' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'expireDate'), + 'cvv' => $creditCard->getCvv(), + ]; $requestData['hash'] = $this->crypt->createHash($posAccount, $requestData); @@ -98,11 +92,11 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po $order = $this->preparePostPaymentOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'orderId' => (string) $order['id'], - 'amount' => $this->formatAmount($order['amount']), - 'rnd' => $this->crypt->generateRandomString(), - 'timeSpan' => $order['time_span'], - ]; + 'orderId' => (string) $order['id'], + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'rnd' => $this->crypt->generateRandomString(), + 'timeSpan' => $this->valueFormatter->formatDateTime($order['time_span'], 'timeSpan'), + ]; $requestData['hash'] = $this->crypt->createHash($posAccount, $requestData); @@ -117,10 +111,10 @@ public function createStatusRequestData(AbstractPosAccount $posAccount, array $o $order = $this->prepareStatusOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'orderId' => (string) $order['id'], - 'rnd' => $this->crypt->generateRandomString(), - 'timeSpan' => $order['time_span'], - ]; + 'orderId' => (string) $order['id'], + 'rnd' => $this->crypt->generateRandomString(), + 'timeSpan' => $this->valueFormatter->formatDateTime($order['time_span'], 'timeSpan'), + ]; $requestData['hash'] = $this->crypt->createHash($posAccount, $requestData); @@ -135,10 +129,10 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o $order = $this->prepareCancelOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'orderId' => (string) $order['id'], - 'rnd' => $this->crypt->generateRandomString(), - 'timeSpan' => $order['time_span'], - ]; + 'orderId' => (string) $order['id'], + 'rnd' => $this->crypt->generateRandomString(), + 'timeSpan' => $this->valueFormatter->formatDateTime($order['time_span'], 'timeSpan'), + ]; $requestData['hash'] = $this->crypt->createHash($posAccount, $requestData); @@ -153,11 +147,11 @@ public function createRefundRequestData(AbstractPosAccount $posAccount, array $o $order = $this->prepareRefundOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'orderId' => (string) $order['id'], - 'rnd' => $this->crypt->generateRandomString(), - 'amount' => $this->formatAmount($order['amount']), - 'timeSpan' => $order['time_span'], - ]; + 'orderId' => (string) $order['id'], + 'rnd' => $this->crypt->generateRandomString(), + 'amount' => $this->valueFormatter->formatAmount($order['amount']), + 'timeSpan' => $this->valueFormatter->formatDateTime($order['time_span'], 'timeSpan'), + ]; $requestData['hash'] = $this->crypt->createHash($posAccount, $requestData); @@ -171,13 +165,13 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar { $order = $this->prepareOrderHistoryOrder($order); $requestData = $this->getRequestAccountData($posAccount) + [ - 'orderId' => (string) $order['id'], - 'transactionDate' => $order['transaction_date']->format('Ymd'), - 'page' => $order['page'], - 'pageSize' => $order['page_size'], - 'rnd' => $this->crypt->generateRandomString(), - 'timeSpan' => $order['time_span'], - ]; + 'orderId' => (string) $order['id'], + 'transactionDate' => $this->valueFormatter->formatDateTime($order['transaction_date'], 'transactionDate'), + 'page' => $order['page'], + 'pageSize' => $order['page_size'], + 'rnd' => $this->crypt->generateRandomString(), + 'timeSpan' => $this->valueFormatter->formatDateTime($order['time_span'], 'timeSpan'), + ]; $requestData['hash'] = $this->crypt->createHash($posAccount, $requestData); @@ -191,7 +185,7 @@ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, arr { $requestData += $this->getRequestAccountData($posAccount) + [ 'rnd' => $this->crypt->generateRandomString(), - 'timeSpan' => $this->newTimeSpan(), + 'timeSpan' => $this->valueFormatter->formatDateTime($this->newTimeSpan(), 'timeSpan'), ]; if (!isset($requestData['hash'])) { @@ -231,7 +225,7 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s if ($creditCard instanceof CreditCardInterface) { $inputs['CardHolderName'] = (string) $creditCard->getHolderName(); $inputs['CardNo'] = $creditCard->getNumber(); - $inputs['ExpireDate'] = $creditCard->getExpirationDate(self::CREDIT_CARD_EXP_DATE_FORMAT); + $inputs['ExpireDate'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'ExpireDate'); $inputs['Cvv'] = $creditCard->getCvv(); } @@ -242,30 +236,6 @@ public function create3DFormData(AbstractPosAccount $posAccount, array $order, s ]; } - /** - * 0 => '0' - * 1 => '0' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : '0'; - } - - /** - * Get amount - * formats 10.01 to 1001 - * - * @param float $amount - * - * @return int - */ - protected function formatAmount(float $amount): int - { - return (int) (\round($amount, 2) * 100); - } - /** * @inheritDoc */ @@ -352,13 +322,10 @@ private function getRequestAccountData(AbstractPosAccount $posAccount): array } /** - * @return string ex: 20231209201121 + * @return \DateTimeImmutable */ - private function newTimeSpan(): string + private function newTimeSpan(): \DateTimeImmutable { - $turkeyTimeZone = new \DateTimeZone('Europe/Istanbul'); - $turkeyTime = new \DateTime('now', $turkeyTimeZone); - - return $turkeyTime->format('YmdHis'); + return new \DateTimeImmutable('now', new \DateTimeZone('Europe/Istanbul')); } } diff --git a/src/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapper.php b/src/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapper.php index 7199d9d5..92e23498 100644 --- a/src/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapper.php +++ b/src/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapper.php @@ -11,6 +11,7 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\KuveytPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; +use Mews\Pos\Gateways\VakifKatilimPos; use Mews\Pos\PosInterface; /** @@ -21,36 +22,16 @@ class VakifKatilimPosRequestDataMapper extends AbstractRequestDataMapper /** @var string */ public const API_VERSION = '1.0.0'; - /** @var string */ - public const CREDIT_CARD_EXP_YEAR_FORMAT = 'y'; - - /** @var string */ - public const CREDIT_CARD_EXP_MONTH_FORMAT = 'm'; - - /** - * {@inheritdoc} - */ - protected array $secureTypeMappings = [ - PosInterface::MODEL_3D_SECURE => '3', - PosInterface::MODEL_NON_SECURE => '5', - ]; + /** @var KuveytPosCrypt */ + protected CryptInterface $crypt; /** - * Currency mapping - * - * {@inheritdoc} + * @inheritDoc */ - protected array $currencyMappings = [ - PosInterface::CURRENCY_TRY => '0949', - PosInterface::CURRENCY_USD => '0840', - PosInterface::CURRENCY_EUR => '0978', - PosInterface::CURRENCY_GBP => '0826', - PosInterface::CURRENCY_JPY => '0392', - PosInterface::CURRENCY_RUB => '0810', - ]; - - /** @var KuveytPosCrypt */ - protected CryptInterface $crypt; + public static function supports(string $gatewayClass): bool + { + return VakifKatilimPos::class === $gatewayClass; + } /** * @param KuveytPosAccount $posAccount @@ -75,10 +56,10 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array ], ], ], - 'InstallmentCount' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), 'MerchantOrderId' => $responseData['MerchantOrderId'], - 'TransactionSecurity' => $this->secureTypeMappings[PosInterface::MODEL_3D_SECURE], + 'TransactionSecurity' => $this->valueMapper->mapSecureType(PosInterface::MODEL_3D_SECURE), ]; $result['HashData'] = $this->crypt->createHash($posAccount, $result); @@ -96,7 +77,7 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array * @param string $txType * @param CreditCardInterface|null $creditCard * - * @return array + * @return array */ public function create3DEnrollmentCheckRequestData(KuveytPosAccount $kuveytPosAccount, array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null): array { @@ -105,11 +86,11 @@ public function create3DEnrollmentCheckRequestData(KuveytPosAccount $kuveytPosAc $requestData = $this->getRequestAccountData($kuveytPosAccount) + [ 'APIVersion' => self::API_VERSION, 'HashPassword' => $this->crypt->hashString($kuveytPosAccount->getStoreKey() ?? ''), - 'TransactionSecurity' => $this->secureTypeMappings[$paymentModel], - 'InstallmentCount' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), - 'DisplayAmount' => $this->formatAmount($order['amount']), - 'FECCurrencyCode' => $this->mapCurrency($order['currency']), + 'TransactionSecurity' => $this->valueMapper->mapSecureType($paymentModel), + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => (int) $this->valueFormatter->formatAmount($order['amount']), + 'DisplayAmount' => (int) $this->valueFormatter->formatAmount($order['amount']), + 'FECCurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), 'MerchantOrderId' => (string) $order['id'], 'OkUrl' => (string) $order['success_url'], 'FailUrl' => (string) $order['fail_url'], @@ -118,8 +99,8 @@ public function create3DEnrollmentCheckRequestData(KuveytPosAccount $kuveytPosAc if ($creditCard instanceof CreditCardInterface) { $requestData['CardHolderName'] = (string) $creditCard->getHolderName(); $requestData['CardNumber'] = $creditCard->getNumber(); - $requestData['CardExpireDateYear'] = $creditCard->getExpireYear(self::CREDIT_CARD_EXP_YEAR_FORMAT); - $requestData['CardExpireDateMonth'] = $creditCard->getExpireMonth(self::CREDIT_CARD_EXP_MONTH_FORMAT); + $requestData['CardExpireDateYear'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateYear'); + $requestData['CardExpireDateMonth'] = $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateMonth'); $requestData['CardCVV2'] = $creditCard->getCvv(); } @@ -162,14 +143,14 @@ public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount 'APIVersion' => self::API_VERSION, 'HashPassword' => $this->crypt->hashString($posAccount->getStoreKey() ?? ''), 'MerchantOrderId' => $order['id'], - 'InstallmentCount' => $this->mapInstallment($order['installment']), - 'Amount' => $this->formatAmount($order['amount']), - 'FECCurrencyCode' => $this->mapCurrency($order['currency']), - 'CurrencyCode' => $this->mapCurrency($order['currency']), - 'TransactionSecurity' => $this->secureTypeMappings[PosInterface::MODEL_NON_SECURE], + 'InstallmentCount' => $this->valueFormatter->formatInstallment($order['installment']), + 'Amount' => $this->valueFormatter->formatAmount($order['amount']), + 'FECCurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'CurrencyCode' => $this->valueMapper->mapCurrency($order['currency']), + 'TransactionSecurity' => $this->valueMapper->mapSecureType(PosInterface::MODEL_NON_SECURE), 'CardNumber' => $creditCard->getNumber(), - 'CardExpireDateYear' => $creditCard->getExpireYear(self::CREDIT_CARD_EXP_YEAR_FORMAT), - 'CardExpireDateMonth' => $creditCard->getExpireMonth(self::CREDIT_CARD_EXP_MONTH_FORMAT), + 'CardExpireDateYear' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateYear'), + 'CardExpireDateMonth' => $this->valueFormatter->formatCardExpDate($creditCard->getExpirationDate(), 'CardExpireDateMonth'), 'CardCVV2' => $creditCard->getCvv(), 'CardHolderName' => $creditCard->getHolderName(), ]; @@ -212,7 +193,7 @@ public function createCancelRequestData(AbstractPosAccount $posAccount, array $o ]; if (!isset($order['transaction_type']) || PosInterface::TX_TYPE_PAY_PRE_AUTH !== $order['transaction_type']) { - $result['Amount'] = $this->formatAmount($order['amount']); + $result['Amount'] = $this->valueFormatter->formatAmount($order['amount']); } $result['HashData'] = $this->crypt->createHash($posAccount, $result); @@ -261,30 +242,29 @@ public function createCustomQueryRequestData(AbstractPosAccount $posAccount, arr /** * {@inheritDoc} * - * @param array $order Vakif Katilim bank'tan donen HTML cevaptan parse edilen form inputlar yada - * 3D Host odemede siparis bilgileri - * * @return array{gateway: string, method: 'POST', inputs: array} */ public function create3DFormData(AbstractPosAccount $posAccount, array $order, string $paymentModel, string $txType, string $gatewayURL, ?CreditCardInterface $creditCard = null): array { - $inputs = $order; - if (PosInterface::MODEL_3D_HOST === $paymentModel) { - $order = $this->preparePaymentOrder($order); - - $inputs = [ - 'UserName' => $posAccount->getUsername(), - 'HashPassword' => $this->crypt->hashString($posAccount->getStoreKey() ?? ''), - 'MerchantId' => $posAccount->getClientId(), - 'MerchantOrderId' => (string) $order['id'], - 'Amount' => $this->formatAmount($order['amount']), - 'FECCurrencyCode' => $this->mapCurrency($order['currency']), - 'OkUrl' => $order['success_url'], - 'FailUrl' => $order['fail_url'], - 'PaymentType' => '1', - ]; + if (PosInterface::MODEL_3D_HOST !== $paymentModel) { + throw new \LogicException('3D Form oluşturma sadece 3D Host modeli için desteklenmektedir! + Diğer modeller için banka API hazır HTML string döndürmektedir.'); } + $order = $this->preparePaymentOrder($order); + + $inputs = [ + 'UserName' => $posAccount->getUsername(), + 'HashPassword' => $this->crypt->hashString($posAccount->getStoreKey() ?? ''), + 'MerchantId' => $posAccount->getClientId(), + 'MerchantOrderId' => (string) $order['id'], + 'Amount' => (string) $this->valueFormatter->formatAmount($order['amount']), + 'FECCurrencyCode' => (string) $this->valueMapper->mapCurrency($order['currency']), + 'OkUrl' => (string) $order['success_url'], + 'FailUrl' => (string) $order['fail_url'], + 'PaymentType' => '1', + ]; + return [ 'gateway' => $gatewayURL, 'method' => 'POST', @@ -305,8 +285,8 @@ public function createHistoryRequestData(AbstractPosAccount $posAccount, array $ /** * Tarih aralığı maksimum 90 gün olabilir. */ - 'StartDate' => $data['start_date']->format('Y-m-d'), - 'EndDate' => $data['end_date']->format('Y-m-d'), + 'StartDate' => $this->valueFormatter->formatDateTime($data['start_date'], 'StartDate'), + 'EndDate' => $this->valueFormatter->formatDateTime($data['end_date'], 'EndDate'), 'LowerLimit' => ($data['page'] - 1) * $data['page_size'], 'UpperLimit' => $data['page_size'], 'ProvNumber' => null, @@ -330,8 +310,8 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar $order = $this->prepareOrderHistoryOrder($order); $result = $this->getRequestAccountData($posAccount) + [ - 'StartDate' => $order['start_date']->format('Y-m-d'), - 'EndDate' => $order['end_date']->format('Y-m-d'), + 'StartDate' => $this->valueFormatter->formatDateTime($order['start_date'], 'StartDate'), + 'EndDate' => $this->valueFormatter->formatDateTime($order['end_date'], 'EndDate'), 'LowerLimit' => 0, 'UpperLimit' => 100, 'ProvNumber' => $order['auth_code'], @@ -345,30 +325,6 @@ public function createOrderHistoryRequestData(AbstractPosAccount $posAccount, ar return $result; } - /** - * Amount Formatter - * converts 100 to 10000, or 10.01 to 1001 - * - * @param float $amount - * - * @return int - */ - protected function formatAmount(float $amount): int - { - return (int) (\round($amount, 2) * 100); - } - - /** - * 0 => '0' - * 1 => '0' - * 2 => '2' - * @inheritDoc - */ - protected function mapInstallment(int $installment): string - { - return $installment > 1 ? (string) $installment : '0'; - } - /** * @inheritDoc */ diff --git a/src/DataMapper/RequestValueFormatter/AkbankPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/AkbankPosRequestValueFormatter.php new file mode 100644 index 00000000..d6b0a124 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/AkbankPosRequestValueFormatter.php @@ -0,0 +1,59 @@ + 1 + * 1 => 1 + * 2 => 2 + * @inheritDoc + */ + public function formatInstallment(int $installment): int + { + return \max($installment, 1); + } + + /** + * @param float $amount + * + * @return string + */ + public function formatAmount(float $amount, ?string $txType = null): string + { + return \number_format($amount, 2, '.', ''); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + return $expDate->format('my'); + } + + /** + * example 2024-04-14T16:45:30.000 + * + * @inheritdoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + return $dateTime->format('Y-m-d\TH:i:s').'.000'; + } +} diff --git a/src/DataMapper/RequestValueFormatter/EstPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/EstPosRequestValueFormatter.php new file mode 100644 index 00000000..39f7c0a9 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/EstPosRequestValueFormatter.php @@ -0,0 +1,74 @@ + '' + * 1 => '' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : ''; + } + + + /** + * @inheritdoc + * + * @return string + */ + public function formatAmount(float $amount, ?string $txType = null): string + { + return (string) $amount; + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('Ecom_Payment_Card_ExpDate_Month' === $fieldName) { + return $expDate->format('m'); + } + + if ('Ecom_Payment_Card_ExpDate_Year' === $fieldName) { + return $expDate->format('y'); + } + + if ('Expires' === $fieldName) { + return $expDate->format('m/y'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + throw new NotImplementedException(); + } +} diff --git a/src/DataMapper/RequestValueFormatter/GarantiPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/GarantiPosRequestValueFormatter.php new file mode 100644 index 00000000..60f75439 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/GarantiPosRequestValueFormatter.php @@ -0,0 +1,72 @@ + '' + * 1 => '' + * 2 => '2' + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : ''; + } + + + /** + * converts 100 to 10000, or 10.01 to 1001 + * + * @inheritDoc + * + * @return int + */ + public function formatAmount(float $amount, ?string $txType = null): int + { + return (int) (\round($amount, 2) * 100); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('cardexpiredatemonth' === $fieldName) { + return $expDate->format('m'); + } + + if ('cardexpiredateyear' === $fieldName) { + return $expDate->format('y'); + } + + if ('ExpireDate' === $fieldName) { + return $expDate->format('my'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + return $dateTime->format('d/m/Y H:i'); + } +} diff --git a/src/DataMapper/RequestValueFormatter/InterPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/InterPosRequestValueFormatter.php new file mode 100644 index 00000000..74f13644 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/InterPosRequestValueFormatter.php @@ -0,0 +1,59 @@ + '' + * 1 => '' + * 2 => '2' + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : ''; + } + + + /** + * @inheritDoc + * + * @return string + */ + public function formatAmount(float $amount, ?string $txType = null): string + { + return (string) $amount; + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + return $expDate->format('my'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + throw new NotImplementedException(); + } +} diff --git a/src/DataMapper/RequestValueFormatter/KuveytPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/KuveytPosRequestValueFormatter.php new file mode 100644 index 00000000..61d5be7e --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/KuveytPosRequestValueFormatter.php @@ -0,0 +1,69 @@ + '0' + * 1 => '0' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : '0'; + } + + + /** + * example: 100 to 10000, or 10.01 to 1001 + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): int + { + return (int) (\round($amount, 2) * 100); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('CardExpireDateYear' === $fieldName) { + return $expDate->format('y'); + } + + if ('CardExpireDateMonth' === $fieldName) { + return $expDate->format('m'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + return $dateTime->format('Y-m-d\TH:i:s'); + } +} diff --git a/src/DataMapper/RequestValueFormatter/ParamPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/ParamPosRequestValueFormatter.php new file mode 100644 index 00000000..ff592ca5 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/ParamPosRequestValueFormatter.php @@ -0,0 +1,80 @@ + '1' + * 1 => '1' + * 2 => '2' + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : '1'; + } + + /** + * @inheritDoc + * + * @return string + */ + public function formatAmount(float $amount, ?string $txType = null): string + { + $txTypes = [ + PosInterface::TX_TYPE_CANCEL, + PosInterface::TX_TYPE_REFUND, + PosInterface::TX_TYPE_REFUND_PARTIAL, + ]; + + if (\in_array($txType, $txTypes, true)) { + return \number_format($amount, 2, '.', ''); + } + + return \number_format($amount, 2, ',', ''); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('KK_SK_Yil' === $fieldName) { + return $expDate->format('Y'); + } + + if ('KK_SK_Ay' === $fieldName) { + return $expDate->format('m'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * example 20.11.2018 15:00:00 + * + * @inheritdoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + return $dateTime->format('d.m.Y H:i:s'); + } +} diff --git a/src/DataMapper/RequestValueFormatter/PayFlexCPV4PosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/PayFlexCPV4PosRequestValueFormatter.php new file mode 100644 index 00000000..52591341 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/PayFlexCPV4PosRequestValueFormatter.php @@ -0,0 +1,72 @@ + '0' + * 1 => '0' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : '0'; + } + + + /** + * ex: 10.1 => 10.10 + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): string + { + return \number_format($amount, 2, '.', ''); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('ExpireMonth' === $fieldName) { + return $expDate->format('m'); + } + + if ('ExpireYear' === $fieldName) { + return $expDate->format('y'); + } + + if ('Expiry' === $fieldName) { + return $expDate->format('Ym'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + throw new NotImplementedException(); + } +} diff --git a/src/DataMapper/RequestValueFormatter/PayFlexV4PosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/PayFlexV4PosRequestValueFormatter.php new file mode 100644 index 00000000..7ffb5739 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/PayFlexV4PosRequestValueFormatter.php @@ -0,0 +1,69 @@ + '0' + * 1 => '0' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : '0'; + } + + + /** + * ex: 10.1 => 10.10 + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): string + { + return \number_format($amount, 2, '.', ''); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('ExpiryDate' === $fieldName) { + return $expDate->format('ym'); + } + + if ('Expiry' === $fieldName) { + return $expDate->format('Ym'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * example: 20240414 + * + * @inheritdoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null, ?string $txType = null): string + { + return $dateTime->format('Ymd'); + } +} diff --git a/src/DataMapper/RequestValueFormatter/PayForPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/PayForPosRequestValueFormatter.php new file mode 100644 index 00000000..ff31b8ef --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/PayForPosRequestValueFormatter.php @@ -0,0 +1,61 @@ + '0' + * 1 => '0' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : '0'; + } + + + /** + * 10.1 => "10.1" + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): string + { + return (string) $amount; + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + return $expDate->format('my'); + } + + /** + * example 2024-04-14T16:45:30.000 + * + * @inheritdoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + return $dateTime->format('Ymd'); + } +} diff --git a/src/DataMapper/RequestValueFormatter/PosNetRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/PosNetRequestValueFormatter.php new file mode 100644 index 00000000..4159439f --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/PosNetRequestValueFormatter.php @@ -0,0 +1,131 @@ + '00' + * 1 => '00' + * 2 => '02' + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + if ($installment > 1) { + return \str_pad((string) $installment, 2, '0', STR_PAD_LEFT); + } + + return '00'; + } + + /** + * formats 10.01 to 1001 + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): int + { + return (int) (\round($amount, 2) * 100); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + return $expDate->format('ym'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + throw new NotImplementedException(); + } + + /** + * formats order id by adding 0 pad to the left and adding prefix + * + * @param string $orderId + * @param PosInterface::TX_TYPE_*|null $txType + * @param PosInterface::MODEL_*|null $orderPaymentModel payment model of the order + * + * @return string + */ + public function formatOrderId(string $orderId, ?string $txType = null, ?string $orderPaymentModel = null): string + { + $prefix = ''; + $padLength = self::ORDER_ID_LENGTH; + + if (\in_array($txType, [ + PosInterface::TX_TYPE_STATUS, + PosInterface::TX_TYPE_REFUND, + PosInterface::TX_TYPE_REFUND_PARTIAL, + PosInterface::TX_TYPE_CANCEL, + ], true)) { + /** + * To check the status of an order or cancel/refund order Yapikredi + * - requires the order length to be 24 + * - and order id prefix which is "TDSC" for 3D payments + */ + $prefix = self::ORDER_ID_REGULAR_PREFIX; + $padLength = self::ORDER_ID_TOTAL_LENGTH; + if (PosInterface::MODEL_3D_SECURE === $orderPaymentModel) { + $prefix = self::ORDER_ID_3D_PREFIX; + } elseif (PosInterface::MODEL_3D_PAY === $orderPaymentModel) { + $prefix = self::ORDER_ID_3D_PAY_PREFIX; + } + } + + if (\strlen($orderId) > $padLength) { + throw new \InvalidArgumentException(\sprintf( + // Banka tarafindan belirlenen kisitlama + "Saglanan siparis ID'nin (%s) uzunlugu %d karakter. Siparis ID %d karakterden uzun olamaz!", + $orderId, + \strlen($orderId), + $padLength + )); + } + + return $prefix.\str_pad($orderId, $padLength - \strlen($prefix), '0', STR_PAD_LEFT); + } +} diff --git a/src/DataMapper/RequestValueFormatter/PosNetV1PosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/PosNetV1PosRequestValueFormatter.php new file mode 100644 index 00000000..47998479 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/PosNetV1PosRequestValueFormatter.php @@ -0,0 +1,134 @@ + '0' + * 1 => '0' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + if ($installment > 1) { + return (string) $installment; + } + + return '0'; + } + + /** + * example: 10.01 to 1001 + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): int + { + return (int) (\round($amount, 2) * 100); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + return $expDate->format('ym'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + throw new NotImplementedException(); + } + + /** + * formats order id by adding 0 pad to the left and adding prefix + * + * @param string $orderId + * @param PosInterface::TX_TYPE_*|null $txType + * @param PosInterface::MODEL_*|null $orderPaymentModel payment model of the order + * + * @return string + */ + public function formatOrderId(string $orderId, ?string $txType = null, ?string $orderPaymentModel = null): string + { + $prefix = ''; + $padLength = self::ORDER_ID_LENGTH; + + if (\in_array($txType, [ + PosInterface::TX_TYPE_STATUS, + PosInterface::TX_TYPE_REFUND, + PosInterface::TX_TYPE_REFUND_PARTIAL, + PosInterface::TX_TYPE_CANCEL, + ], true)) { + /** + * To check the status of an order or cancel/refund order Yapikredi + * - requires the order length to be 24 + * - and order id prefix which is "TDSC" for 3D payments + */ + $prefix = self::ORDER_ID_REGULAR_PREFIX; + $padLength = self::ORDER_ID_TOTAL_LENGTH; + if (PosInterface::MODEL_3D_SECURE === $orderPaymentModel) { + $prefix = self::ORDER_ID_3D_PREFIX; + } elseif (PosInterface::MODEL_3D_PAY === $orderPaymentModel) { + $prefix = self::ORDER_ID_3D_PAY_PREFIX; + + } + } + + if (\strlen($orderId) > $padLength) { + throw new \InvalidArgumentException(\sprintf( + // Banka tarafindan belirlenen kisitlama + "Saglanan siparis ID'nin (%s) uzunlugu %d karakter. Siparis ID %d karakterden uzun olamaz!", + $orderId, + \strlen($orderId), + $padLength + )); + } + + return $prefix.\str_pad($orderId, $padLength - strlen($prefix), '0', STR_PAD_LEFT); + } +} diff --git a/src/DataMapper/RequestValueFormatter/RequestValueFormatterInterface.php b/src/DataMapper/RequestValueFormatter/RequestValueFormatterInterface.php new file mode 100644 index 00000000..0cece249 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/RequestValueFormatterInterface.php @@ -0,0 +1,60 @@ + $gatewayClass + * + * @return bool + */ + public static function supports(string $gatewayClass): bool; + + /** + * @param int<0, max> $installment + * + * @return string|int + */ + public function formatInstallment(int $installment); + + + /** + * formats purchase amount + * + * @param float $amount + * @param PosInterface::TX_TYPE_*|null $txType + * + * @return string|int|float + */ + public function formatAmount(float $amount, ?string $txType = null); + + /** + * @param \DateTimeInterface $expDate + * @param string $fieldName request expiration date/month/year field name + * + * @return string formatted expiration month, year, or month and year + * + * @throws \InvalidArgumentException when unsupported field name + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string; + + /** + * @param \DateTimeInterface $dateTime + * @param string $fieldName request field name of the date + * + * @return string formatted date time + * + * @throws \InvalidArgumentException when unsupported field name + */ + public function formatDateTime(\DateTimeInterface $dateTime, string $fieldName): string; +} diff --git a/src/DataMapper/RequestValueFormatter/ToslaPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/ToslaPosRequestValueFormatter.php new file mode 100644 index 00000000..96a93315 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/ToslaPosRequestValueFormatter.php @@ -0,0 +1,75 @@ + '0' + * 1 => '0' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): int + { + return $installment > 1 ? $installment : 0; + } + + + /** + * formats 10.01 to 1001 + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): int + { + return (int) (\round($amount, 2) * 100); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('ExpireDate' === $fieldName) { + return $expDate->format('m/y'); + } + + if ('expireDate' === $fieldName) { + return $expDate->format('my'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + if ('timeSpan' === $fieldName) { + return $dateTime->format('YmdHis'); + } + + if ('transactionDate' === $fieldName) { + return $dateTime->format('Ymd'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } +} diff --git a/src/DataMapper/RequestValueFormatter/VakifKatilimPosRequestValueFormatter.php b/src/DataMapper/RequestValueFormatter/VakifKatilimPosRequestValueFormatter.php new file mode 100644 index 00000000..39629a16 --- /dev/null +++ b/src/DataMapper/RequestValueFormatter/VakifKatilimPosRequestValueFormatter.php @@ -0,0 +1,71 @@ + '0' + * 1 => '0' + * 2 => '2' + * + * @inheritDoc + */ + public function formatInstallment(int $installment): string + { + return $installment > 1 ? (string) $installment : '0'; + } + + + /** + * example: 100 to 10000, or 10.01 to 1001 + * + * @inheritDoc + */ + public function formatAmount(float $amount, ?string $txType = null): int + { + return (int) (\round($amount, 2) * 100); + } + + /** + * @inheritDoc + */ + public function formatCardExpDate(\DateTimeInterface $expDate, string $fieldName): string + { + if ('CardExpireDateYear' === $fieldName) { + return $expDate->format('y'); + } + + if ('CardExpireDateMonth' === $fieldName) { + return $expDate->format('m'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } + + /** + * @inheritDoc + */ + public function formatDateTime(\DateTimeInterface $dateTime, ?string $fieldName = null): string + { + if ('StartDate' === $fieldName || 'EndDate' === $fieldName) { + return $dateTime->format('Y-m-d'); + } + + throw new \InvalidArgumentException('Unsupported field name'); + } +} diff --git a/src/DataMapper/RequestValueMapper/AbstractRequestValueMapper.php b/src/DataMapper/RequestValueMapper/AbstractRequestValueMapper.php new file mode 100644 index 00000000..86d1373b --- /dev/null +++ b/src/DataMapper/RequestValueMapper/AbstractRequestValueMapper.php @@ -0,0 +1,209 @@ + */ + protected array $cardTypeMappings = []; + + /** + * Transaction Types + * + * @var array> + */ + protected array $txTypeMappings = []; + + /** + * period mapping for recurring orders + * @var array<'DAY'|'WEEK'|'MONTH'|'YEAR', string> + */ + protected array $recurringOrderFrequencyMappings = []; + + /** @var array */ + protected array $secureTypeMappings = []; + + /** @var array */ + protected array $langMappings = []; + + /** + * by default we set ISO 4217 currency values. + * Some gateways may use different currency values. + * + * @var non-empty-array + */ + protected array $currencyMappings = [ + PosInterface::CURRENCY_TRY => '949', + PosInterface::CURRENCY_USD => '840', + PosInterface::CURRENCY_EUR => '978', + PosInterface::CURRENCY_GBP => '826', + PosInterface::CURRENCY_JPY => '392', + PosInterface::CURRENCY_RUB => '643', + ]; + + /** + * @return array> + */ + public function getTxTypeMappings(): array + { + return $this->txTypeMappings; + } + + /** + * @inheritDoc + */ + public function mapTxType(string $txType, ?string $paymentModel = null, ?array $order = null): string + { + if (!$this->isSupportedTxType($txType, $paymentModel)) { + throw new UnsupportedTransactionTypeException(); + } + + if (\is_string($this->txTypeMappings[$txType])) { + return $this->txTypeMappings[$txType]; + } + + if (null === $paymentModel) { + throw new \InvalidArgumentException( + sprintf('$paymentModel must be provided for the transaction type %s', $txType) + ); + } + + return $this->txTypeMappings[$txType][$paymentModel]; + } + + /** + * @return array + */ + public function getSecureTypeMappings(): array + { + return $this->secureTypeMappings; + } + + /** + * @inheritDoc + */ + public function mapSecureType(string $paymentModel): string + { + if ([] === $this->secureTypeMappings) { + throw new \LogicException('Security type mappings are not supported.'); + } + + return $this->secureTypeMappings[$paymentModel]; + } + + /** + * @inheritDoc + */ + public function mapCurrency(string $currency) + { + return $this->currencyMappings[$currency]; + } + + /** + * @inheritDoc + */ + public function getCurrencyMappings(): array + { + return $this->currencyMappings; + } + + /** + * @inheritDoc + */ + public function getRecurringOrderFrequencyMappings(): array + { + return $this->recurringOrderFrequencyMappings; + } + + /** + * @inheritDoc + */ + public function mapRecurringFrequency(string $period): string + { + if ([] === $this->recurringOrderFrequencyMappings) { + throw new \LogicException('Recurring frequency mappings are not supported.'); + } + + return $this->recurringOrderFrequencyMappings[$period]; + } + + /** + * @inheritDoc + */ + public function mapLang(string $lang): string + { + if ([] === $this->langMappings) { + throw new \LogicException('Language mappings are not supported.'); + } + + return $this->langMappings[$lang] + ?? $this->langMappings[PosInterface::LANG_TR] + ?? $lang; + } + + /** + * @inheritDoc + */ + public function getLangMappings(): array + { + return $this->langMappings; + } + + /** + * @inheritDoc + */ + public function getCardTypeMappings(): array + { + return $this->cardTypeMappings; + } + + /** + * @inheritDoc + */ + public function mapCardType(string $cardType): string + { + if ([] === $this->cardTypeMappings) { + throw new \LogicException('Card type mappings are not supported.'); + } + + return $this->cardTypeMappings[$cardType]; + } + + /** + * @phpstan-param PosInterface::TX_TYPE_* $txType + * @phpstan-param PosInterface::MODEL_*|null $paymentModel + * + * @param string $txType + * @param string|null $paymentModel + * + * @return bool + * + * @throws \InvalidArgumentException + */ + protected function isSupportedTxType(string $txType, ?string $paymentModel = null): bool + { + if (!isset($this->txTypeMappings[$txType])) { + return false; + } + + if (\is_array($this->txTypeMappings[$txType])) { + if (null === $paymentModel) { + throw new \InvalidArgumentException( + sprintf('$paymentModel must be provided for the transaction type %s', $txType) + ); + } + + return isset($this->txTypeMappings[$txType][$paymentModel]); + } + + return true; + } +} diff --git a/src/DataMapper/RequestValueMapper/AkbankPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/AkbankPosRequestValueMapper.php new file mode 100644 index 00000000..c56f1011 --- /dev/null +++ b/src/DataMapper/RequestValueMapper/AkbankPosRequestValueMapper.php @@ -0,0 +1,83 @@ + [ + PosInterface::MODEL_NON_SECURE => '1000', + PosInterface::MODEL_3D_SECURE => '3000', + PosInterface::MODEL_3D_PAY => '3000', + PosInterface::MODEL_3D_HOST => '3000', + ], + PosInterface::TX_TYPE_PAY_PRE_AUTH => [ + PosInterface::MODEL_NON_SECURE => '1004', + PosInterface::MODEL_3D_SECURE => '3004', + PosInterface::MODEL_3D_PAY => '3004', + PosInterface::MODEL_3D_HOST => '3004', + ], + PosInterface::TX_TYPE_PAY_POST_AUTH => '1005', + PosInterface::TX_TYPE_REFUND => '1002', + PosInterface::TX_TYPE_REFUND_PARTIAL => '1002', + PosInterface::TX_TYPE_CANCEL => '1003', + PosInterface::TX_TYPE_ORDER_HISTORY => '1010', + PosInterface::TX_TYPE_HISTORY => '1009', + ]; + + /** + * @var non-empty-array + */ + protected array $currencyMappings = [ + PosInterface::CURRENCY_TRY => 949, + PosInterface::CURRENCY_USD => 840, + PosInterface::CURRENCY_EUR => 978, + PosInterface::CURRENCY_GBP => 826, + PosInterface::CURRENCY_JPY => 392, + PosInterface::CURRENCY_RUB => 643, + ]; + + /** + * {@inheritdoc} + */ + protected array $recurringOrderFrequencyMappings = [ + 'DAY' => 'D', + 'WEEK' => 'W', + 'MONTH' => 'M', + 'YEAR' => 'Y', + ]; + + /** + * {@inheritdoc} + */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3D', + PosInterface::MODEL_3D_PAY => '3D_PAY', + PosInterface::MODEL_3D_HOST => '3D_PAY_HOSTING', + PosInterface::MODEL_NON_SECURE => 'PAY_HOSTING', + ]; + + /** @var array */ + protected array $langMappings = [ + PosInterface::LANG_TR => 'TR', + PosInterface::LANG_EN => 'EN', + ]; +} diff --git a/src/DataMapper/RequestValueMapper/EstPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/EstPosRequestValueMapper.php new file mode 100644 index 00000000..8d7ec275 --- /dev/null +++ b/src/DataMapper/RequestValueMapper/EstPosRequestValueMapper.php @@ -0,0 +1,76 @@ + 'tr', + PosInterface::LANG_EN => 'en', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Auth', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'PostAuth', + PosInterface::TX_TYPE_CANCEL => 'Void', + PosInterface::TX_TYPE_REFUND => 'Credit', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'Credit', + PosInterface::TX_TYPE_STATUS => 'ORDERSTATUS', + PosInterface::TX_TYPE_HISTORY => 'ORDERHISTORY', + ]; + + /** + * {@inheritdoc} + */ + protected array $recurringOrderFrequencyMappings = [ + 'DAY' => 'D', + 'WEEK' => 'W', + 'MONTH' => 'M', + 'YEAR' => 'Y', + ]; + + /** + * {@inheritdoc} + */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3d', + PosInterface::MODEL_3D_PAY => '3d_pay', + PosInterface::MODEL_3D_PAY_HOSTING => '3d_pay_hosting', + PosInterface::MODEL_3D_HOST => '3d_host', + PosInterface::MODEL_NON_SECURE => 'regular', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return EstV3Pos::class === $gatewayClass + || EstPos::class === $gatewayClass; + } + + /** + * @inheritDoc + * + * @return string + */ + public function mapCurrency(string $currency): string + { + return (string) $this->currencyMappings[$currency]; + } +} diff --git a/src/DataMapper/RequestValueMapper/GarantiPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/GarantiPosRequestValueMapper.php new file mode 100644 index 00000000..a2049888 --- /dev/null +++ b/src/DataMapper/RequestValueMapper/GarantiPosRequestValueMapper.php @@ -0,0 +1,53 @@ + 'sales', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'preauth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'postauth', + PosInterface::TX_TYPE_CANCEL => 'void', + PosInterface::TX_TYPE_REFUND => 'refund', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'refund', + PosInterface::TX_TYPE_ORDER_HISTORY => 'orderhistoryinq', + PosInterface::TX_TYPE_HISTORY => 'orderlistinq', + PosInterface::TX_TYPE_STATUS => 'orderinq', + ]; + + /** + * {@inheritdoc} + */ + protected array $recurringOrderFrequencyMappings = [ + 'DAY' => 'D', + 'WEEK' => 'W', + 'MONTH' => 'M', + ]; + + /** + * {@inheritdoc} + */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3D', + PosInterface::MODEL_3D_PAY => '3D_PAY', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return GarantiPos::class === $gatewayClass; + } +} diff --git a/src/DataMapper/RequestValueMapper/InterPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/InterPosRequestValueMapper.php new file mode 100644 index 00000000..14fba12a --- /dev/null +++ b/src/DataMapper/RequestValueMapper/InterPosRequestValueMapper.php @@ -0,0 +1,73 @@ + 'tr', + PosInterface::LANG_EN => 'en', + ]; + + /** + * {@inheritdoc} + */ + protected array $cardTypeMappings = [ + CreditCardInterface::CARD_TYPE_VISA => '0', + CreditCardInterface::CARD_TYPE_MASTERCARD => '1', + CreditCardInterface::CARD_TYPE_AMEX => '2', + CreditCardInterface::CARD_TYPE_TROY => '3', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Auth', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'PostAuth', + PosInterface::TX_TYPE_CANCEL => 'Void', + PosInterface::TX_TYPE_REFUND => 'Refund', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', + PosInterface::TX_TYPE_STATUS => 'StatusHistory', + ]; + + /** + * {@inheritdoc} + */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3DModel', + PosInterface::MODEL_3D_PAY => '3DPay', + PosInterface::MODEL_3D_HOST => '3DHost', + PosInterface::MODEL_NON_SECURE => 'NonSecure', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return InterPos::class === $gatewayClass; + } + + /** + * @inheritDoc + * + * @return string + */ + public function mapCurrency(string $currency): string + { + return (string) $this->currencyMappings[$currency]; + } +} diff --git a/src/DataMapper/RequestValueMapper/KuveytPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/KuveytPosRequestValueMapper.php new file mode 100644 index 00000000..4823f5a4 --- /dev/null +++ b/src/DataMapper/RequestValueMapper/KuveytPosRequestValueMapper.php @@ -0,0 +1,73 @@ + '0949', + PosInterface::CURRENCY_USD => '0840', + PosInterface::CURRENCY_EUR => '0978', + ]; + + /** + * {@inheritdoc} + */ + protected array $cardTypeMappings = [ + CreditCardInterface::CARD_TYPE_VISA => 'Visa', + CreditCardInterface::CARD_TYPE_MASTERCARD => 'MasterCard', + CreditCardInterface::CARD_TYPE_TROY => 'Troy', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Sale', + PosInterface::TX_TYPE_CANCEL => 'SaleReversal', + PosInterface::TX_TYPE_STATUS => 'GetMerchantOrderDetail', + PosInterface::TX_TYPE_REFUND => 'DrawBack', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'PartialDrawback', + ]; + + /** + * {@inheritdoc} + */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3', + PosInterface::MODEL_NON_SECURE => '0', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return KuveytPos::class === $gatewayClass + || KuveytSoapApiPos::class === $gatewayClass; + } + + /** + * @inheritDoc + * + * @return string + */ + public function mapCurrency(string $currency): string + { + return (string) $this->currencyMappings[$currency]; + } +} diff --git a/src/DataMapper/RequestValueMapper/ParamPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/ParamPosRequestValueMapper.php new file mode 100644 index 00000000..3997994b --- /dev/null +++ b/src/DataMapper/RequestValueMapper/ParamPosRequestValueMapper.php @@ -0,0 +1,81 @@ + [ + PosInterface::MODEL_NON_SECURE => 'TP_WMD_UCD', + PosInterface::MODEL_3D_SECURE => 'TP_WMD_UCD', + PosInterface::MODEL_3D_PAY => 'Pos_Odeme', + PosInterface::MODEL_3D_HOST => 'TO_Pre_Encrypting_OOS', + ], + PosInterface::TX_TYPE_PAY_PRE_AUTH => [ + PosInterface::MODEL_NON_SECURE => 'TP_Islem_Odeme_OnProv_WMD', + PosInterface::MODEL_3D_SECURE => 'TP_Islem_Odeme_OnProv_WMD', + ], + PosInterface::TX_TYPE_PAY_POST_AUTH => 'TP_Islem_Odeme_OnProv_Kapa', + PosInterface::TX_TYPE_REFUND => 'TP_Islem_Iptal_Iade_Kismi2', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'TP_Islem_Iptal_Iade_Kismi2', + PosInterface::TX_TYPE_CANCEL => 'TP_Islem_Iptal_Iade_Kismi2', + PosInterface::TX_TYPE_STATUS => 'TP_Islem_Sorgulama4', + PosInterface::TX_TYPE_HISTORY => 'TP_Islem_Izleme', + ]; + + /** + * @var non-empty-array + */ + protected array $currencyMappings = [ + PosInterface::CURRENCY_TRY => '1000', + PosInterface::CURRENCY_USD => '1001', + PosInterface::CURRENCY_EUR => '1002', + PosInterface::CURRENCY_GBP => '1003', + ]; + + /** + * {@inheritdoc} + */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3D', + PosInterface::MODEL_3D_PAY => '3D', + PosInterface::MODEL_NON_SECURE => 'NS', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return ParamPos::class === $gatewayClass + || Param3DHostPos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function mapTxType(string $txType, ?string $paymentModel = null, ?array $order = null): string + { + if (isset($order['currency']) && PosInterface::CURRENCY_TRY !== $order['currency']) { + return 'TP_Islem_Odeme_WD'; + } + + $orderTxType = $order['transaction_type'] ?? null; + if (PosInterface::TX_TYPE_CANCEL === $txType && PosInterface::TX_TYPE_PAY_PRE_AUTH === $orderTxType) { + return 'TP_Islem_Iptal_OnProv'; + } + + return parent::mapTxType($txType, $paymentModel); + } +} diff --git a/src/DataMapper/RequestValueMapper/PayFlexCPV4PosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/PayFlexCPV4PosRequestValueMapper.php new file mode 100644 index 00000000..fa06b04d --- /dev/null +++ b/src/DataMapper/RequestValueMapper/PayFlexCPV4PosRequestValueMapper.php @@ -0,0 +1,64 @@ + '100', + CreditCardInterface::CARD_TYPE_MASTERCARD => '200', + CreditCardInterface::CARD_TYPE_TROY => '300', + CreditCardInterface::CARD_TYPE_AMEX => '400', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Sale', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capture', + PosInterface::TX_TYPE_CANCEL => 'Cancel', + PosInterface::TX_TYPE_REFUND => 'Refund', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', + PosInterface::TX_TYPE_HISTORY => 'TxnHistory', + PosInterface::TX_TYPE_STATUS => 'OrderInquiry', + ]; + + /** + * {@inheritdoc} + */ + protected array $langMappings = [ + PosInterface::LANG_TR => 'tr-TR', + PosInterface::LANG_EN => 'en-US', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayFlexCPV4Pos::class === $gatewayClass; + } + + /** + * @inheritDoc + * + * @return string + */ + public function mapCurrency(string $currency): string + { + return (string) $this->currencyMappings[$currency]; + } +} diff --git a/src/DataMapper/RequestValueMapper/PayFlexV4PosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/PayFlexV4PosRequestValueMapper.php new file mode 100644 index 00000000..37d07e4a --- /dev/null +++ b/src/DataMapper/RequestValueMapper/PayFlexV4PosRequestValueMapper.php @@ -0,0 +1,64 @@ + '100', + CreditCardInterface::CARD_TYPE_MASTERCARD => '200', + CreditCardInterface::CARD_TYPE_TROY => '300', + CreditCardInterface::CARD_TYPE_AMEX => '400', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Sale', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capture', + PosInterface::TX_TYPE_CANCEL => 'Cancel', + PosInterface::TX_TYPE_REFUND => 'Refund', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', + PosInterface::TX_TYPE_STATUS => 'status', + ]; + + /** + * {@inheritdoc} + */ + protected array $recurringOrderFrequencyMappings = [ + 'DAY' => 'Day', + 'MONTH' => 'Month', + 'YEAR' => 'Year', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayFlexV4Pos::class === $gatewayClass; + } + + /** + * @inheritDoc + * + * @return string + */ + public function mapCurrency(string $currency): string + { + return (string) $this->currencyMappings[$currency]; + } +} diff --git a/src/DataMapper/RequestValueMapper/PayForPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/PayForPosRequestValueMapper.php new file mode 100644 index 00000000..e02f3712 --- /dev/null +++ b/src/DataMapper/RequestValueMapper/PayForPosRequestValueMapper.php @@ -0,0 +1,61 @@ + 'tr', + PosInterface::LANG_EN => 'en', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Auth', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'PostAuth', + PosInterface::TX_TYPE_CANCEL => 'Void', + PosInterface::TX_TYPE_REFUND => 'Refund', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'Refund', + PosInterface::TX_TYPE_HISTORY => 'TxnHistory', + PosInterface::TX_TYPE_STATUS => 'OrderInquiry', + ]; + + /** {@inheritdoc} */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3DModel', + PosInterface::MODEL_3D_PAY => '3DPay', + PosInterface::MODEL_3D_HOST => '3DHost', + PosInterface::MODEL_NON_SECURE => 'NonSecure', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayForPos::class === $gatewayClass; + } + + /** + * @inheritDoc + * + * @return string + */ + public function mapCurrency(string $currency): string + { + return (string) $this->currencyMappings[$currency]; + } +} diff --git a/src/DataMapper/RequestValueMapper/PosNetRequestValueMapper.php b/src/DataMapper/RequestValueMapper/PosNetRequestValueMapper.php new file mode 100644 index 00000000..bf0fa46b --- /dev/null +++ b/src/DataMapper/RequestValueMapper/PosNetRequestValueMapper.php @@ -0,0 +1,54 @@ + 'tr', + PosInterface::LANG_EN => 'en', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Sale', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capt', + PosInterface::TX_TYPE_CANCEL => 'reverse', + PosInterface::TX_TYPE_REFUND => 'return', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'return', + PosInterface::TX_TYPE_STATUS => 'agreement', + ]; + + /** + * {@inheritDoc} + */ + protected array $currencyMappings = [ + PosInterface::CURRENCY_TRY => 'TL', + PosInterface::CURRENCY_USD => 'US', + PosInterface::CURRENCY_EUR => 'EU', + PosInterface::CURRENCY_GBP => 'GB', + PosInterface::CURRENCY_JPY => 'JP', + PosInterface::CURRENCY_RUB => 'RU', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PosNet::class === $gatewayClass; + } +} diff --git a/src/DataMapper/RequestValueMapper/PosNetV1PosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/PosNetV1PosRequestValueMapper.php new file mode 100644 index 00000000..c9b834c5 --- /dev/null +++ b/src/DataMapper/RequestValueMapper/PosNetV1PosRequestValueMapper.php @@ -0,0 +1,54 @@ + 'tr', + PosInterface::LANG_EN => 'en', + ]; + + /** + * {@inheritDoc} + */ + protected array $txTypeMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => 'Sale', + PosInterface::TX_TYPE_PAY_PRE_AUTH => 'Auth', + PosInterface::TX_TYPE_PAY_POST_AUTH => 'Capture', + PosInterface::TX_TYPE_CANCEL => 'Reverse', + PosInterface::TX_TYPE_REFUND => 'Return', + PosInterface::TX_TYPE_REFUND_PARTIAL => 'Return', + PosInterface::TX_TYPE_STATUS => 'TransactionInquiry', + ]; + + /** + * {@inheritDoc} + */ + protected array $currencyMappings = [ + PosInterface::CURRENCY_TRY => 'TL', + PosInterface::CURRENCY_USD => 'US', + PosInterface::CURRENCY_EUR => 'EU', + PosInterface::CURRENCY_GBP => 'GB', + PosInterface::CURRENCY_JPY => 'JP', + PosInterface::CURRENCY_RUB => 'RU', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PosNetV1Pos::class === $gatewayClass; + } +} diff --git a/src/DataMapper/RequestValueMapper/RequestValueMapperInterface.php b/src/DataMapper/RequestValueMapper/RequestValueMapperInterface.php new file mode 100644 index 00000000..0d005e8a --- /dev/null +++ b/src/DataMapper/RequestValueMapper/RequestValueMapperInterface.php @@ -0,0 +1,105 @@ + $gatewayClass + * + * @return bool + */ + public static function supports(string $gatewayClass): bool; + + /** + * @return array> + */ + public function getTxTypeMappings(): array; + + /** + * @param PosInterface::TX_TYPE_* $txType + * @param PosInterface::MODEL_* $paymentModel + * @param array $order + * + * @return string + * + * @throws UnsupportedTransactionTypeException + * @throws \InvalidArgumentException + */ + public function mapTxType(string $txType, ?string $paymentModel = null, ?array $order = []): string; + + /** + * @param PosInterface::MODEL_* $paymentModel + * + * @return string + */ + public function mapSecureType(string $paymentModel): string; + + /** + * @return array + */ + public function getSecureTypeMappings(): array; + + /** + * @phpstan-param PosInterface::CURRENCY_* $currency + * + * @param string $currency + * + * @return string|int + */ + public function mapCurrency(string $currency); + + /** + * @return non-empty-array + */ + public function getCurrencyMappings(): array; + + /** + * If language mapping is not found, returns maps for the default language (PosInterface::LANG_TR) or $lang itself. + * + * @param PosInterface::LANG_* $lang + * + * @return string + */ + public function mapLang(string $lang): string; + + /** + * @return array + */ + public function getLangMappings(): array; + + /** + * @return array<'DAY'|'WEEK'|'MONTH'|'YEAR', string> + */ + public function getRecurringOrderFrequencyMappings(): array; + + /** + * @param string $period + * + * @return string + */ + public function mapRecurringFrequency(string $period): string; + + /** + * @return array + */ + public function getCardTypeMappings(): array; + + /** + * @param CreditCardInterface::CARD_TYPE_* $cardType + * + * @return string + */ + public function mapCardType(string $cardType): string; +} diff --git a/src/DataMapper/RequestValueMapper/ToslaPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/ToslaPosRequestValueMapper.php new file mode 100644 index 00000000..5823bb8a --- /dev/null +++ b/src/DataMapper/RequestValueMapper/ToslaPosRequestValueMapper.php @@ -0,0 +1,43 @@ + '1', + PosInterface::TX_TYPE_PAY_PRE_AUTH => '2', + PosInterface::TX_TYPE_PAY_POST_AUTH => '3', + PosInterface::TX_TYPE_CANCEL => '4', + PosInterface::TX_TYPE_REFUND => '5', + PosInterface::TX_TYPE_REFUND_PARTIAL => '5', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return ToslaPos::class === $gatewayClass; + } + + /** + * @inheritDoc + * + * @return int + */ + public function mapCurrency(string $currency): int + { + return (int) $this->currencyMappings[$currency]; + } +} diff --git a/src/DataMapper/RequestValueMapper/VakifKatilimPosRequestValueMapper.php b/src/DataMapper/RequestValueMapper/VakifKatilimPosRequestValueMapper.php new file mode 100644 index 00000000..86106bb4 --- /dev/null +++ b/src/DataMapper/RequestValueMapper/VakifKatilimPosRequestValueMapper.php @@ -0,0 +1,43 @@ + '0949', + PosInterface::CURRENCY_USD => '0840', + PosInterface::CURRENCY_EUR => '0978', + PosInterface::CURRENCY_GBP => '0826', + PosInterface::CURRENCY_JPY => '0392', + PosInterface::CURRENCY_RUB => '0810', + ]; + + /** + * {@inheritdoc} + */ + protected array $secureTypeMappings = [ + PosInterface::MODEL_3D_SECURE => '3', + PosInterface::MODEL_NON_SECURE => '5', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return VakifKatilimPos::class === $gatewayClass; + } +} diff --git a/src/DataMapper/ResponseDataMapper/AbstractResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/AbstractResponseDataMapper.php index abbae0d6..812fc41a 100644 --- a/src/DataMapper/ResponseDataMapper/AbstractResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/AbstractResponseDataMapper.php @@ -6,6 +6,8 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\PosInterface; use Psr\Log\LoggerInterface; @@ -14,101 +16,28 @@ abstract class AbstractResponseDataMapper implements ResponseDataMapperInterface /** @var string */ public const PROCEDURE_SUCCESS_CODE = '00'; - protected LoggerInterface $logger; - /** @var array */ protected array $codes = []; - /** @var array */ - protected array $currencyMappings; + protected ResponseValueFormatterInterface $valueFormatter; - /** @var array> */ - protected array $txTypeMappings; + protected ResponseValueMapperInterface $valueMapper; - /** @var array */ - protected array $secureTypeMappings; + protected LoggerInterface $logger; /** - * @param array $currencyMappings - * @param array $txTypeMappings - * @param array $secureTypeMappings - * @param LoggerInterface $logger + * @param ResponseValueFormatterInterface $valueFormatter + * @param ResponseValueMapperInterface $valueMapper + * @param LoggerInterface $logger */ - public function __construct(array $currencyMappings, array $txTypeMappings, array $secureTypeMappings, LoggerInterface $logger) - { + public function __construct( + ResponseValueFormatterInterface $valueFormatter, + ResponseValueMapperInterface $valueMapper, + LoggerInterface $logger + ) { $this->logger = $logger; - $this->currencyMappings = \array_flip($currencyMappings); - $this->txTypeMappings = $txTypeMappings; - $this->secureTypeMappings = \array_flip($secureTypeMappings); - } - - /** - * @return array> - */ - public function getTxTypeMappings(): array - { - return $this->txTypeMappings; - } - - /** - * @param string|int $txType - * - * @return PosInterface::TX_*|null - */ - public function mapTxType($txType): ?string - { - foreach ($this->txTypeMappings as $mappedTxType => $mapping) { - if (\is_array($mapping) && \in_array($txType, $mapping, true)) { - return $mappedTxType; - } - - if ($mapping === $txType) { - return $mappedTxType; - } - } - - return null; - } - - /** - * @param string|int $securityType - * - * @return PosInterface::MODEL_*|null - */ - public function mapSecurityType($securityType): ?string - { - return $this->secureTypeMappings[$securityType] ?? null; - } - - /** - * "1000.01" => 1000.01 - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return (float) $amount; - } - - /** - * @param string $currency currency code that is accepted by bank - * - * @return PosInterface::CURRENCY_*|string - */ - protected function mapCurrency(string $currency): string - { - return $this->currencyMappings[$currency] ?? $currency; - } - - /** - * @param string|null $installment - * - * @return int - */ - protected function mapInstallment(?string $installment): int - { - return (int) $installment; + $this->valueFormatter = $valueFormatter; + $this->valueMapper = $valueMapper; } /** @@ -237,7 +166,7 @@ protected function getStatusDetail(?string $procReturnCode): ?string /** * bankadan gelen response'da bos string degerler var. - * bu metod ile bos string'leri null deger olarak degistiriyoruz + * bu method ile bos string'leri null deger olarak degistiriyoruz * * @param mixed $data * diff --git a/src/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapper.php index 3298ea9c..1bf88d1a 100644 --- a/src/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapper.php @@ -6,7 +6,10 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueMapper\AkbankPosResponseValueMapper; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; use Mews\Pos\PosInterface; /** @@ -27,35 +30,17 @@ class AkbankPosResponseDataMapper extends AbstractResponseDataMapper ]; /** - * N: Normal - * S: Şüpheli - * V: İptal - * R: Reversal - * @var array + * @var AkbankPosResponseValueMapper */ - private array $orderStatusMappings = [ - 'N' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 'S' => PosInterface::PAYMENT_STATUS_ERROR, - 'V' => PosInterface::PAYMENT_STATUS_CANCELED, - 'R' => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, - - // status that are return on history request - 'Başarılı' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 'Başarısız' => PosInterface::PAYMENT_STATUS_ERROR, - 'İptal' => PosInterface::PAYMENT_STATUS_CANCELED, - ]; + protected ResponseValueMapperInterface $valueMapper; /** - * @var array + * @inheritDoc */ - private array $recurringOrderStatusMappings = [ - 'S' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 'W' => PosInterface::PAYMENT_STATUS_PAYMENT_PENDING, - // when fulfilled payment is canceled - 'V' => PosInterface::PAYMENT_STATUS_CANCELED, - // when unfulfilled payment is canceled - 'C' => PosInterface::PAYMENT_STATUS_CANCELED, - ]; + public static function supports(string $gatewayClass): bool + { + return AkbankPos::class === $gatewayClass; + } /** * {@inheritDoc} @@ -79,12 +64,12 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $mappedResponse = [ 'recurring_id' => $rawPaymentResponseData['order']['orderTrackId'] ?? null, - 'transaction_type' => $this->mapTxType($rawPaymentResponseData['txnCode']), + 'transaction_type' => $this->valueMapper->mapTxType($rawPaymentResponseData['txnCode']), 'currency' => $order['currency'], 'amount' => $order['amount'], 'installment_count' => isset($rawPaymentResponseData['order']['orderTrackId']) ? null : $order['installment'] ?? null, 'transaction_id' => null, - 'transaction_time' => self::TX_APPROVED === $status ? new \DateTimeImmutable($rawPaymentResponseData['txnDateTime']) : null, + 'transaction_time' => self::TX_APPROVED === $status ? $this->valueFormatter->formatDateTime($rawPaymentResponseData['txnDateTime'], $txType) : null, 'proc_return_code' => $procReturnCode, 'status' => $status, 'status_detail' => $this->getStatusDetail($procReturnCode), @@ -165,7 +150,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $defaultResponse['installment_count'] = $order['installment']; if (self::TX_APPROVED === $status) { - $defaultResponse['transaction_time'] = new \DateTimeImmutable($raw3DAuthResponseData['txnDateTime']); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime($raw3DAuthResponseData['txnDateTime'], $txType); $defaultResponse['auth_code'] = $raw3DAuthResponseData['authCode']; $defaultResponse['batch_num'] = (int) $raw3DAuthResponseData['batchNumber']; $defaultResponse['ref_ret_num'] = $raw3DAuthResponseData['rrn']; @@ -405,27 +390,6 @@ protected function getProcReturnCode(array $response): ?string return $response['responseCode'] ?? null; } - /** - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return (float) $amount; - } - - /** - * @param string|null $installment - * - * @return int - */ - protected function mapInstallment(?string $installment): int - { - return $installment > 1 ? (int) $installment : 0; - } - - /** * @param array $rawTx * @@ -433,6 +397,7 @@ protected function mapInstallment(?string $installment): int */ private function mapSingleOrderHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_ORDER_HISTORY; $rawTx = $this->emptyStringsToNull($rawTx); $transaction = $this->getDefaultOrderHistoryTxResponse(); $transaction['proc_return_code'] = $this->getProcReturnCode($rawTx); @@ -441,39 +406,39 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array } $transaction['status_detail'] = $this->getStatusDetail($transaction['proc_return_code']); - $transaction['currency'] = $this->mapCurrency($rawTx['currencyCode']); - $transaction['installment_count'] = $this->mapInstallment($rawTx['installCount']); - $transaction['transaction_type'] = $this->mapTxType($rawTx['txnCode']); - $transaction['first_amount'] = null === $rawTx['amount'] ? null : $this->formatAmount($rawTx['amount']); - $transaction['transaction_time'] = new \DateTimeImmutable($rawTx['txnDateTime']); + $transaction['currency'] = $this->valueMapper->mapCurrency($rawTx['currencyCode'], $txType); + $transaction['installment_count'] = $this->valueFormatter->formatInstallment($rawTx['installCount'], $txType); + $transaction['transaction_type'] = $this->valueMapper->mapTxType($rawTx['txnCode']); + $transaction['first_amount'] = null === $rawTx['amount'] ? null : $this->valueFormatter->formatAmount($rawTx['amount'], $txType); + $transaction['transaction_time'] = $this->valueFormatter->formatDateTime($rawTx['txnDateTime'], $txType); if (self::TX_APPROVED === $transaction['status']) { $transaction['masked_number'] = $rawTx['maskedCardNumber']; $transaction['ref_ret_num'] = $rawTx['rrn']; // batchNumber is not provided when payment is canceled $transaction['batch_num'] = $rawTx['batchNumber'] ?? null; - $transaction['order_status'] = $this->mapOrderStatus($rawTx['txnStatus'], $rawTx['preAuthStatus'] ?? null); + $transaction['order_status'] = $this->valueMapper->mapOrderStatus($rawTx['txnStatus'], $rawTx['preAuthStatus'] ?? null); $transaction['auth_code'] = $rawTx['authCode']; if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $transaction['order_status']) { if (\in_array( $transaction['transaction_type'], [ - PosInterface::TX_TYPE_PAY_AUTH, - PosInterface::TX_TYPE_PAY_POST_AUTH, - ], + PosInterface::TX_TYPE_PAY_AUTH, + PosInterface::TX_TYPE_PAY_POST_AUTH, + ], true, ) ) { - $transaction['capture_amount'] = null === $rawTx['amount'] ? null : $this->formatAmount($rawTx['amount']); + $transaction['capture_amount'] = null === $rawTx['amount'] ? null : $this->valueFormatter->formatAmount($rawTx['amount'], $txType); $transaction['capture'] = $transaction['first_amount'] === $transaction['capture_amount']; if ($transaction['capture']) { - $transaction['capture_time'] = new \DateTimeImmutable($rawTx['txnDateTime']); + $transaction['capture_time'] = $this->valueFormatter->formatDateTime($rawTx['txnDateTime'], $txType); } } elseif (PosInterface::TX_TYPE_PAY_PRE_AUTH === $transaction['transaction_type']) { - $transaction['capture_amount'] = null === $rawTx['preAuthCloseAmount'] ? null : $this->formatAmount($rawTx['preAuthCloseAmount']); + $transaction['capture_amount'] = null === $rawTx['preAuthCloseAmount'] ? null : $this->valueFormatter->formatAmount($rawTx['preAuthCloseAmount'], $txType); $transaction['capture'] = $transaction['first_amount'] === $transaction['capture_amount']; if ($transaction['capture']) { - $transaction['capture_time'] = new \DateTimeImmutable($rawTx['preAuthCloseDate']); + $transaction['capture_time'] = $this->valueFormatter->formatDateTime($rawTx['preAuthCloseDate'], $txType); } } } @@ -491,10 +456,11 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array */ private function mapSingleRecurringOrderHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_ORDER_HISTORY; $rawTx = $this->emptyStringsToNull($rawTx); $transaction = $this->getDefaultOrderHistoryTxResponse(); $transaction['proc_return_code'] = $this->getProcReturnCode($rawTx); - $transaction['order_status'] = $this->mapRecurringOrderStatus($rawTx['requestStatus']); + $transaction['order_status'] = $this->valueMapper->mapOrderStatus($rawTx['requestStatus'], null, true); if (null === $transaction['proc_return_code']) { // no proc return code since this is the pending payment $transaction['status'] = null; @@ -505,23 +471,23 @@ private function mapSingleRecurringOrderHistoryTransaction(array $rawTx): array $transaction['status_detail'] = $this->getStatusDetail($transaction['proc_return_code']); $transaction['recurring_order'] = $rawTx['recurringOrder']; $transaction['masked_number'] = $rawTx['maskedCardNumber']; - $transaction['currency'] = $this->mapCurrency($rawTx['currencyCode']); - $transaction['installment_count'] = $this->mapInstallment($rawTx['installCount']); - $transaction['transaction_type'] = $this->mapTxType($rawTx['txnCode']); - $transaction['first_amount'] = null === $rawTx['amount'] ? null : $this->formatAmount($rawTx['amount']); + $transaction['currency'] = $this->valueMapper->mapCurrency($rawTx['currencyCode'], $txType); + $transaction['installment_count'] = $this->valueFormatter->formatInstallment($rawTx['installCount'], $txType); + $transaction['transaction_type'] = $this->valueMapper->mapTxType($rawTx['txnCode']); + $transaction['first_amount'] = null === $rawTx['amount'] ? null : $this->valueFormatter->formatAmount($rawTx['amount'], $txType); if (self::TX_APPROVED === $transaction['status']) { $transaction['auth_code'] = $rawTx['authCode']; if (PosInterface::PAYMENT_STATUS_PAYMENT_PENDING !== $transaction['order_status']) { - $transaction['transaction_time'] = new \DateTimeImmutable($rawTx['txnDateTime']); + $transaction['transaction_time'] = $this->valueFormatter->formatDateTime($rawTx['txnDateTime'], $txType); } if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $transaction['order_status']) { $transaction['batch_num'] = $rawTx['batchNumber']; $transaction['ref_ret_num'] = $rawTx['rrn']; - $transaction['capture_amount'] = null === $rawTx['amount'] ? null : $this->formatAmount($rawTx['amount']); + $transaction['capture_amount'] = null === $rawTx['amount'] ? null : $this->valueFormatter->formatAmount($rawTx['amount'], $txType); $transaction['capture'] = $transaction['first_amount'] === $transaction['capture_amount']; - $transaction['capture_time'] = new \DateTimeImmutable($rawTx['txnDateTime']); + $transaction['capture_time'] = $this->valueFormatter->formatDateTime($rawTx['txnDateTime'], $txType); } } else { $transaction['error_code'] = $transaction['proc_return_code']; @@ -537,6 +503,7 @@ private function mapSingleRecurringOrderHistoryTransaction(array $rawTx): array */ private function mapSingleHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_HISTORY; $rawTx = $this->emptyStringsToNull($rawTx); $transaction = $this->getDefaultOrderHistoryTxResponse(); $transaction['proc_return_code'] = $this->getProcReturnCode($rawTx); @@ -547,11 +514,11 @@ private function mapSingleHistoryTransaction(array $rawTx): array $transaction['order_id'] = null; $transaction['status_detail'] = $this->getStatusDetail($transaction['proc_return_code']); - $transaction['currency'] = $this->mapCurrency($rawTx['currencyCode']); - $transaction['installment_count'] = $this->mapInstallment($rawTx['installmentCount']); - $transaction['transaction_type'] = $this->mapTxType($rawTx['txnCode']); - $transaction['first_amount'] = null === $rawTx['amount'] ? null : $this->formatAmount($rawTx['amount']); - $transaction['transaction_time'] = new \DateTimeImmutable($rawTx['txnDateTime']); + $transaction['currency'] = $this->valueMapper->mapCurrency($rawTx['currencyCode'], $txType); + $transaction['installment_count'] = $this->valueFormatter->formatInstallment($rawTx['installmentCount'], $txType); + $transaction['transaction_type'] = $this->valueMapper->mapTxType($rawTx['txnCode']); + $transaction['first_amount'] = null === $rawTx['amount'] ? null : $this->valueFormatter->formatAmount($rawTx['amount'], $txType); + $transaction['transaction_time'] = $this->valueFormatter->formatDateTime($rawTx['txnDateTime'], $txType); if (self::TX_APPROVED === $transaction['status']) { $transaction['order_id'] = $rawTx['orderId']; @@ -559,7 +526,7 @@ private function mapSingleHistoryTransaction(array $rawTx): array $transaction['ref_ret_num'] = $rawTx['rrn']; // batchNumber is not provided when payment is canceled $transaction['batch_num'] = $rawTx['batchNumber'] ?? null; - $transaction['order_status'] = $this->mapOrderStatus($rawTx['txnStatus'], $rawTx['preAuthStatus'] ?? null); + $transaction['order_status'] = $this->valueMapper->mapOrderStatus($rawTx['txnStatus'], $rawTx['preAuthStatus'] ?? null); $transaction['auth_code'] = $rawTx['authCode']; if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $transaction['order_status']) { if (\in_array( @@ -570,16 +537,16 @@ private function mapSingleHistoryTransaction(array $rawTx): array ], true, )) { - $transaction['capture_amount'] = null === $rawTx['amount'] ? null : $this->formatAmount($rawTx['amount']); + $transaction['capture_amount'] = null === $rawTx['amount'] ? null : $this->valueFormatter->formatAmount($rawTx['amount'], PosInterface::TX_TYPE_HISTORY); $transaction['capture'] = $transaction['first_amount'] === $transaction['capture_amount']; if ($transaction['capture']) { - $transaction['capture_time'] = new \DateTimeImmutable($rawTx['txnDateTime']); + $transaction['capture_time'] = $this->valueFormatter->formatDateTime($rawTx['txnDateTime'], $txType); } } elseif (PosInterface::TX_TYPE_PAY_PRE_AUTH === $transaction['transaction_type']) { - $transaction['capture_amount'] = null === $rawTx['preAuthCloseAmount'] ? null : $this->formatAmount($rawTx['preAuthCloseAmount']); + $transaction['capture_amount'] = null === $rawTx['preAuthCloseAmount'] ? null : $this->valueFormatter->formatAmount($rawTx['preAuthCloseAmount'], PosInterface::TX_TYPE_HISTORY); $transaction['capture'] = $transaction['first_amount'] === $transaction['capture_amount']; if ($transaction['capture']) { - $transaction['capture_time'] = new \DateTimeImmutable($rawTx['preAuthCloseDate']); + $transaction['capture_time'] = $this->valueFormatter->formatDateTime($rawTx['preAuthCloseDate'], $txType); } } } @@ -621,35 +588,4 @@ private function map3DResponseData(array $raw3DAuthResponseData, string $payment return $threeDResponse; } - - /** - * @param string $txStatus - * @param string|null $preAuthStatus - * - * @return string - */ - private function mapOrderStatus(string $txStatus, ?string $preAuthStatus): string - { - $orderStatus = $this->orderStatusMappings[$txStatus]; - /** - * preAuthStatus - * "O": Açık - * "C": Kapalı - */ - if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $orderStatus && 'O' === $preAuthStatus) { - return PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED; - } - - return $orderStatus; - } - - /** - * @param string $requestStatus - * - * @return string - */ - private function mapRecurringOrderStatus(string $requestStatus): string - { - return $this->recurringOrderStatusMappings[$requestStatus] ?? $requestStatus; - } } diff --git a/src/DataMapper/ResponseDataMapper/EstPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/EstPosResponseDataMapper.php index 511b2868..4cde4903 100644 --- a/src/DataMapper/ResponseDataMapper/EstPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/EstPosResponseDataMapper.php @@ -7,6 +7,8 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\EstPos; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; /** @@ -37,27 +39,12 @@ class EstPosResponseDataMapper extends AbstractResponseDataMapper ]; /** - * D : Başarısız işlem - * A : Otorizasyon, gün sonu kapanmadan - * C : Ön otorizasyon kapama, gün sonu kapanmadan - * PN : Bekleyen İşlem - * CNCL : İptal Edilmiş İşlem - * ERR : Hata Almış İşlem - * S : Satış - * R : Teknik İptal gerekiyor - * V : İptal - * @var array + * @inheritDoc */ - protected array $orderStatusMappings = [ - 'D' => PosInterface::PAYMENT_STATUS_ERROR, - 'ERR' => PosInterface::PAYMENT_STATUS_ERROR, - 'A' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 'C' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 'S' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 'PN' => PosInterface::PAYMENT_STATUS_PAYMENT_PENDING, - 'CNCL' => PosInterface::PAYMENT_STATUS_CANCELED, - 'V' => PosInterface::PAYMENT_STATUS_CANCELED, - ]; + public static function supports(string $gatewayClass): bool + { + return EstV3Pos::class === $gatewayClass || EstPos::class === $gatewayClass; + } /** * @param PaymentStatusModel $rawPaymentResponseData @@ -88,7 +75,7 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType 'amount' => $order['amount'], 'group_id' => $rawPaymentResponseData['GroupId'], 'transaction_id' => $rawPaymentResponseData['TransId'], - 'transaction_time' => self::TX_APPROVED === $status ? new \DateTimeImmutable($extra['TRXDATE']) : null, + 'transaction_time' => self::TX_APPROVED === $status ? $this->valueFormatter->formatDateTime($extra['TRXDATE'], $txType) : null, 'auth_code' => $rawPaymentResponseData['AuthCode'] ?? null, 'ref_ret_num' => $rawPaymentResponseData['HostRefNum'], 'proc_return_code' => $procReturnCode, @@ -116,7 +103,7 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'provision_response' => $rawPaymentResponseData, ]); $raw3DAuthResponseData = $this->emptyStringsToNull($raw3DAuthResponseData); - $paymentModel = $this->mapSecurityType($raw3DAuthResponseData['storetype']); + $paymentModel = $this->valueMapper->mapSecureType($raw3DAuthResponseData['storetype'], $txType); $paymentResponseData = $this->getDefaultPaymentResponse($txType, $paymentModel); $mdStatus = $this->extractMdStatus($raw3DAuthResponseData); if (null !== $rawPaymentResponseData) { @@ -130,9 +117,9 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'masked_number' => $raw3DAuthResponseData['maskedCreditCard'], 'month' => $raw3DAuthResponseData['Ecom_Payment_Card_ExpDate_Month'], 'year' => $raw3DAuthResponseData['Ecom_Payment_Card_ExpDate_Year'], - 'amount' => null !== $raw3DAuthResponseData['amount'] ? $this->formatAmount($raw3DAuthResponseData['amount']) : null, - 'currency' => '*' === $raw3DAuthResponseData['currency'] ? null : $this->mapCurrency($raw3DAuthResponseData['currency']), - 'installment_count' => $this->mapInstallment($raw3DAuthResponseData['taksit']), + 'amount' => null !== $raw3DAuthResponseData['amount'] ? $this->valueFormatter->formatAmount($raw3DAuthResponseData['amount'], $txType) : null, + 'currency' => $this->valueMapper->mapCurrency($raw3DAuthResponseData['currency'], $txType), + 'installment_count' => $this->valueFormatter->formatInstallment($raw3DAuthResponseData['taksit'], $txType), 'eci' => null, 'tx_status' => null, 'cavv' => null, @@ -174,7 +161,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $status = self::TX_APPROVED; } - $paymentModel = $this->mapSecurityType($raw3DAuthResponseData['storetype']); + $paymentModel = $this->valueMapper->mapSecureType($raw3DAuthResponseData['storetype'], $txType); $defaultResponse = $this->getDefaultPaymentResponse($txType, $paymentModel); $response = [ @@ -186,9 +173,9 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp 'masked_number' => $raw3DAuthResponseData['maskedCreditCard'], 'month' => $raw3DAuthResponseData['Ecom_Payment_Card_ExpDate_Month'], 'year' => $raw3DAuthResponseData['Ecom_Payment_Card_ExpDate_Year'], - 'amount' => $this->formatAmount($raw3DAuthResponseData['amount']), - 'currency' => $this->mapCurrency($raw3DAuthResponseData['currency']), - 'installment_count' => $this->mapInstallment($raw3DAuthResponseData['taksit']), + 'amount' => $this->valueFormatter->formatAmount($raw3DAuthResponseData['amount'], $txType), + 'currency' => $this->valueMapper->mapCurrency($raw3DAuthResponseData['currency'], $txType), + 'installment_count' => $this->valueFormatter->formatInstallment($raw3DAuthResponseData['taksit'], $txType), 'tx_status' => null, 'eci' => null, 'cavv' => null, @@ -201,7 +188,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $response['eci'] = $raw3DAuthResponseData['eci']; $response['cavv'] = $raw3DAuthResponseData['cavv']; $response['transaction_id'] = $raw3DAuthResponseData['TransId']; - $response['transaction_time'] = new \DateTimeImmutable($raw3DAuthResponseData['EXTRA_TRXDATE']); + $response['transaction_time'] = $this->valueFormatter->formatDateTime($raw3DAuthResponseData['EXTRA_TRXDATE'], $txType); $response['ref_ret_num'] = $raw3DAuthResponseData['HostRefNum']; $response['status_detail'] = $this->getStatusDetail($procReturnCode); $response['error_message'] = $raw3DAuthResponseData['ErrMsg']; @@ -223,7 +210,7 @@ public function map3DHostResponseData(array $raw3DAuthResponseData, string $txTy $status = self::TX_APPROVED; } - $paymentModel = $this->mapSecurityType($raw3DAuthResponseData['storetype']); + $paymentModel = $this->valueMapper->mapSecureType($raw3DAuthResponseData['storetype'], $txType); $defaultResponse = $this->getDefaultPaymentResponse($txType, $paymentModel); $response = [ @@ -231,9 +218,9 @@ public function map3DHostResponseData(array $raw3DAuthResponseData, string $txTy 'transaction_security' => null === $mdStatus ? null : $this->mapResponseTransactionSecurity($mdStatus), 'md_status' => $mdStatus, 'status' => $status, - 'amount' => $this->formatAmount($raw3DAuthResponseData['amount']), - 'currency' => $this->mapCurrency($raw3DAuthResponseData['currency']), - 'installment_count' => $this->mapInstallment($raw3DAuthResponseData['taksit']), + 'amount' => $this->valueFormatter->formatAmount($raw3DAuthResponseData['amount'], $txType), + 'currency' => $this->valueMapper->mapCurrency($raw3DAuthResponseData['currency'], $txType), + 'installment_count' => $this->valueFormatter->formatInstallment($raw3DAuthResponseData['taksit'], $txType), 'tx_status' => null, 'masked_number' => null, 'month' => null, @@ -251,7 +238,7 @@ public function map3DHostResponseData(array $raw3DAuthResponseData, string $txTy if (self::TX_APPROVED === $status) { $response['eci'] = $raw3DAuthResponseData['eci']; $response['cavv'] = $raw3DAuthResponseData['cavv']; - $response['transaction_time'] = new \DateTimeImmutable(); + $response['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } } @@ -357,6 +344,7 @@ public function mapCancelResponse(array $rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $procReturnCode = $this->getProcReturnCode($rawResponseData); $status = self::TX_DECLINED; @@ -383,17 +371,16 @@ public function mapStatusResponse(array $rawResponseData): array if (self::TX_APPROVED === $status) { $result['auth_code'] = $extra['AUTH_CODE']; $result['ref_ret_num'] = $extra['HOST_REF_NUM']; - $result['first_amount'] = $this->formatAmount($extra['ORIG_TRANS_AMT']); - $result['capture_amount'] = null !== $extra['CAPTURE_AMT'] ? $this->formatAmount($extra['CAPTURE_AMT']) : null; + $result['first_amount'] = $this->valueFormatter->formatAmount($extra['ORIG_TRANS_AMT'], $txType); + $result['capture_amount'] = null !== $extra['CAPTURE_AMT'] ? $this->valueFormatter->formatAmount($extra['CAPTURE_AMT'], $txType) : null; $result['masked_number'] = $extra['PAN']; $result['num_code'] = $extra['NUMCODE']; $result['capture'] = $result['first_amount'] === $result['capture_amount']; - $txType = 'S' === $extra['CHARGE_TYPE_CD'] ? PosInterface::TX_TYPE_PAY_AUTH : PosInterface::TX_TYPE_REFUND; - $result['transaction_type'] = $txType; - $result['order_status'] = $this->orderStatusMappings[$extra['TRANS_STAT']] ?? null; - $result['transaction_time'] = isset($extra['AUTH_DTTM']) ? new \DateTimeImmutable($extra['AUTH_DTTM']) : null; - $result['capture_time'] = isset($extra['CAPTURE_DTTM']) ? new \DateTimeImmutable($extra['CAPTURE_DTTM']) : null; - $result['cancel_time'] = isset($extra['VOID_DTTM']) ? new \DateTimeImmutable($extra['VOID_DTTM']) : null; + $result['transaction_type'] = $this->valueMapper->mapTxType($extra['CHARGE_TYPE_CD']); + $result['order_status'] = $this->valueMapper->mapOrderStatus($extra['TRANS_STAT']); + $result['transaction_time'] = isset($extra['AUTH_DTTM']) ? $this->valueFormatter->formatDateTime($extra['AUTH_DTTM'], $txType) : null; + $result['capture_time'] = isset($extra['CAPTURE_DTTM']) ? $this->valueFormatter->formatDateTime($extra['CAPTURE_DTTM'], $txType) : null; + $result['cancel_time'] = isset($extra['VOID_DTTM']) ? $this->valueFormatter->formatDateTime($extra['VOID_DTTM'], $txType) : null; } return $result; @@ -521,19 +508,6 @@ protected function getProcReturnCode(array $response): ?string return $response['ProcReturnCode'] ?? null; } - /** - * "100001" => 1000.01 odeme durum sorgulandiginda gelen amount format - * "1000.01" => 1000.01 odeme yapildiginda gelen amount format - * - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return ((float) \str_replace('.', '', $amount)) / 100; - } - /** * @param array $rawTx * @@ -541,6 +515,7 @@ protected function formatAmount(string $amount): float */ private function mapSingleOrderHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_ORDER_HISTORY; $rawTx = $this->emptyStringsToNull($rawTx); $transaction = $this->getDefaultOrderHistoryTxResponse(); $transaction['auth_code'] = $rawTx[8]; @@ -551,15 +526,12 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array $transaction['status_detail'] = $this->getStatusDetail($transaction['proc_return_code']); $transaction['transaction_id'] = $rawTx[10]; - /** - * S: Auth/PreAuth/PostAuth - * C: Refund - */ - $transaction['transaction_type'] = 'S' === $rawTx[0] ? PosInterface::TX_TYPE_PAY_AUTH : PosInterface::TX_TYPE_REFUND; - $transaction['order_status'] = $this->orderStatusMappings[$rawTx[1]] ?? null; - $transaction['transaction_time'] = new \DateTimeImmutable($rawTx[4]); - $transaction['first_amount'] = null === $rawTx[2] ? null : $this->formatAmount($rawTx[2]); - $transaction['capture_amount'] = null === $rawTx[3] ? null : $this->formatAmount($rawTx[3]); + + $transaction['transaction_type'] = $this->valueMapper->mapTxType($rawTx[0]); + $transaction['order_status'] = $this->valueMapper->mapOrderStatus($rawTx[1]); + $transaction['transaction_time'] = $this->valueFormatter->formatDateTime($rawTx[4], $txType); + $transaction['first_amount'] = null === $rawTx[2] ? null : $this->valueFormatter->formatAmount($rawTx[2], PosInterface::TX_TYPE_ORDER_HISTORY); + $transaction['capture_amount'] = null === $rawTx[3] ? null : $this->valueFormatter->formatAmount($rawTx[3], PosInterface::TX_TYPE_ORDER_HISTORY); $transaction['capture'] = self::TX_APPROVED === $transaction['status'] && $transaction['first_amount'] === $transaction['capture_amount']; $transaction['ref_ret_num'] = $rawTx[7]; @@ -574,6 +546,7 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array */ private function mapSingleRecurringOrderStatus(array $extra, int $i): array { + $txType = PosInterface::TX_TYPE_STATUS; $procReturnCode = $extra[\sprintf('PROC_RET_CD_%d', $i)] ?? null; $status = self::TX_DECLINED; if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { @@ -582,23 +555,32 @@ private function mapSingleRecurringOrderStatus(array $extra, int $i): array $status = null; } + $transStat = $extra[\sprintf('TRANS_STAT_%d', $i)]; + $chargeType = $extra[\sprintf('CHARGE_TYPE_CD_%d', $i)]; + $recurringOrder = [ 'order_id' => $extra[\sprintf('ORD_ID_%d', $i)], 'masked_number' => $extra[\sprintf('PAN_%d', $i)], - 'order_status' => $this->orderStatusMappings[$extra[\sprintf('TRANS_STAT_%d', $i)]] ?? null, + 'order_status' => null === $transStat ? null : $this->valueMapper->mapOrderStatus($transStat), // following fields are null until transaction is done for respective installment: 'auth_code' => $extra[\sprintf('AUTH_CODE_%d', $i)] ?? null, 'proc_return_code' => $procReturnCode, - 'transaction_type' => 'S' === $extra[\sprintf('CHARGE_TYPE_CD_%d', $i)] ? PosInterface::TX_TYPE_PAY_AUTH : PosInterface::TX_TYPE_REFUND, + 'transaction_type' => null === $chargeType ? null : $this->valueMapper->mapTxType($chargeType), 'status' => $status, 'status_detail' => $this->getStatusDetail($procReturnCode), - 'transaction_time' => isset($extra[\sprintf('AUTH_DTTM_%d', $i)]) ? new \DateTimeImmutable($extra[\sprintf('AUTH_DTTM_%d', $i)]) : null, - 'capture_time' => isset($extra[\sprintf('CAPTURE_DTTM_%d', $i)]) ? new \DateTimeImmutable($extra[\sprintf('CAPTURE_DTTM_%d', $i)]) : null, + 'transaction_time' => isset($extra[\sprintf('AUTH_DTTM_%d', $i)]) ? $this->valueFormatter->formatDateTime($extra[\sprintf('AUTH_DTTM_%d', $i)], $txType) : null, + 'capture_time' => isset($extra[\sprintf('CAPTURE_DTTM_%d', $i)]) ? $this->valueFormatter->formatDateTime($extra[\sprintf('CAPTURE_DTTM_%d', $i)], $txType) : null, 'transaction_id' => $extra[\sprintf('TRANS_ID_%d', $i)] ?? null, 'ref_ret_num' => $extra[\sprintf('HOST_REF_NUM_%d', $i)] ?? null, - 'first_amount' => isset($extra[\sprintf('ORIG_TRANS_AMT_%d', $i)]) ? $this->formatAmount($extra[\sprintf('ORIG_TRANS_AMT_%d', $i)]) : null, - 'capture_amount' => isset($extra[\sprintf('CAPTURE_AMT_%d', $i)]) ? $this->formatAmount($extra[\sprintf('CAPTURE_AMT_%d', $i)]) : null, + 'first_amount' => isset($extra[\sprintf('ORIG_TRANS_AMT_%d', $i)]) ? $this->valueFormatter->formatAmount( + $extra[\sprintf('ORIG_TRANS_AMT_%d', $i)], + $txType + ) : null, + 'capture_amount' => isset($extra[\sprintf('CAPTURE_AMT_%d', $i)]) ? $this->valueFormatter->formatAmount( + $extra[\sprintf('CAPTURE_AMT_%d', $i)], + $txType + ) : null, ]; diff --git a/src/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapper.php index 91361430..bca2fe9e 100644 --- a/src/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapper.php @@ -6,7 +6,10 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueMapper\GarantiPosResponseValueMapper; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\GarantiPos; use Mews\Pos\PosInterface; /** @@ -14,6 +17,11 @@ */ class GarantiPosResponseDataMapper extends AbstractResponseDataMapper { + /** + * @var GarantiPosResponseValueMapper + */ + protected ResponseValueMapperInterface $valueMapper; + /** * Response Codes * @@ -38,6 +46,14 @@ class GarantiPosResponseDataMapper extends AbstractResponseDataMapper '99' => 'general_error', ]; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return GarantiPos::class === $gatewayClass; + } + /** * @param PaymentStatusModel $rawPaymentResponseData * {@inheritDoc} @@ -65,7 +81,7 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType 'auth_code' => self::TX_APPROVED === $status ? $transaction['AuthCode'] : null, 'ref_ret_num' => self::TX_APPROVED === $status ? $transaction['RetrefNum'] : null, 'batch_num' => self::TX_APPROVED === $status ? $transaction['BatchNum'] : null, - 'transaction_time' => self::TX_APPROVED === $status ? new \DateTimeImmutable($provDate) : null, + 'transaction_time' => self::TX_APPROVED === $status ? $this->valueFormatter->formatDateTime($provDate, $txType) : null, 'proc_return_code' => $procReturnCode, 'status' => $status, 'currency' => $order['currency'], @@ -95,7 +111,11 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'provision_response' => $rawPaymentResponseData, ]); - $commonResult = $this->map3DCommonResponseData($raw3DAuthResponseData, PosInterface::MODEL_3D_SECURE); + $commonResult = $this->map3DCommonResponseData( + $raw3DAuthResponseData, + PosInterface::MODEL_3D_SECURE, + $txType + ); $mdStatus = $this->extractMdStatus($raw3DAuthResponseData); // todo refactor if ($this->is3dAuthSuccess($mdStatus)) { @@ -110,7 +130,7 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen } $paymentStatus = self::TX_DECLINED; - $paymentModel = $this->mapSecurityType($raw3DAuthResponseData['secure3dsecuritylevel']); + $paymentModel = $this->valueMapper->mapSecureType($raw3DAuthResponseData['secure3dsecuritylevel'], $txType); $defaultPaymentResponse = $this->getDefaultPaymentResponse($txType, $paymentModel); $mappedPaymentResponse = []; if (self::TX_APPROVED === $commonResult['status'] && null !== $rawPaymentResponseData) { @@ -128,7 +148,7 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'auth_code' => $transaction['AuthCode'] ?? null, 'ref_ret_num' => $transaction['RetrefNum'] ?? null, 'batch_num' => $transaction['BatchNum'] ?? null, - 'transaction_time' => self::TX_APPROVED === $paymentStatus ? new \DateTimeImmutable($provDate) : null, + 'transaction_time' => self::TX_APPROVED === $paymentStatus ? $this->valueFormatter->formatDateTime($provDate, $txType) : null, 'error_code' => self::TX_APPROVED === $paymentStatus ? null : $transaction['Response']['ReasonCode'], 'error_message' => self::TX_APPROVED === $paymentStatus ? null : $transaction['Response']['ErrorMsg'], 'all' => $rawPaymentResponseData, @@ -154,7 +174,11 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp { $raw3DAuthResponseData = $this->emptyStringsToNull($raw3DAuthResponseData); - $threeDAuthResult = $this->map3DCommonResponseData($raw3DAuthResponseData, PosInterface::MODEL_3D_PAY); + $threeDAuthResult = $this->map3DCommonResponseData( + $raw3DAuthResponseData, + PosInterface::MODEL_3D_PAY, + $txType + ); $threeDAuthStatus = $threeDAuthResult['status']; $paymentStatus = self::TX_DECLINED; $procReturnCode = $raw3DAuthResponseData['procreturncode']; @@ -162,7 +186,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $paymentStatus = self::TX_APPROVED; } - $paymentModel = $this->mapSecurityType($raw3DAuthResponseData['secure3dsecuritylevel']); + $paymentModel = $this->valueMapper->mapSecureType($raw3DAuthResponseData['secure3dsecuritylevel'], $txType); /** @var PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType */ $txType = $threeDAuthResult['transaction_type'] ?? $txType; $defaultPaymentResponse = $this->getDefaultPaymentResponse( @@ -186,7 +210,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $defaultPaymentResponse['error_message'] = $raw3DAuthResponseData['errmsg']; $defaultPaymentResponse['error_code'] = $procReturnCode; } else { - $defaultPaymentResponse['transaction_time'] = new \DateTimeImmutable(); + $defaultPaymentResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } return $this->mergeArraysPreferNonNullValues($threeDAuthResult, $defaultPaymentResponse); @@ -250,6 +274,7 @@ public function mapStatusResponse(array $rawResponseData): array $rawResponseData = $this->emptyStringsToNull($rawResponseData); $procReturnCode = $this->getProcReturnCode($rawResponseData); $status = self::TX_DECLINED; + $txType = PosInterface::TX_TYPE_STATUS; if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { $status = self::TX_APPROVED; } @@ -260,18 +285,13 @@ public function mapStatusResponse(array $rawResponseData): array $orderInqResult = $rawResponseData['Order']['OrderInqResult']; $defaultResponse = $this->getDefaultStatusResponse($rawResponseData); - $orderStatus = $orderInqResult['Status']; - if ('WAITINGPOSTAUTH' === $orderInqResult['Status']) { - $orderStatus = PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED; - } - $result = [ 'order_id' => $rawResponseData['Order']['OrderID'] ?? null, 'auth_code' => $orderInqResult['AuthCode'] ?? null, 'ref_ret_num' => $orderInqResult['RetrefNum'] ?? null, - 'installment_count' => $this->mapInstallment($orderInqResult['InstallmentCnt']), + 'installment_count' => $this->valueFormatter->formatInstallment($orderInqResult['InstallmentCnt'], $txType), 'proc_return_code' => $procReturnCode, - 'order_status' => $orderStatus, + 'order_status' => null !== $orderInqResult['Status'] ? $this->valueMapper->mapOrderStatus($orderInqResult['Status'], $txType) : null, 'status' => $status, 'status_detail' => $this->getStatusDetail($procReturnCode), 'error_code' => self::TX_APPROVED === $status ? null : $transaction['Response']['Code'], @@ -279,13 +299,13 @@ public function mapStatusResponse(array $rawResponseData): array ]; if (self::TX_APPROVED === $status) { $transTime = $orderInqResult['ProvDate'] ?? $orderInqResult['PreAuthDate']; - $result['transaction_time'] = $transTime === null ? null : new \DateTimeImmutable($transTime); - $result['capture_time'] = null !== $orderInqResult['AuthDate'] ? new \DateTimeImmutable($orderInqResult['AuthDate']) : null; + $result['transaction_time'] = $transTime === null ? null : $this->valueFormatter->formatDateTime($transTime, $txType); + $result['capture_time'] = null !== $orderInqResult['AuthDate'] ? $this->valueFormatter->formatDateTime($orderInqResult['AuthDate'], $txType) : null; $result['masked_number'] = $orderInqResult['CardNumberMasked']; $amount = $orderInqResult['AuthAmount']; - $result['capture_amount'] = null !== $amount ? $this->formatAmount($amount) : null; + $result['capture_amount'] = null !== $amount ? $this->valueFormatter->formatAmount($amount, $txType) : null; $firstAmount = $amount > 0 ? $amount : $orderInqResult['PreAuthAmount']; - $result['first_amount'] = null !== $firstAmount ? $this->formatAmount($firstAmount) : null; + $result['first_amount'] = null !== $firstAmount ? $this->valueFormatter->formatAmount($firstAmount, $txType) : null; $result['capture'] = $result['first_amount'] > 0 ? $result['capture_amount'] === $result['first_amount'] : null; } @@ -383,44 +403,16 @@ public function extractMdStatus(array $raw3DAuthResponseData): ?string return $raw3DAuthResponseData['mdstatus'] ?? null; } - /** - * @inheritDoc - */ - public function mapTxType($txType): ?string - { - $historyResponseTxTypes = [ - 'Satis' => PosInterface::TX_TYPE_PAY_AUTH, - 'On Otorizasyon' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'On Otorizasyon Kapama' => PosInterface::TX_TYPE_PAY_POST_AUTH, - 'Iade' => PosInterface::TX_TYPE_REFUND, - 'Iptal' => PosInterface::TX_TYPE_CANCEL, - // ... Odul Sorgulama - ]; - - return $historyResponseTxTypes[$txType] ?? parent::mapTxType($txType); - } - - /** - * 100001 => 1000.01 - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return ((float) $amount) / 100; - } - /** * returns mapped data of the common response data among all 3d models. - * @phpstan-param PosInterface::MODEL_3D_* $paymentModel * - * @param array $raw3DAuthResponseData - * @param string $paymentModel + * @param array $raw3DAuthResponseData + * @param PosInterface::MODEL_3D_* $paymentModel + * @param PosInterface::TX_TYPE_PAY_* $txType * * @return array */ - protected function map3DCommonResponseData(array $raw3DAuthResponseData, string $paymentModel): array + protected function map3DCommonResponseData(array $raw3DAuthResponseData, string $paymentModel, string $txType): array { $procReturnCode = $raw3DAuthResponseData['procreturncode']; $mdStatus = $this->extractMdStatus($raw3DAuthResponseData); @@ -437,15 +429,15 @@ protected function map3DCommonResponseData(array $raw3DAuthResponseData, string 'auth_code' => null, 'ref_ret_num' => null, 'transaction_security' => null === $mdStatus ? null : $this->mapResponseTransactionSecurity($mdStatus), - 'transaction_type' => $this->mapTxType($raw3DAuthResponseData['txntype']), + 'transaction_type' => $this->valueMapper->mapTxType($raw3DAuthResponseData['txntype']), 'proc_return_code' => $procReturnCode, 'md_status' => $mdStatus, 'status' => $status, 'status_detail' => $this->getStatusDetail($procReturnCode), 'masked_number' => null, - 'amount' => $this->formatAmount($raw3DAuthResponseData['txnamount']), - 'currency' => $this->mapCurrency($raw3DAuthResponseData['txncurrencycode']), - 'installment_count' => $this->mapInstallment($raw3DAuthResponseData['txninstallmentcount']), + 'amount' => $this->valueFormatter->formatAmount($raw3DAuthResponseData['txnamount'], $txType), + 'currency' => $this->valueMapper->mapCurrency($raw3DAuthResponseData['txncurrencycode'], $txType), + 'installment_count' => $this->valueFormatter->formatInstallment($raw3DAuthResponseData['txninstallmentcount'], $txType), 'tx_status' => null, 'eci' => null, 'cavv' => null, @@ -495,40 +487,6 @@ protected function getProcReturnCode(array $response): ?string return $response['Transaction']['Response']['Code'] ?? null; } - /** - * @inheritDoc - */ - protected function mapCurrency(string $currency): string - { - $historyResponseCurrencyMapping = [ - 'TL' => PosInterface::CURRENCY_TRY, - 'USD' => PosInterface::CURRENCY_USD, - 'EUR' => PosInterface::CURRENCY_EUR, - 'RUB' => PosInterface::CURRENCY_RUB, - 'JPY' => PosInterface::CURRENCY_JPY, - 'GBP' => PosInterface::CURRENCY_GBP, - ]; - - return $historyResponseCurrencyMapping[$currency] ?? parent::mapCurrency($currency); - } - - /** - * @inheritDoc - */ - protected function mapInstallment(?string $installment): int - { - if (null === $installment) { - return 0; - } - - // history response - if ('Pesin' === $installment || '1' === $installment) { - return 0; - } - - return parent::mapInstallment($installment); - } - /** * @param array $rawTx * @@ -536,6 +494,7 @@ protected function mapInstallment(?string $installment): int */ private function mapSingleOrderHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_ORDER_HISTORY; $procReturnCode = $rawTx['Status']; $status = self::TX_DECLINED; if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { @@ -549,18 +508,21 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array $defaultResponse['status'] = $status; $defaultResponse['status_detail'] = $this->getStatusDetail($procReturnCode); $defaultResponse['error_code'] = self::TX_APPROVED === $status ? null : $procReturnCode; - $defaultResponse['transaction_type'] = $rawTx['Type'] === null ? null : $this->mapTxType($rawTx['Type']); + $defaultResponse['transaction_type'] = $rawTx['Type'] === null ? null : $this->valueMapper->mapTxType($rawTx['Type']); if (self::TX_APPROVED === $status) { - $transTime = $rawTx['ProvDate'] ?? $rawTx['PreAuthDate'] ?? $rawTx['AuthDate']; - $defaultResponse['transaction_time'] = new \DateTimeImmutable($transTime.'T000000'); - $defaultResponse['capture_time'] = null !== $rawTx['AuthDate'] ? new \DateTimeImmutable($rawTx['AuthDate'].'T000000') : null; + $transTime = $rawTx['ProvDate'] ?? $rawTx['PreAuthDate'] ?? $rawTx['AuthDate']; + if (null !== $transTime) { + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime($transTime, $txType); + } + + $defaultResponse['capture_time'] = null !== $rawTx['AuthDate'] ? $this->valueFormatter->formatDateTime($rawTx['AuthDate'], $txType) : null; $amount = $rawTx['AuthAmount']; - $defaultResponse['capture_amount'] = null !== $amount ? $this->formatAmount($amount) : null; + $defaultResponse['capture_amount'] = null !== $amount ? $this->valueFormatter->formatAmount($amount, $txType) : null; $firstAmount = $amount > 0 ? $amount : $rawTx['PreAuthAmount']; - $defaultResponse['first_amount'] = null !== $firstAmount ? $this->formatAmount($firstAmount) : null; + $defaultResponse['first_amount'] = null !== $firstAmount ? $this->valueFormatter->formatAmount($firstAmount, $txType) : null; $defaultResponse['capture'] = $defaultResponse['first_amount'] > 0 ? $defaultResponse['capture_amount'] === $defaultResponse['first_amount'] : null; - $defaultResponse['currency'] = '0' !== $rawTx['CurrencyCode'] && null !== $rawTx['CurrencyCode'] ? $this->mapCurrency($rawTx['CurrencyCode']) : null; + $defaultResponse['currency'] = '0' !== $rawTx['CurrencyCode'] && null !== $rawTx['CurrencyCode'] ? $this->valueMapper->mapCurrency($rawTx['CurrencyCode'], $txType) : null; } return $defaultResponse; @@ -573,6 +535,7 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array */ private function mapSingleHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_HISTORY; $procReturnCode = $rawTx['ResponseCode']; $status = self::TX_DECLINED; if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { @@ -585,23 +548,20 @@ private function mapSingleHistoryTransaction(array $rawTx): array $defaultResponse['order_id'] = $rawTx['OrderID']; $defaultResponse['batch_num'] = $rawTx['BatchNum']; $defaultResponse['proc_return_code'] = $procReturnCode; - $defaultResponse['transaction_type'] = null !== $rawTx['TrxType'] ? $this->mapTxType($rawTx['TrxType']) : null; - $defaultResponse['order_status'] = null !== $rawTx['Status'] ? $this->mapHistoryOrderStatus($rawTx['Status'], $defaultResponse['transaction_type']) : null; + $defaultResponse['transaction_type'] = null !== $rawTx['TrxType'] ? $this->valueMapper->mapTxType($rawTx['TrxType']) : null; + $defaultResponse['order_status'] = null !== $rawTx['Status'] ? $this->valueMapper->mapOrderStatus($rawTx['Status'], $txType, $defaultResponse['transaction_type']) : null; $defaultResponse['status'] = $status; $defaultResponse['status_detail'] = $this->getStatusDetail($procReturnCode); $defaultResponse['error_code'] = self::TX_APPROVED === $status ? null : $procReturnCode; $defaultResponse['error_message'] = self::TX_APPROVED === $status ? null : $rawTx['SysErrMsg']; - // 3D Secure => 3D - // 3D Pay => 3D - // NonSecure => '' - $defaultResponse['payment_model'] = '3D' === $rawTx['SafeType'] ? PosInterface::MODEL_3D_SECURE : PosInterface::MODEL_NON_SECURE; - $defaultResponse['transaction_time'] = null !== $rawTx['LastTrxDate'] ? new \DateTimeImmutable($rawTx['LastTrxDate']) : null; + $defaultResponse['payment_model'] = $this->valueMapper->mapSecureType($rawTx['SafeType'] ?? '', $txType); + $defaultResponse['transaction_time'] = null !== $rawTx['LastTrxDate'] ? $this->valueFormatter->formatDateTime($rawTx['LastTrxDate'], $txType) : null; if (self::TX_APPROVED === $status) { $defaultResponse['masked_number'] = $rawTx['CardNumberMasked']; - $defaultResponse['installment_count'] = $this->mapInstallment($rawTx['InstallmentCnt']); - $defaultResponse['currency'] = null !== $rawTx['CurrencyCode'] ? $this->mapCurrency($rawTx['CurrencyCode']) : null; - $defaultResponse['first_amount'] = null !== $rawTx['AuthAmount'] ? $this->formatAmount($rawTx['AuthAmount']) : null; + $defaultResponse['installment_count'] = $this->valueFormatter->formatInstallment($rawTx['InstallmentCnt'], $txType); + $defaultResponse['currency'] = null !== $rawTx['CurrencyCode'] ? $this->valueMapper->mapCurrency($rawTx['CurrencyCode'], $txType) : null; + $defaultResponse['first_amount'] = null !== $rawTx['AuthAmount'] ? $this->valueFormatter->formatAmount($rawTx['AuthAmount'], $txType) : null; if ($defaultResponse['order_status'] === PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED) { $defaultResponse['capture_amount'] = $defaultResponse['first_amount']; $defaultResponse['capture'] = $defaultResponse['first_amount'] > 0 ? $defaultResponse['capture_amount'] === $defaultResponse['first_amount'] : null; @@ -611,56 +571,4 @@ private function mapSingleHistoryTransaction(array $rawTx): array return $defaultResponse; } - - /** - * todo anlasilmayan durumlar: - * - "Status" => "Iptal", "TrxType" => "Satis" - * - "Status" => "Iptal", "TrxType" => "On Otorizasyon" - * - "Status" => "Iptal", "TrxType" => "Iptal" - * - "Status" => "Iptal", "TrxType" => "Iade" - * - * @param string $txStatus - * @param PosInterface::TX_TYPE_*|null $txType - * - * @return string|null - */ - private function mapHistoryOrderStatus(string $txStatus, ?string $txType): ?string - { - if (null === $txType) { - return null; - } - - // txStatus possible values: - // Basarili - // Basarisiz - // Iptal - // Onaylandi - - if ('Basarili' === $txStatus || 'Onaylandi' === $txStatus) { - if (PosInterface::TX_TYPE_CANCEL === $txType) { - return PosInterface::PAYMENT_STATUS_CANCELED; - } - - if (PosInterface::TX_TYPE_REFUND === $txType) { - // todo how can we decide if order is partially or fully refunded? - return PosInterface::PAYMENT_STATUS_FULLY_REFUNDED; - } - - if (PosInterface::TX_TYPE_PAY_AUTH === $txType || PosInterface::TX_TYPE_PAY_POST_AUTH === $txType) { - return PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED; - } - - if (PosInterface::TX_TYPE_PAY_PRE_AUTH === $txType) { - return PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED; - } - - return null; - } - - if ('Iptal' === $txStatus) { - return null; - } - - return PosInterface::PAYMENT_STATUS_ERROR; - } } diff --git a/src/DataMapper/ResponseDataMapper/InterPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/InterPosResponseDataMapper.php index 46ce2eec..053d3785 100644 --- a/src/DataMapper/ResponseDataMapper/InterPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/InterPosResponseDataMapper.php @@ -7,6 +7,7 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\InterPos; use Mews\Pos\PosInterface; class InterPosResponseDataMapper extends AbstractResponseDataMapper @@ -23,6 +24,14 @@ class InterPosResponseDataMapper extends AbstractResponseDataMapper 'E39' => 'invalid_transaction', ]; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return InterPos::class === $gatewayClass; + } + /** * {@inheritDoc} */ @@ -55,7 +64,7 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $result['all'] = $rawPaymentResponseData; if (self::TX_APPROVED === $status) { - $result['transaction_time'] = new \DateTimeImmutable($rawPaymentResponseData['TRXDATE'] ?? null); + $result['transaction_time'] = $this->valueFormatter->formatDateTime($rawPaymentResponseData['TRXDATE'] ?? 'now', $txType); } $this->logger->debug('mapped payment response', $result); @@ -142,6 +151,7 @@ public function mapCancelResponse($rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $procReturnCode = $this->getProcReturnCode($rawResponseData); $status = self::TX_DECLINED; @@ -158,7 +168,7 @@ public function mapStatusResponse(array $rawResponseData): array $defaultResponse['transaction_id'] = $rawResponseData['TransId']; $defaultResponse['error_code'] = self::TX_APPROVED !== $status ? $procReturnCode : null; $defaultResponse['error_message'] = self::TX_APPROVED !== $status ? $rawResponseData['ErrorMessage'] : null; - $defaultResponse['refund_amount'] = $rawResponseData['RefundedAmount'] > 0 ? $this->formatAmount($rawResponseData['RefundedAmount']) : null; + $defaultResponse['refund_amount'] = $rawResponseData['RefundedAmount'] > 0 ? $this->valueFormatter->formatAmount($rawResponseData['RefundedAmount'], $txType) : null; // todo success cevap ornegi bulundugunda guncellenecek: $defaultResponse['order_status'] = null; @@ -166,7 +176,7 @@ public function mapStatusResponse(array $rawResponseData): array $defaultResponse['capture'] = null; if ('' !== $rawResponseData['VoidDate'] && '1.1.0001 00:00:00' !== $rawResponseData['VoidDate']) { - $defaultResponse['cancel_time'] = new \DateTimeImmutable($rawResponseData['VoidDate']); + $defaultResponse['cancel_time'] = $this->valueFormatter->formatDateTime($rawResponseData['VoidDate'], $txType); } return $defaultResponse; @@ -234,18 +244,6 @@ protected function getProcReturnCode(array $response): ?string return $response['ProcReturnCode'] ?? null; } - /** - * 0 => 0.0 - * 1.056,2 => 1056.2 - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return (float) \str_replace(',', '.', \str_replace('.', '', $amount)); - } - /** * @phpstan-param PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType * @phpstan-param PosInterface::MODEL_3D_* $paymentModel @@ -283,7 +281,7 @@ private function map3DPaymentResponse(?array $rawPaymentResponseData, string $tx $result['all'] = $rawPaymentResponseData; if (self::TX_APPROVED === $result['status']) { - $result['transaction_time'] = new \DateTimeImmutable($rawPaymentResponseData['TRXDATE']); + $result['transaction_time'] = $this->valueFormatter->formatDateTime($rawPaymentResponseData['TRXDATE'], $txType); } $this->logger->debug('mapped payment response', $result); @@ -327,9 +325,9 @@ private function map3DCommonResponseData(array $raw3DAuthResponseData, ?array $r 'masked_number' => $raw3DAuthResponseData['Pan'], 'month' => null, 'year' => null, - 'amount' => $this->formatAmount($raw3DAuthResponseData['PurchAmount']), - 'currency' => $this->mapCurrency($raw3DAuthResponseData['Currency']), - 'transaction_time' => !isset($paymentResponseData['transaction_time']) && isset($raw3DAuthResponseData['TRXDATE']) ? new \DateTimeImmutable($raw3DAuthResponseData['TRXDATE']) : null, + 'amount' => $this->valueFormatter->formatAmount($raw3DAuthResponseData['PurchAmount'], $txType), + 'currency' => $this->valueMapper->mapCurrency($raw3DAuthResponseData['Currency'], $txType), + 'transaction_time' => !isset($paymentResponseData['transaction_time']) && isset($raw3DAuthResponseData['TRXDATE']) ? $this->valueFormatter->formatDateTime($raw3DAuthResponseData['TRXDATE'], $txType) : null, 'eci' => $raw3DAuthResponseData['Eci'], /** * TxnStat 3D doğrulama sonucunu belirtir : diff --git a/src/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapper.php index 644931fb..f6257355 100644 --- a/src/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapper.php @@ -7,6 +7,7 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\KuveytPos; use Mews\Pos\PosInterface; class KuveytPosResponseDataMapper extends AbstractResponseDataMapper @@ -24,16 +25,12 @@ class KuveytPosResponseDataMapper extends AbstractResponseDataMapper ]; /** - * Order Status Codes - * - * @var array + * @inheritDoc */ - protected array $orderStatusMappings = [ - 1 => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 4 => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, - 5 => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED, - 6 => PosInterface::PAYMENT_STATUS_CANCELED, - ]; + public static function supports(string $gatewayClass): bool + { + return KuveytPos::class === $gatewayClass; + } /** * {@inheritDoc} @@ -80,11 +77,11 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $result['batch_num'] = $vPosMessage['BatchID']; // Stan: Pos bankası tarafında verilen referans işlem referans numarasıdır. $result['transaction_id'] = $rawPaymentResponseData['Stan']; - $result['amount'] = $this->formatAmount($vPosMessage['Amount']); - $result['currency'] = $this->mapCurrency($vPosMessage['CurrencyCode']); - $result['installment_count'] = $this->mapInstallment($vPosMessage['InstallmentCount']); + $result['amount'] = $this->valueFormatter->formatAmount($vPosMessage['Amount'], $txType); + $result['currency'] = $this->valueMapper->mapCurrency($vPosMessage['CurrencyCode'], $txType); + $result['installment_count'] = $this->valueFormatter->formatInstallment($vPosMessage['InstallmentCount'], $txType); $result['masked_number'] = $vPosMessage['CardNumber']; - $result['transaction_time'] = new \DateTimeImmutable(); + $result['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); $this->logger->debug('mapped payment response', $result); @@ -100,7 +97,7 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen '3d_auth_response' => $raw3DAuthResponseData, 'provision_response' => $rawPaymentResponseData, ]); - $threeDResponse = $this->map3DCommonResponseData($raw3DAuthResponseData); + $threeDResponse = $this->map3DCommonResponseData($raw3DAuthResponseData, $txType); /** @var PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType */ $txType = $threeDResponse['transaction_type'] ?? $txType; if (null === $rawPaymentResponseData || [] === $rawPaymentResponseData) { @@ -142,59 +139,7 @@ public function map3DHostResponseData(array $raw3DAuthResponseData, string $txTy */ public function mapStatusResponse(array $rawResponseData): array { - $rawResponseData = $this->emptyStringsToNull($rawResponseData); - $status = self::TX_DECLINED; - $data = $rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Value']; - - $defaultResponse = $this->getDefaultStatusResponse($rawResponseData); - - if (!isset($data['OrderContract'])) { - if (isset($rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Results']['Result'])) { - $rawResult = $rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Results']['Result']; - $defaultResponse['error_code'] = $rawResult['ErrorCode']; - $defaultResponse['error_message'] = $rawResult['ErrorMessage']; - } - - return $defaultResponse; - } - - $orderContract = $rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Value']['OrderContract']; - $procReturnCode = $this->getProcReturnCode($orderContract); - - if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { - $status = self::TX_APPROVED; - } - - $defaultResponse['status'] = $status; - $defaultResponse['proc_return_code'] = $procReturnCode; - - if (self::TX_APPROVED === $status) { - $defaultResponse['order_status'] = $this->orderStatusMappings[$orderContract['LastOrderStatus']] ?? null; - $defaultResponse['order_id'] = $orderContract['MerchantOrderId']; - $defaultResponse['remote_order_id'] = (string) $orderContract['OrderId']; - - $defaultResponse['auth_code'] = $orderContract['ProvNumber']; - $defaultResponse['ref_ret_num'] = $orderContract['RRN']; - $defaultResponse['transaction_id'] = $orderContract['Stan']; - $defaultResponse['currency'] = $this->mapCurrency($orderContract['FEC']); - $defaultResponse['first_amount'] = null === $orderContract['FirstAmount'] ? null : (float) $orderContract['FirstAmount']; - $defaultResponse['masked_number'] = $orderContract['CardNumber']; - $defaultResponse['transaction_time'] = new \DateTimeImmutable($orderContract['OrderDate']); - $defaultResponse['installment_count'] = $this->mapInstallment($orderContract['InstallmentCount']); - if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $defaultResponse['order_status']) { - $defaultResponse['capture_amount'] = $defaultResponse['first_amount']; - $defaultResponse['capture'] = $defaultResponse['first_amount'] > 0; - if ($defaultResponse['capture']) { - $defaultResponse['capture_time'] = new \DateTimeImmutable($orderContract['UpdateSystemDate']); - } - } elseif (PosInterface::PAYMENT_STATUS_CANCELED === $defaultResponse['order_status']) { - $defaultResponse['cancel_time'] = new \DateTimeImmutable($orderContract['UpdateSystemDate']); - } elseif (PosInterface::PAYMENT_STATUS_FULLY_REFUNDED === $defaultResponse['order_status']) { - $defaultResponse['refund_time'] = new \DateTimeImmutable($orderContract['UpdateSystemDate']); - } - } - - return $defaultResponse; + throw new NotImplementedException(); } /** @@ -202,121 +147,12 @@ public function mapStatusResponse(array $rawResponseData): array */ public function mapRefundResponse(array $rawResponseData): array { - $rawResponseData = $this->emptyStringsToNull($rawResponseData); - $status = self::TX_DECLINED; - - $result = [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => null, - 'transaction_id' => null, - 'currency' => null, - 'error_message' => null, - 'ref_ret_num' => null, - 'status' => $status, - 'error_code' => null, - 'status_detail' => null, - 'all' => $rawResponseData, - ]; - - $drawbackResult = $rawResponseData['PartialDrawbackResponse']['PartialDrawbackResult'] - ?? $rawResponseData['DrawBackResponse']['DrawBackResult']; - $value = $drawbackResult['Value']; - - $procReturnCode = $this->getProcReturnCode($value); - - if (null === $procReturnCode) { - return $result; - } - - if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { - $status = self::TX_APPROVED; - } - - $responseResults = $drawbackResult['Results']; - if (self::TX_APPROVED !== $status && isset($responseResults['Result']) && [] !== $responseResults['Result']) { - $responseResult = $responseResults['Result'][0] ?? $responseResults['Result']; - $result['proc_return_code'] = $procReturnCode; - $result['error_code'] = $responseResult['ErrorCode'] ?? $procReturnCode; - $result['error_message'] = $responseResult['ErrorMessage']; - - return $result; - } - - $result['ref_ret_num'] = $value['RRN']; - $result['transaction_id'] = $value['Stan']; - $result['proc_return_code'] = $procReturnCode; - $result['order_id'] = $value['MerchantOrderId']; - $result['remote_order_id'] = (string) $value['OrderId']; - $result['status'] = $status; - - if (self::TX_APPROVED === $status) { - $result['currency'] = $this->mapCurrency($value['CurrencyCode']); - $result['auth_code'] = $value['ProvisionNumber']; - } else { - $result['error_code'] = $procReturnCode; - $result['error_message'] = $value['ResponseMessage']; - } - - return $result; + throw new NotImplementedException(); } public function mapCancelResponse(array $rawResponseData): array { - $rawResponseData = $this->emptyStringsToNull($rawResponseData); - $status = self::TX_DECLINED; - - $result = [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => null, - 'transaction_id' => null, - 'currency' => null, - 'error_message' => null, - 'ref_ret_num' => null, - 'status' => $status, - 'error_code' => null, - 'status_detail' => null, - 'all' => $rawResponseData, - ]; - - $value = $rawResponseData['SaleReversalResponse']['SaleReversalResult']['Value']; - $procReturnCode = $this->getProcReturnCode($value); - - if (null === $procReturnCode) { - return $result; - } - - if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { - $status = self::TX_APPROVED; - } - - $responseResults = $rawResponseData['SaleReversalResponse']['SaleReversalResult']['Results']; - if (self::TX_APPROVED !== $status && isset($responseResults['Result']) && [] !== $responseResults['Result']) { - $responseResult = $responseResults['Result'][0] ?? $responseResults['Result']; - $result['proc_return_code'] = $procReturnCode; - $result['error_code'] = $responseResult['ErrorCode'] ?? $procReturnCode; - $result['error_message'] = $responseResult['ErrorMessage']; - - return $result; - } - - $result['ref_ret_num'] = $value['RRN']; - $result['transaction_id'] = $value['Stan']; - $result['proc_return_code'] = $procReturnCode; - $result['order_id'] = $value['MerchantOrderId']; - $result['remote_order_id'] = (string) $value['OrderId']; - $result['status'] = $status; - $result['currency'] = $this->mapCurrency($value['CurrencyCode']); - - if (self::TX_APPROVED === $status) { - $result['auth_code'] = $value['ProvisionNumber']; - } else { - $result['error_code'] = $procReturnCode; - $result['error_message'] = $value['ResponseMessage']; - } - - return $result; + throw new NotImplementedException(); } /** @@ -351,17 +187,6 @@ public function extractMdStatus(array $raw3DAuthResponseData): ?string return $this->getProcReturnCode($raw3DAuthResponseData); } - /** - * "101" => 1.01 - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return (float) $amount / 100; - } - /** * Get ProcReturnCode * @@ -374,20 +199,6 @@ protected function getProcReturnCode(array $response): ?string return $response['ResponseCode'] ?? null; } - /** - * @param string $currency currency code that is accepted by bank - * - * @return PosInterface::CURRENCY_*|string - */ - protected function mapCurrency(string $currency): string - { - // 949 => 0949; for the request gateway wants 0949 code, but in response they send 949 code. - $currencyNormalized = str_pad($currency, 4, '0', STR_PAD_LEFT); - - return parent::mapCurrency($currencyNormalized); - } - - /** * @param string $mdStatus * @@ -402,11 +213,12 @@ protected function mapResponseTransactionSecurity(string $mdStatus): string /** * returns mapped data of the common response data among all 3d models. * - * @param array $raw3DAuthResponseData + * @param array $raw3DAuthResponseData + * @param PosInterface::TX_TYPE_PAY_* $txType * * @return array */ - protected function map3DCommonResponseData(array $raw3DAuthResponseData): array + protected function map3DCommonResponseData(array $raw3DAuthResponseData, string $txType): array { $raw3DAuthResponseData = $this->emptyStringsToNull($raw3DAuthResponseData); $procReturnCode = $this->getProcReturnCode($raw3DAuthResponseData); @@ -428,7 +240,7 @@ protected function map3DCommonResponseData(array $raw3DAuthResponseData): array $default = [ 'order_id' => $orderId, 'transaction_security' => $this->mapResponseTransactionSecurity('todo'), - 'transaction_type' => isset($vPosMessage['TransactionType']) ? $this->mapTxType($vPosMessage['TransactionType']) : null, + 'transaction_type' => isset($vPosMessage['TransactionType']) ? $this->valueMapper->mapTxType($vPosMessage['TransactionType']) : null, 'proc_return_code' => $procReturnCode, 'md_status' => null, 'payment_model' => null, @@ -444,9 +256,9 @@ protected function map3DCommonResponseData(array $raw3DAuthResponseData): array ]; if (self::TX_APPROVED === $status) { - $default['payment_model'] = $this->mapSecurityType($vPosMessage['TransactionSecurity']); - $default['amount'] = $this->formatAmount($vPosMessage['Amount']); - $default['currency'] = $this->mapCurrency($vPosMessage['CurrencyCode']); + $default['payment_model'] = $this->valueMapper->mapSecureType($vPosMessage['TransactionSecurity'], $txType); + $default['amount'] = $this->valueFormatter->formatAmount($vPosMessage['Amount'], $txType); + $default['currency'] = $this->valueMapper->mapCurrency($vPosMessage['CurrencyCode'], $txType); $default['masked_number'] = $vPosMessage['CardNumber']; $default['batch_num'] = $vPosMessage['BatchID'] > 0 ? $vPosMessage['BatchID'] : null; } diff --git a/src/DataMapper/ResponseDataMapper/KuveytSoapApiPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/KuveytSoapApiPosResponseDataMapper.php new file mode 100644 index 00000000..349dc02d --- /dev/null +++ b/src/DataMapper/ResponseDataMapper/KuveytSoapApiPosResponseDataMapper.php @@ -0,0 +1,293 @@ + + */ + protected array $codes = [ + self::PROCEDURE_SUCCESS_CODE => self::TX_APPROVED, + 'ApiUserNotDefined' => 'invalid_transaction', + 'EmptyMDException' => 'invalid_transaction', + 'HashDataError' => 'invalid_transaction', + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return KuveytSoapApiPos::class === $gatewayClass; + } + + /** + * {@inheritDoc} + */ + public function mapPaymentResponse(array $rawPaymentResponseData, string $txType, array $order): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritdoc} + */ + public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymentResponseData, string $txType, array $order): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritdoc} + */ + public function map3DPayResponseData(array $raw3DAuthResponseData, string $txType, array $order): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritdoc} + */ + public function map3DHostResponseData(array $raw3DAuthResponseData, string $txType, array $order): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritdoc} + */ + public function mapStatusResponse(array $rawResponseData): array + { + $txType = PosInterface::TX_TYPE_STATUS; + $rawResponseData = $this->emptyStringsToNull($rawResponseData); + $status = self::TX_DECLINED; + $data = $rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Value']; + + $defaultResponse = $this->getDefaultStatusResponse($rawResponseData); + + if (!isset($data['OrderContract'])) { + if (isset($rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Results']['Result'])) { + $rawResult = $rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Results']['Result']; + $defaultResponse['error_code'] = $rawResult['ErrorCode']; + $defaultResponse['error_message'] = $rawResult['ErrorMessage']; + } + + return $defaultResponse; + } + + $orderContract = $rawResponseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Value']['OrderContract']; + $procReturnCode = $this->getProcReturnCode($orderContract); + + if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { + $status = self::TX_APPROVED; + } + + $defaultResponse['status'] = $status; + $defaultResponse['proc_return_code'] = $procReturnCode; + + if (self::TX_APPROVED === $status) { + $defaultResponse['order_status'] = $this->valueMapper->mapOrderStatus($orderContract['LastOrderStatus']); + $defaultResponse['order_id'] = $orderContract['MerchantOrderId']; + $defaultResponse['remote_order_id'] = (string) $orderContract['OrderId']; + + $defaultResponse['auth_code'] = $orderContract['ProvNumber']; + $defaultResponse['ref_ret_num'] = $orderContract['RRN']; + $defaultResponse['transaction_id'] = $orderContract['Stan']; + $defaultResponse['currency'] = $this->valueMapper->mapCurrency($orderContract['FEC'], $txType); + $defaultResponse['first_amount'] = null === $orderContract['FirstAmount'] ? null : $this->valueFormatter->formatAmount($orderContract['FirstAmount'], $txType); + $defaultResponse['masked_number'] = $orderContract['CardNumber']; + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime($orderContract['OrderDate'], $txType); + $defaultResponse['installment_count'] = $this->valueFormatter->formatInstallment($orderContract['InstallmentCount'], $txType); + if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $defaultResponse['order_status']) { + $defaultResponse['capture_amount'] = $defaultResponse['first_amount']; + $defaultResponse['capture'] = $defaultResponse['first_amount'] > 0; + if ($defaultResponse['capture']) { + $defaultResponse['capture_time'] = $this->valueFormatter->formatDateTime($orderContract['UpdateSystemDate'], $txType); + } + } elseif (PosInterface::PAYMENT_STATUS_CANCELED === $defaultResponse['order_status']) { + $defaultResponse['cancel_time'] = $this->valueFormatter->formatDateTime($orderContract['UpdateSystemDate'], $txType); + } elseif (PosInterface::PAYMENT_STATUS_FULLY_REFUNDED === $defaultResponse['order_status']) { + $defaultResponse['refund_time'] = $this->valueFormatter->formatDateTime($orderContract['UpdateSystemDate'], $txType); + } + } + + return $defaultResponse; + } + + /** + * @inheritDoc + */ + public function mapRefundResponse(array $rawResponseData): array + { + $rawResponseData = $this->emptyStringsToNull($rawResponseData); + $status = self::TX_DECLINED; + + $result = [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => null, + 'transaction_id' => null, + 'currency' => null, + 'error_message' => null, + 'ref_ret_num' => null, + 'status' => $status, + 'error_code' => null, + 'status_detail' => null, + 'all' => $rawResponseData, + ]; + + $drawbackResult = $rawResponseData['PartialDrawbackResponse']['PartialDrawbackResult'] + ?? $rawResponseData['DrawBackResponse']['DrawBackResult']; + $value = $drawbackResult['Value']; + + $procReturnCode = $this->getProcReturnCode($value); + + if (null === $procReturnCode) { + return $result; + } + + if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { + $status = self::TX_APPROVED; + } + + $responseResults = $drawbackResult['Results']; + if (self::TX_APPROVED !== $status && isset($responseResults['Result']) && [] !== $responseResults['Result']) { + $responseResult = $responseResults['Result'][0] ?? $responseResults['Result']; + $result['proc_return_code'] = $procReturnCode; + $result['error_code'] = $responseResult['ErrorCode'] ?? $procReturnCode; + $result['error_message'] = $responseResult['ErrorMessage']; + + return $result; + } + + $result['ref_ret_num'] = $value['RRN']; + $result['transaction_id'] = $value['Stan']; + $result['proc_return_code'] = $procReturnCode; + $result['order_id'] = $value['MerchantOrderId']; + $result['remote_order_id'] = (string) $value['OrderId']; + $result['status'] = $status; + + if (self::TX_APPROVED === $status) { + $result['currency'] = $this->valueMapper->mapCurrency($value['CurrencyCode'], PosInterface::TX_TYPE_REFUND); + $result['auth_code'] = $value['ProvisionNumber']; + } else { + $result['error_code'] = $procReturnCode; + $result['error_message'] = $value['ResponseMessage']; + } + + return $result; + } + + public function mapCancelResponse(array $rawResponseData): array + { + $rawResponseData = $this->emptyStringsToNull($rawResponseData); + $status = self::TX_DECLINED; + + $result = [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => null, + 'transaction_id' => null, + 'currency' => null, + 'error_message' => null, + 'ref_ret_num' => null, + 'status' => $status, + 'error_code' => null, + 'status_detail' => null, + 'all' => $rawResponseData, + ]; + + $value = $rawResponseData['SaleReversalResponse']['SaleReversalResult']['Value']; + $procReturnCode = $this->getProcReturnCode($value); + + if (null === $procReturnCode) { + return $result; + } + + if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { + $status = self::TX_APPROVED; + } + + $responseResults = $rawResponseData['SaleReversalResponse']['SaleReversalResult']['Results']; + if (self::TX_APPROVED !== $status && isset($responseResults['Result']) && [] !== $responseResults['Result']) { + $responseResult = $responseResults['Result'][0] ?? $responseResults['Result']; + $result['proc_return_code'] = $procReturnCode; + $result['error_code'] = $responseResult['ErrorCode'] ?? $procReturnCode; + $result['error_message'] = $responseResult['ErrorMessage']; + + return $result; + } + + $result['ref_ret_num'] = $value['RRN']; + $result['transaction_id'] = $value['Stan']; + $result['proc_return_code'] = $procReturnCode; + $result['order_id'] = $value['MerchantOrderId']; + $result['remote_order_id'] = (string) $value['OrderId']; + $result['status'] = $status; + $result['currency'] = $this->valueMapper->mapCurrency($value['CurrencyCode'], PosInterface::TX_TYPE_CANCEL); + + if (self::TX_APPROVED === $status) { + $result['auth_code'] = $value['ProvisionNumber']; + } else { + $result['error_code'] = $procReturnCode; + $result['error_message'] = $value['ResponseMessage']; + } + + return $result; + } + + /** + * {@inheritDoc} + */ + public function mapHistoryResponse(array $rawResponseData): array + { + throw new NotImplementedException(); + } + + /** + * {@inheritDoc} + */ + public function mapOrderHistoryResponse(array $rawResponseData): array + { + throw new NotImplementedException(); + } + + /** + * @inheritDoc + */ + public function is3dAuthSuccess(?string $mdStatus): bool + { + return self::PROCEDURE_SUCCESS_CODE === $mdStatus; + } + + /** + * @inheritDoc + */ + public function extractMdStatus(array $raw3DAuthResponseData): ?string + { + return $this->getProcReturnCode($raw3DAuthResponseData); + } + + /** + * Get ProcReturnCode + * + * @param array $response + * + * @return string|null + */ + protected function getProcReturnCode(array $response): ?string + { + return $response['ResponseCode'] ?? null; + } +} diff --git a/src/DataMapper/ResponseDataMapper/ParamPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/ParamPosResponseDataMapper.php index 09aefead..2200b63f 100644 --- a/src/DataMapper/ResponseDataMapper/ParamPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/ParamPosResponseDataMapper.php @@ -7,81 +7,19 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\Param3DHostPos; +use Mews\Pos\Gateways\ParamPos; use Mews\Pos\PosInterface; -use Psr\Log\LoggerInterface; class ParamPosResponseDataMapper extends AbstractResponseDataMapper { - /** - * Response Codes - * - * @var array - */ - protected array $codes = [ - self::PROCEDURE_SUCCESS_CODE => self::TX_APPROVED, - ]; - - /** - * @var array - */ - protected array $orderStatusMappings = [ - 'FAIL' => PosInterface::PAYMENT_STATUS_ERROR, - 'BANK_FAIL' => PosInterface::PAYMENT_STATUS_ERROR, - 'SUCCESS' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 'CANCEL' => PosInterface::PAYMENT_STATUS_CANCELED, - 'REFUND' => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, - 'PARTIAL_REFUND' => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED, - ]; - - /** - * @var array - */ - private array $statusRequestTxMappings = [ - 'SALE' => PosInterface::TX_TYPE_PAY_AUTH, - 'PRE_AUTH' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'POST_AUTH' => PosInterface::TX_TYPE_PAY_POST_AUTH, - ]; - - /** - * @var array - */ - private array $historyRequestTxMappings = [ - 'Satış' => PosInterface::TX_TYPE_PAY_AUTH, - 'İptal' => PosInterface::TX_TYPE_CANCEL, - 'İade' => PosInterface::TX_TYPE_REFUND, - ]; - - /** - * @param array $currencyMappings - * @param array $txTypeMappings - * @param array $secureTypeMappings - * @param LoggerInterface $logger - */ - public function __construct(array $currencyMappings, array $txTypeMappings, array $secureTypeMappings, LoggerInterface $logger) - { - parent::__construct($currencyMappings, $txTypeMappings, $secureTypeMappings, $logger); - - $this->secureTypeMappings = [ - 'NONSECURE' => PosInterface::MODEL_NON_SECURE, - '3D' => PosInterface::MODEL_3D_SECURE, - ]; - - $this->currencyMappings = [ - 'TRL' => PosInterface::CURRENCY_TRY, - 'TL' => PosInterface::CURRENCY_TRY, - 'EUR' => PosInterface::CURRENCY_EUR, - 'USD' => PosInterface::CURRENCY_USD, - ]; - } - /** * @inheritDoc */ - public function mapTxType($txType): ?string + public static function supports(string $gatewayClass): bool { - return $this->statusRequestTxMappings[$txType] - ?? $this->historyRequestTxMappings[$txType] - ?? parent::mapTxType($txType); + return ParamPos::class === $gatewayClass + || Param3DHostPos::class === $gatewayClass; } /** @@ -136,7 +74,7 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $mappedResponse['amount'] = $order['amount']; $mappedResponse['currency'] = $currency; - $mappedResponse['transaction_time'] = new \DateTimeImmutable(); + $mappedResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } $this->logger->debug('mapped payment response', $mappedResponse); @@ -183,7 +121,7 @@ private function map3DPaymentResponse(array $rawPaymentResponseData, string $txT $mappedResponse['auth_code'] = $payResult['Bank_AuthCode']; $mappedResponse['ref_ret_num'] = $payResult['Bank_HostRefNum']; $mappedResponse['currency'] = $order['currency']; - $mappedResponse['transaction_time'] = new \DateTimeImmutable(); + $mappedResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } $this->logger->debug('mapped payment response', $mappedResponse); @@ -213,7 +151,8 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'transaction_security' => null, 'md_status' => $mdStatus, 'order_id' => $raw3DAuthResponseData['orderId'], - 'amount' => null !== $raw3DAuthResponseData['transactionAmount'] ? $this->formatAmount($raw3DAuthResponseData['transactionAmount']) : null, + 'amount' => null !== $raw3DAuthResponseData['transactionAmount'] + ? $this->valueFormatter->formatAmount($raw3DAuthResponseData['transactionAmount'], $txType) : null, 'currency' => $order['currency'], 'installment_count' => null, 'md_error_message' => null, @@ -255,11 +194,22 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp ]; if (self::TX_APPROVED === $status) { $mappedResponse['order_id'] = $raw3DAuthResponseData['TURKPOS_RETVAL_Siparis_ID']; - $mappedResponse['amount'] = $this->formatAmount($raw3DAuthResponseData['TURKPOS_RETVAL_Tahsilat_Tutari']); - $mappedResponse['currency'] = $this->mapCurrency($raw3DAuthResponseData['TURKPOS_RETVAL_PB']); - $mappedResponse['installment_count'] = isset($raw3DAuthResponseData['TURKPOS_RETVAL_Taksit']) ? $this->mapInstallment($raw3DAuthResponseData['TURKPOS_RETVAL_Taksit']) : null; + $mappedResponse['amount'] = $this->valueFormatter->formatAmount( + $raw3DAuthResponseData['TURKPOS_RETVAL_Tahsilat_Tutari'], + $txType + ); + $mappedResponse['currency'] = $this->valueMapper->mapCurrency( + $raw3DAuthResponseData['TURKPOS_RETVAL_PB'], + $txType + ); + $mappedResponse['installment_count'] = isset($raw3DAuthResponseData['TURKPOS_RETVAL_Taksit']) + ? $this->valueFormatter->formatInstallment($raw3DAuthResponseData['TURKPOS_RETVAL_Taksit'], $txType) + : null; $mappedResponse['masked_number'] = $raw3DAuthResponseData['TURKPOS_RETVAL_KK_No']; - $mappedResponse['transaction_time'] = new \DateTimeImmutable($raw3DAuthResponseData['TURKPOS_RETVAL_Islem_Tarih']); + $mappedResponse['transaction_time'] = $this->valueFormatter->formatDateTime( + $raw3DAuthResponseData['TURKPOS_RETVAL_Islem_Tarih'], + $txType + ); } $this->logger->debug('mapped payment response', $mappedResponse); @@ -272,7 +222,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp */ public function map3DHostResponseData(array $raw3DAuthResponseData, string $txType, array $order): array { - $result = $this->map3DPayResponseData($raw3DAuthResponseData, $txType, $order); + $result = $this->map3DPayResponseData($raw3DAuthResponseData, $txType, $order); $result['payment_model'] = PosInterface::MODEL_3D_HOST; return $result; @@ -329,6 +279,7 @@ public function mapCancelResponse(array $rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $statusResponse = $rawResponseData['TP_Islem_Sorgulama4Response']['TP_Islem_Sorgulama4Result']; @@ -354,10 +305,10 @@ public function mapStatusResponse(array $rawResponseData): array $result['auth_code'] = $dtBilgi['Bank_AuthCode']; $result['ref_ret_num'] = $dtBilgi['Bank_HostRefNum']; $result['masked_number'] = $dtBilgi['KK_No']; - $result['first_amount'] = (float) $dtBilgi['Toplam_Tutar']; + $result['first_amount'] = $this->valueFormatter->formatAmount($dtBilgi['Toplam_Tutar'], $txType); - $result['order_status'] = $this->orderStatusMappings[$dtBilgi['Durum']] ?? null; - $result['transaction_type'] = $this->mapTxType($dtBilgi['Islem_Tip']); + $result['order_status'] = $this->valueMapper->mapOrderStatus($dtBilgi['Durum']); + $result['transaction_type'] = $this->valueMapper->mapTxType($dtBilgi['Islem_Tip']); if (PosInterface::TX_TYPE_PAY_AUTH === $result['transaction_type']) { $result['transaction_type'] = PosInterface::TX_TYPE_PAY_AUTH; @@ -367,9 +318,9 @@ public function mapStatusResponse(array $rawResponseData): array $result['order_status'] = PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED; } - $txDate = isset($dtBilgi['Tarih']) ? new \DateTimeImmutable($dtBilgi['Tarih']) : null; + $txDate = isset($dtBilgi['Tarih']) ? $this->valueFormatter->formatDateTime($dtBilgi['Tarih'], $txType) : null; if ($dtBilgi['Toplam_Iade_Tutar'] > 0) { - $dtBilgi['refund_amount'] = $this->formatAmount($dtBilgi['Toplam_Iade_Tutar']); + $dtBilgi['refund_amount'] = $this->valueFormatter->formatAmount($dtBilgi['Toplam_Iade_Tutar'], $txType); $dtBilgi['refund_time'] = $txDate; } @@ -460,16 +411,6 @@ protected function getProcReturnCode(array $response): ?int return $response['Sonuc'] ?? $response['TURKPOS_RETVAL_Sonuc'] ?? null; } - /** - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return ((float) \str_replace(',', '.', $amount)); - } - /** * @param array $rawTx * @@ -477,6 +418,7 @@ protected function formatAmount(string $amount): float */ private function mapSingleHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_HISTORY; $rawTx = $this->emptyStringsToNull($rawTx); $transaction = $this->getDefaultOrderHistoryTxResponse(); $procReturnCode = $this->getProcReturnCode($rawTx); @@ -485,21 +427,28 @@ private function mapSingleHistoryTransaction(array $rawTx): array $transaction['status'] = self::TX_APPROVED; } - $transaction['transaction_type'] = $this->mapTxType($rawTx['Tip_Str']); + $dateTime = $this->valueFormatter->formatDateTime($rawTx['Tarih'], $txType); + $transaction['transaction_type'] = $this->valueMapper->mapTxType($rawTx['Tip_Str']); if (self::TX_APPROVED === $transaction['status']) { - $transaction['currency'] = isset($rawTx['PB']) ? $this->mapCurrency($rawTx['PB']) : null; - $amount = null === $rawTx['Tutar'] ? null : $this->formatAmount($rawTx['Tutar']); + $transaction['currency'] = isset($rawTx['PB']) + ? $this->valueMapper->mapCurrency($rawTx['PB'], $txType) + : null; + $amount = null === $rawTx['Tutar'] + ? null : $this->valueFormatter->formatAmount($rawTx['Tutar'], PosInterface::TX_TYPE_HISTORY); if (PosInterface::TX_TYPE_PAY_AUTH === $transaction['transaction_type']) { $transaction['first_amount'] = $amount; $transaction['capture_amount'] = $amount; $transaction['capture'] = true; - $transaction['capture_time'] = new \DateTimeImmutable($rawTx['Tarih']); + $transaction['capture_time'] = $dateTime; } elseif (PosInterface::TX_TYPE_CANCEL === $transaction['transaction_type'] && $rawTx['Tutar'] < 0) { $transaction['refund_amount'] = $transaction['first_amount']; } if ($rawTx['Toplam_Iade_Tutar'] > 0) { - $transaction['refund_amount'] = $this->formatAmount($rawTx['Toplam_Iade_Tutar']); + $transaction['refund_amount'] = $this->valueFormatter->formatAmount( + $rawTx['Toplam_Iade_Tutar'], + PosInterface::TX_TYPE_HISTORY + ); } } else { $transaction['error_code'] = $procReturnCode; @@ -507,8 +456,8 @@ private function mapSingleHistoryTransaction(array $rawTx): array } $transaction['order_id'] = $rawTx['ORJ_ORDER_ID']; - $transaction['payment_model'] = $this->mapSecurityType($rawTx['Islem_Guvenlik']); - $transaction['transaction_time'] = new \DateTimeImmutable($rawTx['Tarih']); + $transaction['payment_model'] = $this->valueMapper->mapSecureType($rawTx['Islem_Guvenlik'], $txType); + $transaction['transaction_time'] = $dateTime; return $transaction; } diff --git a/src/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapper.php index 39d48e6d..ac900c03 100644 --- a/src/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapper.php @@ -7,6 +7,7 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\PayFlexCPV4Pos; use Mews\Pos\PosInterface; class PayFlexCPV4PosResponseDataMapper extends AbstractResponseDataMapper @@ -23,6 +24,14 @@ class PayFlexCPV4PosResponseDataMapper extends AbstractResponseDataMapper self::PROCEDURE_SUCCESS_CODE => self::TX_APPROVED, ]; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayFlexCPV4Pos::class === $gatewayClass; + } + /** * {@inheritdoc} */ @@ -60,11 +69,11 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $paymentResponse['auth_code'] = $raw3DAuthResponseData['AuthCode']; $paymentResponse['ref_ret_num'] = $raw3DAuthResponseData['TransactionId']; $paymentResponse['order_id'] = $raw3DAuthResponseData['OrderID']; - $paymentResponse['currency'] = $this->mapCurrency($raw3DAuthResponseData['AmountCode']); - $paymentResponse['amount'] = $this->formatAmount($raw3DAuthResponseData['Amount']); - $paymentResponse['transaction_type'] = $this->mapTxType($raw3DAuthResponseData['TransactionType']); - $paymentResponse['installment_count'] = $this->mapInstallment($raw3DAuthResponseData['InstallmentCount']); - $paymentResponse['transaction_time'] = new \DateTimeImmutable($raw3DAuthResponseData['HostDate']); + $paymentResponse['currency'] = $this->valueMapper->mapCurrency($raw3DAuthResponseData['AmountCode'], $txType); + $paymentResponse['amount'] = $this->valueFormatter->formatAmount($raw3DAuthResponseData['Amount'], $txType); + $paymentResponse['transaction_type'] = $this->valueMapper->mapTxType($raw3DAuthResponseData['TransactionType']); + $paymentResponse['installment_count'] = $this->valueFormatter->formatInstallment($raw3DAuthResponseData['InstallmentCount'], $txType); + $paymentResponse['transaction_time'] = $this->valueFormatter->formatDateTime($raw3DAuthResponseData['HostDate'], $txType); } return $paymentResponse; diff --git a/src/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapper.php index 60c5cec3..bedf754a 100644 --- a/src/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapper.php @@ -7,8 +7,8 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\PayFlexV4Pos; use Mews\Pos\PosInterface; -use Psr\Log\LoggerInterface; class PayFlexV4PosResponseDataMapper extends AbstractResponseDataMapper { @@ -30,20 +30,11 @@ class PayFlexV4PosResponseDataMapper extends AbstractResponseDataMapper ]; /** - * @param array $currencyMappings - * @param array $txTypeMappings - * @param array $secureTypeMappings - * @param LoggerInterface $logger + * @inheritDoc */ - public function __construct(array $currencyMappings, array $txTypeMappings, array $secureTypeMappings, LoggerInterface $logger) + public static function supports(string $gatewayClass): bool { - parent::__construct($currencyMappings, $txTypeMappings, $secureTypeMappings, $logger); - - $this->secureTypeMappings += [ - '1' => PosInterface::MODEL_NON_SECURE, - '2' => PosInterface::MODEL_3D_SECURE, - '3' => PosInterface::MODEL_3D_PAY, - ]; + return PayFlexV4Pos::class === $gatewayClass; } /** @@ -71,8 +62,8 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'auth_code' => null, 'order_id' => $raw3DAuthResponseData['VerifyEnrollmentRequestId'], 'status' => $threeDAuthStatus, - 'currency' => $paymentResponseData['currency'] ?? $this->mapCurrency($raw3DAuthResponseData['PurchCurrency']), - 'installment_count' => $paymentResponseData['installment_count'] ?? $this->mapInstallment($raw3DAuthResponseData['InstallmentCount']), + 'currency' => $paymentResponseData['currency'] ?? $this->valueMapper->mapCurrency($raw3DAuthResponseData['PurchCurrency'], $txType), + 'installment_count' => $paymentResponseData['installment_count'] ?? $this->valueFormatter->formatInstallment($raw3DAuthResponseData['InstallmentCount'], $txType), 'status_detail' => null, 'error_code' => self::TX_DECLINED === $threeDAuthStatus ? $raw3DAuthResponseData['ErrorCode'] : null, 'error_message' => self::TX_DECLINED === $threeDAuthStatus ? $raw3DAuthResponseData['ErrorMessage'] : null, @@ -143,6 +134,7 @@ public function mapCancelResponse($rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); /** * @var array{ResponseCode: string, ResponseMessage: string, ResponseDateTime: string, Status: 'Success'|'Error'} $responseInfo @@ -183,9 +175,9 @@ public function mapStatusResponse(array $rawResponseData): array $defaultResponse['transaction_id'] = $txResultInfo['TransactionId']; $defaultResponse['ref_ret_num'] = $txResultInfo['Rrn']; $defaultResponse['order_status'] = $orderStatus; - $defaultResponse['transaction_type'] = $this->mapTxType($txResultInfo['TransactionType']); - $defaultResponse['currency'] = $this->mapCurrency($txResultInfo['AmountCode']); - $defaultResponse['first_amount'] = $this->formatAmount($txResultInfo['CurrencyAmount'] ?? $txResultInfo['Amount']); + $defaultResponse['transaction_type'] = $this->valueMapper->mapTxType($txResultInfo['TransactionType']); + $defaultResponse['currency'] = $this->valueMapper->mapCurrency($txResultInfo['AmountCode'], $txType); + $defaultResponse['first_amount'] = $this->valueFormatter->formatAmount($txResultInfo['CurrencyAmount'] ?? $txResultInfo['Amount'], $txType); $defaultResponse['capture_amount'] = null; $defaultResponse['status'] = self::PROCEDURE_SUCCESS_CODE === $orderProcCode ? self::TX_APPROVED : self::TX_DECLINED; $defaultResponse['error_code'] = self::PROCEDURE_SUCCESS_CODE !== $orderProcCode ? $txResultInfo['HostResultCode'] : null; @@ -203,18 +195,18 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $rawPaymentResponseData = $this->emptyStringsToNull($rawPaymentResponseData); $commonResponse = $this->getCommonPaymentResponse($rawPaymentResponseData, $txType); $commonResponse['order_id'] = $rawPaymentResponseData['OrderId'] ?? null; - $commonResponse['currency'] = isset($rawPaymentResponseData['CurrencyCode']) ? $this->mapCurrency($rawPaymentResponseData['CurrencyCode']) : null; - $commonResponse['amount'] = isset($rawPaymentResponseData['TLAmount']) ? $this->formatAmount($rawPaymentResponseData['TLAmount']) : null; - $commonResponse['transaction_type'] = isset($rawPaymentResponseData['TransactionType']) ? $this->mapTxType($rawPaymentResponseData['TransactionType']) : null; + $commonResponse['currency'] = isset($rawPaymentResponseData['CurrencyCode']) ? $this->valueMapper->mapCurrency($rawPaymentResponseData['CurrencyCode'], $txType) : null; + $commonResponse['amount'] = isset($rawPaymentResponseData['TLAmount']) ? $this->valueFormatter->formatAmount($rawPaymentResponseData['TLAmount'], $txType) : null; + $commonResponse['transaction_type'] = isset($rawPaymentResponseData['TransactionType']) ? $this->valueMapper->mapTxType($rawPaymentResponseData['TransactionType']) : null; if (self::TX_APPROVED === $commonResponse['status']) { - $commonResponse['transaction_id'] = $rawPaymentResponseData['TransactionId']; - $txTime = $rawPaymentResponseData['HostDate']; + $commonResponse['transaction_id'] = $rawPaymentResponseData['TransactionId']; + $txTime = $rawPaymentResponseData['HostDate']; if (\strlen($txTime) === 10) { // ziraat is sending host date without year $txTime = date('Y').$txTime; } - $commonResponse['transaction_time'] = new \DateTimeImmutable($txTime); + $commonResponse['transaction_time'] = $this->valueFormatter->formatDateTime($txTime, $txType); $commonResponse['auth_code'] = $rawPaymentResponseData['AuthCode']; $commonResponse['ref_ret_num'] = $rawPaymentResponseData['TransactionId']; $commonResponse['batch_num'] = $rawPaymentResponseData['BatchNo']; @@ -300,7 +292,7 @@ private function getCommonPaymentResponse(array $responseData, string $txType): $status = self::TX_APPROVED; } - $paymentModel = isset($responseData['ThreeDSecureType']) ? $this->mapSecurityType($responseData['ThreeDSecureType']) : null; + $paymentModel = isset($responseData['ThreeDSecureType']) ? $this->valueMapper->mapSecureType($responseData['ThreeDSecureType'], $txType) : null; $response = $this->getDefaultPaymentResponse($txType, $paymentModel); $response['proc_return_code'] = $resultCode; diff --git a/src/DataMapper/ResponseDataMapper/PayForPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/PayForPosResponseDataMapper.php index 65227a75..b9796915 100644 --- a/src/DataMapper/ResponseDataMapper/PayForPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/PayForPosResponseDataMapper.php @@ -6,10 +6,19 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; +use Mews\Pos\Gateways\PayForPos; use Mews\Pos\PosInterface; class PayForPosResponseDataMapper extends AbstractResponseDataMapper { + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayForPos::class === $gatewayClass; + } + /** * Response Codes * @@ -60,7 +69,7 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $mappedResponse = [ 'order_id' => $rawPaymentResponseData['TransId'], 'transaction_id' => $rawPaymentResponseData['TransId'], - 'transaction_time' => (self::TX_APPROVED === $status) ? new \DateTimeImmutable() : null, + 'transaction_time' => (self::TX_APPROVED === $status) ? $this->valueFormatter->formatDateTime('now', $txType) : null, 'auth_code' => $rawPaymentResponseData['AuthCode'], 'currency' => $order['currency'], 'amount' => $order['amount'], @@ -93,7 +102,7 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen $threeDAuthStatus = $this->is3dAuthSuccess($mdStatus) ? self::TX_APPROVED : self::TX_DECLINED; $paymentResponseData = []; - $mapped3DResponseData = $this->map3DCommonResponseData($raw3DAuthResponseData); + $mapped3DResponseData = $this->map3DCommonResponseData($raw3DAuthResponseData, $txType); /** @var PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType */ $txType = $mapped3DResponseData['transaction_type'] ?? $txType; @@ -154,7 +163,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp 'all' => $raw3DAuthResponseData, ]; - $commonThreeDResponseData = $this->map3DCommonResponseData($raw3DAuthResponseData); + $commonThreeDResponseData = $this->map3DCommonResponseData($raw3DAuthResponseData, $txType); /** @var PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType */ $txType = $commonThreeDResponseData['transaction_type']; /** @var PosInterface::MODEL_3D_* $paymentModel */ @@ -221,6 +230,7 @@ public function mapCancelResponse($rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $procReturnCode = $this->getProcReturnCode($rawResponseData); @@ -234,9 +244,9 @@ public function mapStatusResponse(array $rawResponseData): array $defaultResponse['proc_return_code'] = $procReturnCode; $defaultResponse['order_id'] = $rawResponseData['OrderId']; $defaultResponse['org_order_id'] = $rawResponseData['OrgOrderId']; - $defaultResponse['installment_count'] = $this->mapInstallment($rawResponseData['InstallmentCount']); - $defaultResponse['transaction_type'] = $this->mapTxType($rawResponseData['TxnType']); - $defaultResponse['currency'] = $this->mapCurrency($rawResponseData['Currency']); + $defaultResponse['installment_count'] = $this->valueFormatter->formatInstallment($rawResponseData['InstallmentCount'], $txType); + $defaultResponse['transaction_type'] = $this->valueMapper->mapTxType($rawResponseData['TxnType']); + $defaultResponse['currency'] = $this->valueMapper->mapCurrency($rawResponseData['Currency'], $txType); $defaultResponse['status'] = $status; $defaultResponse['status_detail'] = $this->getStatusDetail($procReturnCode); @@ -246,8 +256,8 @@ public function mapStatusResponse(array $rawResponseData): array $defaultResponse['ref_ret_num'] = $rawResponseData['HostRefNum']; $defaultResponse['masked_number'] = $rawResponseData['CardMask']; - $defaultResponse['first_amount'] = $this->formatAmount($rawResponseData['PurchAmount']); - $defaultResponse['transaction_time'] = new \DateTimeImmutable($rawResponseData['InsertDatetime']); + $defaultResponse['first_amount'] = $this->valueFormatter->formatAmount($rawResponseData['PurchAmount'], $txType); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime($rawResponseData['InsertDatetime'], $txType); $defaultResponse['capture'] = false; if (\in_array( $defaultResponse['transaction_type'], @@ -264,11 +274,11 @@ public function mapStatusResponse(array $rawResponseData): array // ex: // VoidDate: 20240119 // VoidTime: 213405 - $defaultResponse['cancel_time'] = new \DateTimeImmutable($rawResponseData['VoidDate'].'T'.$rawResponseData['VoidTime']); + $defaultResponse['cancel_time'] = $this->valueFormatter->formatDateTime($rawResponseData['VoidDate'].'T'.$rawResponseData['VoidTime'], $txType); } if ($rawResponseData['RefundedAmount'] > 0) { - $defaultResponse['refund_amount'] = $this->formatAmount($rawResponseData['RefundedAmount']); + $defaultResponse['refund_amount'] = $this->valueFormatter->formatAmount($rawResponseData['RefundedAmount'], PosInterface::TX_TYPE_STATUS); } @@ -474,11 +484,12 @@ private function map3DPaymentResponseCommon(array $rawPaymentResponseData, strin /** * returns mapped data of the common response data among all 3d models. * - * @param array $raw3DAuthResponseData + * @param array $raw3DAuthResponseData + * @param PosInterface::TX_TYPE_PAY_* $txType * * @return array */ - private function map3DCommonResponseData(array $raw3DAuthResponseData): array + private function map3DCommonResponseData(array $raw3DAuthResponseData, string $txType): array { $procReturnCode = $this->getProcReturnCode($raw3DAuthResponseData); $mdStatus = $this->extractMdStatus($raw3DAuthResponseData); @@ -486,11 +497,11 @@ private function map3DCommonResponseData(array $raw3DAuthResponseData): array $result = [ 'transaction_security' => null, - 'transaction_type' => $this->mapTxType($raw3DAuthResponseData['TxnType']), - 'payment_model' => $this->mapSecurityType($raw3DAuthResponseData['SecureType']), + 'transaction_type' => $this->valueMapper->mapTxType($raw3DAuthResponseData['TxnType']), + 'payment_model' => $this->valueMapper->mapSecureType($raw3DAuthResponseData['SecureType'], $txType), 'masked_number' => $raw3DAuthResponseData['CardMask'], - 'amount' => $this->formatAmount($raw3DAuthResponseData['PurchAmount']), - 'currency' => $this->mapCurrency($raw3DAuthResponseData['Currency']), + 'amount' => $this->valueFormatter->formatAmount($raw3DAuthResponseData['PurchAmount'], $txType), + 'currency' => $this->valueMapper->mapCurrency($raw3DAuthResponseData['Currency'], $txType), 'tx_status' => $raw3DAuthResponseData['TxnResult'], 'md_status' => $mdStatus, 'md_error_code' => (self::TX_DECLINED === $threeDAuthStatus) ? $procReturnCode : null, @@ -500,8 +511,8 @@ private function map3DCommonResponseData(array $raw3DAuthResponseData): array ]; if (self::TX_APPROVED === $threeDAuthStatus) { - $result['installment_count'] = $this->mapInstallment($raw3DAuthResponseData['InstallmentCount']); - $result['transaction_time'] = new \DateTimeImmutable($raw3DAuthResponseData['TransactionDate']); + $result['installment_count'] = $this->valueFormatter->formatInstallment($raw3DAuthResponseData['InstallmentCount'], $txType); + $result['transaction_time'] = $this->valueFormatter->formatDateTime($raw3DAuthResponseData['TransactionDate'], $txType); $result['batch_num'] = $raw3DAuthResponseData['BatchNo']; } @@ -519,6 +530,7 @@ private function map3DCommonResponseData(array $raw3DAuthResponseData): array */ private function mapSingleOrderHistoryTransaction(array $rawTx): array { + $txType = PosInterface::TX_TYPE_ORDER_HISTORY; $procReturnCode = $this->getProcReturnCode($rawTx); $status = self::TX_DECLINED; if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { @@ -531,16 +543,16 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array $defaultResponse['status'] = $status; $defaultResponse['status_detail'] = $this->getStatusDetail($procReturnCode); $defaultResponse['error_code'] = self::TX_APPROVED === $status ? null : $procReturnCode; - $defaultResponse['transaction_type'] = $this->mapTxType((string) $rawTx['TxnType']); - $defaultResponse['currency'] = null !== $rawTx['Currency'] ? $this->mapCurrency($rawTx['Currency']) : null; + $defaultResponse['transaction_type'] = $this->valueMapper->mapTxType((string) $rawTx['TxnType']); + $defaultResponse['currency'] = null !== $rawTx['Currency'] ? $this->valueMapper->mapCurrency($rawTx['Currency'], $txType) : null; if (self::TX_APPROVED === $status) { $orderStatus = null; $defaultResponse['auth_code'] = $rawTx['AuthCode'] ?? null; $defaultResponse['ref_ret_num'] = $rawTx['HostRefNum'] ?? null; $defaultResponse['masked_number'] = $rawTx['CardMask']; - $defaultResponse['first_amount'] = null !== $rawTx['PurchAmount'] ? $this->formatAmount($rawTx['PurchAmount']) : null; - $defaultResponse['transaction_time'] = null !== $rawTx['InsertDatetime'] ? new \DateTimeImmutable($rawTx['InsertDatetime']) : null; + $defaultResponse['first_amount'] = null !== $rawTx['PurchAmount'] ? $this->valueFormatter->formatAmount($rawTx['PurchAmount'], $txType) : null; + $defaultResponse['transaction_time'] = null !== $rawTx['InsertDatetime'] ? $this->valueFormatter->formatDateTime($rawTx['InsertDatetime'], $txType) : null; if (\in_array( $defaultResponse['transaction_type'], [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::TX_TYPE_PAY_POST_AUTH], @@ -568,7 +580,7 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array */ private function mapSingleHistoryTransaction(array $rawTx): array { - $mappedTx = $this->mapSingleOrderHistoryTransaction($rawTx); + $mappedTx = $this->mapSingleOrderHistoryTransaction($rawTx); $mappedTx['order_id'] = $rawTx['OrderId']; return $mappedTx; diff --git a/src/DataMapper/ResponseDataMapper/PosNetResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/PosNetResponseDataMapper.php index 30090e97..b8027e76 100644 --- a/src/DataMapper/ResponseDataMapper/PosNetResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/PosNetResponseDataMapper.php @@ -7,6 +7,7 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\PosNet; use Mews\Pos\PosInterface; class PosNetResponseDataMapper extends AbstractResponseDataMapper @@ -43,6 +44,14 @@ class PosNetResponseDataMapper extends AbstractResponseDataMapper '0444' => 'bank_call', ]; + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PosNet::class === $gatewayClass; + } + /** * {@inheritDoc} */ @@ -79,8 +88,8 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $defaultResponse['all'] = $rawPaymentResponseData; if (self::TX_APPROVED === $status) { - $defaultResponse['installment_count'] = $this->mapInstallment($rawPaymentResponseData['instInfo']['inst1']); - $defaultResponse['transaction_time'] = new \DateTimeImmutable(); + $defaultResponse['installment_count'] = $this->valueFormatter->formatInstallment($rawPaymentResponseData['instInfo']['inst1'], $txType); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } return $defaultResponse; @@ -128,8 +137,8 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'order_id' => $order['id'], 'remote_order_id' => $oosResolveMerchantDataResponse['xid'] ?? null, 'transaction_security' => $transactionSecurity, - 'amount' => $this->formatAmount((string) $oosResolveMerchantDataResponse['amount']), - 'currency' => $this->mapCurrency((string) $oosResolveMerchantDataResponse['currency']), + 'amount' => $this->valueFormatter->formatAmount((string) $oosResolveMerchantDataResponse['amount'], $txType), + 'currency' => $this->valueMapper->mapCurrency((string) $oosResolveMerchantDataResponse['currency'], $txType), 'proc_return_code' => $procReturnCode, 'status' => $status, 'status_detail' => $this->getStatusDetail($procReturnCode), @@ -190,7 +199,7 @@ public function mapCancelResponse($rawResponseData): array $state = $rawResponseData['state'] ?? null; $transactionType = null; if (null !== $state) { - $transactionType = $this->mapTxType($state); + $transactionType = $this->valueMapper->mapTxType($state); } $results = [ @@ -213,10 +222,10 @@ public function mapCancelResponse($rawResponseData): array $txResults = []; if (null !== $transactionDetails) { $txResults = [ - 'auth_code' => $transactionDetails['authCode'] ?? null, - 'transaction_id' => null, - 'ref_ret_num' => $transactionDetails['hostlogkey'] ?? null, - 'date' => $transactionDetails['tranDate'] ?? null, + 'auth_code' => $transactionDetails['authCode'] ?? null, + 'transaction_id' => null, + 'ref_ret_num' => $transactionDetails['hostlogkey'] ?? null, + 'date' => $transactionDetails['tranDate'] ?? null, ]; } @@ -228,6 +237,7 @@ public function mapCancelResponse($rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $status = self::TX_DECLINED; $errorCode = $rawResponseData['respCode'] ?? null; @@ -245,14 +255,14 @@ public function mapStatusResponse(array $rawResponseData): array $transactionDetails = $rawResponseData['transactions']['transaction']; $txResults = [ - 'currency' => $this->mapCurrency($transactionDetails['currencyCode']), - 'first_amount' => $this->formatStatusAmount($transactionDetails['amount']), - 'transaction_type' => null === $transactionDetails['state'] ? null : $this->mapTxType($transactionDetails['state']), + 'currency' => $this->valueMapper->mapCurrency($transactionDetails['currencyCode'], $txType), + 'first_amount' => $this->valueFormatter->formatAmount($transactionDetails['amount'], $txType), + 'transaction_type' => null === $transactionDetails['state'] ? null : $this->valueMapper->mapTxType($transactionDetails['state']), 'order_id' => $transactionDetails['orderID'], 'auth_code' => $transactionDetails['authCode'] ?? null, 'ref_ret_num' => $transactionDetails['hostlogkey'] ?? null, // tranDate ex: 2019-10-10 11:21:14.281 - 'transaction_time' => isset($transactionDetails['tranDate']) ? new \DateTimeImmutable($transactionDetails['tranDate']) : null, + 'transaction_time' => isset($transactionDetails['tranDate']) ? $this->valueFormatter->formatDateTime($transactionDetails['tranDate'], $txType) : null, ]; } @@ -271,6 +281,7 @@ public function mapStatusResponse(array $rawResponseData): array */ public function mapOrderHistoryResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_ORDER_HISTORY; $status = self::TX_DECLINED; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $errorCode = $rawResponseData['respCode'] ?? null; @@ -298,9 +309,9 @@ public function mapOrderHistoryResponse(array $rawResponseData): array if (count($transactionDetails) > 1) { foreach ($transactionDetails as $key => $_transaction) { if ($key > 0) { - $currency = $this->mapCurrency($_transaction['currencyCode']); + $currency = $this->valueMapper->mapCurrency($_transaction['currencyCode'], $txType); $refunds[] = [ - 'amount' => (float) $_transaction['amount'], + 'amount' => $this->valueFormatter->formatAmount($_transaction['amount'], $txType), 'currency' => $currency, 'auth_code' => $_transaction['authCode'], 'date' => $_transaction['tranDate'], @@ -311,16 +322,16 @@ public function mapOrderHistoryResponse(array $rawResponseData): array } $txResults = [ - 'auth_code' => $authCode, - 'transaction_id' => null, - 'ref_ret_num' => $transactionDetails['hostlogkey'] ?? null, - 'date' => $transactionDetails['tranDate'] ?? null, + 'auth_code' => $authCode, + 'transaction_id' => null, + 'ref_ret_num' => $transactionDetails['hostlogkey'] ?? null, + 'date' => $transactionDetails['tranDate'] ?? null, ]; } $transactionType = null; if (null !== $state) { - $transactionType = $this->mapTxType($state); + $transactionType = $this->valueMapper->mapTxType($state); } $results = [ @@ -457,8 +468,8 @@ private function map3dPaymentResponseCommon(array $rawPaymentResponseData, strin $defaultResponse['error_message'] = $rawPaymentResponseData['respText'] ?? null; $defaultResponse['all'] = $rawPaymentResponseData; if (self::TX_APPROVED === $status) { - $defaultResponse['installment_count'] = $this->mapInstallment($rawPaymentResponseData['instInfo']['inst1']); - $defaultResponse['transaction_time'] = new \DateTimeImmutable(); + $defaultResponse['installment_count'] = $this->valueFormatter->formatInstallment($rawPaymentResponseData['instInfo']['inst1'], $txType); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } return $defaultResponse; diff --git a/src/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapper.php index 2009954b..d070a400 100644 --- a/src/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapper.php @@ -7,8 +7,8 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\PosNetV1Pos; use Mews\Pos\PosInterface; -use Psr\Log\LoggerInterface; class PosNetV1PosResponseDataMapper extends AbstractResponseDataMapper { @@ -45,36 +45,13 @@ class PosNetV1PosResponseDataMapper extends AbstractResponseDataMapper ]; /** - * @param array $currencyMappings - * @param array $txTypeMappings - * @param array $secureTypeMappings - * @param LoggerInterface $logger + * @inheritDoc */ - public function __construct(array $currencyMappings, array $txTypeMappings, array $secureTypeMappings, LoggerInterface $logger) + public static function supports(string $gatewayClass): bool { - parent::__construct($currencyMappings, $txTypeMappings, $secureTypeMappings, $logger); - - $this->currencyMappings += [ - '949' => PosInterface::CURRENCY_TRY, - '840' => PosInterface::CURRENCY_USD, - '978' => PosInterface::CURRENCY_EUR, - '826' => PosInterface::CURRENCY_GBP, - '392' => PosInterface::CURRENCY_JPY, - '643' => PosInterface::CURRENCY_RUB, - ]; + return PosNetV1Pos::class === $gatewayClass; } - /** - * Order Status Codes - * - * @var array - */ - protected array $orderStatusMappings = [ - PosInterface::TX_TYPE_PAY_AUTH => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - PosInterface::TX_TYPE_CANCEL => PosInterface::PAYMENT_STATUS_CANCELED, - PosInterface::TX_TYPE_REFUND => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, - ]; - /** * {@inheritDoc} */ @@ -111,8 +88,11 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType 'all' => $rawPaymentResponseData, ]; if (self::TX_APPROVED === $status) { - $mappedResponse['installment_count'] = $this->mapInstallment($rawPaymentResponseData['InstallmentData']['InstallmentCount']); - $mappedResponse['transaction_time'] = new \DateTimeImmutable(); + $mappedResponse['installment_count'] = $this->valueFormatter->formatInstallment( + $rawPaymentResponseData['InstallmentData']['InstallmentCount'], + $txType + ); + $mappedResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } return $this->mergeArraysPreferNonNullValues($defaultResponse, $mappedResponse); @@ -133,7 +113,7 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen $threeDAuthApproved = $this->is3dAuthSuccess($mdStatus); $transactionSecurity = null === $mdStatus ? null : $this->mapResponseTransactionSecurity($mdStatus); /** @var PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType */ - $txType = $this->mapTxType($raw3DAuthResponseData['TranType']) ?? $txType; + $txType = $this->valueMapper->mapTxType($raw3DAuthResponseData['TranType']) ?? $txType; $threeDResponse = [ 'order_id' => $order['id'], @@ -141,11 +121,11 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen 'transaction_security' => $transactionSecurity, 'masked_number' => $raw3DAuthResponseData['CCPrefix'], // Kredi Kartı Numarası ön eki: 450634 'proc_return_code' => null, - 'currency' => isset($raw3DAuthResponseData['CurrencyCode']) ? $this->mapCurrency($raw3DAuthResponseData['CurrencyCode']) : null, + 'currency' => isset($raw3DAuthResponseData['CurrencyCode']) ? $this->valueMapper->mapCurrency($raw3DAuthResponseData['CurrencyCode'], $txType) : null, 'status' => self::TX_DECLINED, 'md_status' => $mdStatus, 'md_error_message' => $threeDAuthApproved ? null : $raw3DAuthResponseData['MdErrorMessage'], - 'amount' => $this->formatAmount($raw3DAuthResponseData['Amount']), + 'amount' => $this->valueFormatter->formatAmount($raw3DAuthResponseData['Amount'], $txType), '3d_all' => $raw3DAuthResponseData, ]; @@ -192,7 +172,7 @@ public function mapCancelResponse($rawResponseData): array return [ 'auth_code' => null, - 'transaction_id' => null, + 'transaction_id' => null, 'ref_ret_num' => null, 'group_id' => null, 'transaction_type' => null, @@ -210,6 +190,7 @@ public function mapCancelResponse($rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $status = self::TX_DECLINED; $procReturnCode = $this->getProcReturnCode($rawResponseData); @@ -243,13 +224,15 @@ public function mapStatusResponse(array $rawResponseData): array return $defaultResponse; } - $defaultResponse['first_amount'] = $this->formatStatusAmount($rawTx['Amount']); - $defaultResponse['transaction_time'] = new \DateTimeImmutable($rawTx['TransactionDate']); - $defaultResponse['currency'] = $this->mapCurrency($rawTx['CurrencyCode']); + $defaultResponse['first_amount'] = $this->valueFormatter->formatAmount($rawTx['Amount'], $txType); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime($rawTx['TransactionDate'], $txType); + $defaultResponse['currency'] = $this->valueMapper->mapCurrency($rawTx['CurrencyCode'], $txType); $defaultResponse['masked_number'] = $rawTx['CardNo']; $defaultResponse['order_id'] = $rawTx['OrderId']; - $defaultResponse['transaction_type'] = $this->mapTxType($rawTx['TransactionType']); - $defaultResponse['order_status'] = $this->orderStatusMappings[$defaultResponse['transaction_type']] ?? null; + $defaultResponse['transaction_type'] = $this->valueMapper->mapTxType($rawTx['TransactionType']); + if (null !== $defaultResponse['transaction_type']) { + $defaultResponse['order_status'] = $this->valueMapper->mapOrderStatus($defaultResponse['transaction_type']); + } if (PosInterface::TX_TYPE_REFUND === $defaultResponse['transaction_type']) { $defaultResponse['refund_time'] = $defaultResponse['transaction_time']; @@ -341,28 +324,6 @@ protected function getProcReturnCode(array $response): ?string return $response['ServiceResponseData']['ResponseCode'] ?? null; } - /** - * "100001" => 1000.01 - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return ((int) $amount) / 100; - } - - /** - * "1,16" => 1.16 - * @param string $amount - * - * @return float - */ - protected function formatStatusAmount(string $amount): float - { - return (float) \str_replace(',', '.', \str_replace('.', '', $amount)); - } - /** * @phpstan-param PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType * @phpstan-param PosInterface::MODEL_3D_* $paymentModel @@ -392,7 +353,7 @@ private function map3DPaymentResponseCommon(array $rawPaymentResponseData, strin } $mappedResponse = [ - 'transaction_id' => null, + 'transaction_id' => null, 'auth_code' => $rawPaymentResponseData['AuthCode'] ?? null, 'ref_ret_num' => $rawPaymentResponseData['ReferenceCode'] ?? null, 'proc_return_code' => $procReturnCode, @@ -404,8 +365,11 @@ private function map3DPaymentResponseCommon(array $rawPaymentResponseData, strin ]; if (self::TX_APPROVED === $status) { - $mappedResponse['installment_count'] = $this->mapInstallment($rawPaymentResponseData['InstallmentData']['InstallmentCount']); - $mappedResponse['transaction_time'] = new \DateTimeImmutable(); + $mappedResponse['installment_count'] = $this->valueFormatter->formatInstallment( + $rawPaymentResponseData['InstallmentData']['InstallmentCount'], + $txType + ); + $mappedResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } return $this->mergeArraysPreferNonNullValues($defaultResponse, $mappedResponse); diff --git a/src/DataMapper/ResponseDataMapper/ResponseDataMapperInterface.php b/src/DataMapper/ResponseDataMapper/ResponseDataMapperInterface.php index 3e58446e..f41d241a 100644 --- a/src/DataMapper/ResponseDataMapper/ResponseDataMapperInterface.php +++ b/src/DataMapper/ResponseDataMapper/ResponseDataMapperInterface.php @@ -6,6 +6,8 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; +use Mews\Pos\PosInterface; + interface ResponseDataMapperInterface extends PaymentResponseMapperInterface, NonPaymentResponseMapperInterface { /** @var string */ @@ -13,4 +15,11 @@ interface ResponseDataMapperInterface extends PaymentResponseMapperInterface, No /** @var string */ public const TX_DECLINED = 'declined'; + + /** + * @param class-string $gatewayClass + * + * @return bool + */ + public static function supports(string $gatewayClass): bool; } diff --git a/src/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapper.php index dddf8130..37e6baf8 100644 --- a/src/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapper.php @@ -7,6 +7,7 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\ToslaPos; use Mews\Pos\PosInterface; /** @@ -30,31 +31,11 @@ class ToslaPosResponseDataMapper extends AbstractResponseDataMapper ]; /** - * Order Status Codes - * - * @var array - */ - protected array $orderStatusMappings = [ - 0 => PosInterface::PAYMENT_STATUS_ERROR, - 1 => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 2 => PosInterface::PAYMENT_STATUS_CANCELED, - 3 => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED, - 4 => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, - 5 => PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED, - ]; - - /** - * @param int $txType - * - * @return string + * @inheritDoc */ - public function mapTxType($txType): ?string + public static function supports(string $gatewayClass): bool { - if (0 === $txType) { - return null; - } - - return parent::mapTxType((string) $txType); + return ToslaPos::class === $gatewayClass; } /** @@ -82,7 +63,7 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType 'currency' => $order['currency'], 'amount' => $order['amount'], 'transaction_id' => $rawPaymentResponseData['TransactionId'], - 'transaction_time' => self::TX_APPROVED === $status ? new \DateTimeImmutable() : null, + 'transaction_time' => self::TX_APPROVED === $status ? $this->valueFormatter->formatDateTime('now', $txType) : null, 'transaction_type' => null, 'ref_ret_num' => $rawPaymentResponseData['HostReferenceNumber'], 'proc_return_code' => $procReturnCode, @@ -117,7 +98,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $procReturnCode = $raw3DAuthResponseData['BankResponseCode']; $mdStatus = $this->extractMdStatus($raw3DAuthResponseData); - $transactionStatus = $this->orderStatusMappings[$raw3DAuthResponseData['RequestStatus']] ?? null; + $transactionStatus = $this->valueMapper->mapOrderStatus($raw3DAuthResponseData['RequestStatus']); if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode && PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $transactionStatus && $this->is3dAuthSuccess($mdStatus) @@ -145,7 +126,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp $response['error_message'] = $raw3DAuthResponseData['BankResponseMessage']; $response['error_code'] = $procReturnCode; } else { - $response['transaction_time'] = new \DateTimeImmutable(); + $response['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } return $this->mergeArraysPreferNonNullValues($defaultResponse, $response); @@ -222,6 +203,7 @@ public function mapCancelResponse(array $rawResponseData): array */ public function mapStatusResponse(array $rawResponseData): array { + $txType = PosInterface::TX_TYPE_STATUS; $rawResponseData = $this->emptyStringsToNull($rawResponseData); $procReturnCode = $this->getProcReturnCode($rawResponseData); $errorCode = $rawResponseData['Code']; @@ -237,8 +219,8 @@ public function mapStatusResponse(array $rawResponseData): array $defaultResponse['auth_code'] = $rawResponseData['AuthCode']; $defaultResponse['transaction_id'] = $rawResponseData['TransactionId'] > 0 ? $rawResponseData['TransactionId'] : null; $defaultResponse['masked_number'] = $rawResponseData['CardNo']; - $defaultResponse['order_status'] = $this->orderStatusMappings[$rawResponseData['RequestStatus']] ?? $rawResponseData['RequestStatus']; - $defaultResponse['transaction_type'] = $this->mapTxType($rawResponseData['TransactionType']); + $defaultResponse['order_status'] = $this->valueMapper->mapOrderStatus($rawResponseData['RequestStatus']); + $defaultResponse['transaction_type'] = $this->valueMapper->mapTxType($rawResponseData['TransactionType']); $defaultResponse['status'] = $status; $defaultResponse['status_detail'] = $this->getStatusDetail($errorCode); @@ -251,13 +233,13 @@ public function mapStatusResponse(array $rawResponseData): array if (self::TX_APPROVED === $status) { $defaultResponse['installment_count'] = $rawResponseData['InstallmentCount']; if ($rawResponseData['Currency'] > 0) { - $defaultResponse['currency'] = $this->mapCurrency($rawResponseData['Currency']); + $defaultResponse['currency'] = $this->valueMapper->mapCurrency($rawResponseData['Currency'], $txType); // ex: 20231209154531 - $defaultResponse['transaction_time'] = new \DateTimeImmutable($rawResponseData['CreateDate']); - $defaultResponse['first_amount'] = $this->formatAmount($rawResponseData['Amount']); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime($rawResponseData['CreateDate'], $txType); + $defaultResponse['first_amount'] = $this->valueFormatter->formatAmount($rawResponseData['Amount'], $txType); } - $defaultResponse['refund_amount'] = $rawResponseData['RefundedAmount'] > 0 ? $this->formatAmount($rawResponseData['RefundedAmount']) : null; + $defaultResponse['refund_amount'] = $rawResponseData['RefundedAmount'] > 0 ? $this->valueFormatter->formatAmount($rawResponseData['RefundedAmount'], $txType) : null; if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode && $isPaymentTransaction) { $defaultResponse['capture_amount'] = $defaultResponse['first_amount']; @@ -360,17 +342,6 @@ protected function getProcReturnCode(array $response): ?string return $response['BankResponseCode'] ?? null; } - /** - * "100001" => 1000.01 - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return ((float) $amount) / 100; - } - /** * @param array $rawResponseData * @@ -378,9 +349,10 @@ protected function formatAmount(string $amount): float */ public function mapSingleHistoryResponse(array $rawResponseData): array { - $procReturnCode = $this->getProcReturnCode($rawResponseData); - $errorCode = $rawResponseData['Code']; - $status = self::TX_DECLINED; + $txType = PosInterface::TX_TYPE_HISTORY; + $procReturnCode = $this->getProcReturnCode($rawResponseData); + $errorCode = $rawResponseData['Code']; + $status = self::TX_DECLINED; if (0 === $errorCode) { $status = self::TX_APPROVED; } @@ -392,8 +364,8 @@ public function mapSingleHistoryResponse(array $rawResponseData): array $defaultResponse['auth_code'] = $rawResponseData['AuthCode']; $defaultResponse['transaction_id'] = $rawResponseData['TransactionId'] > 0 ? $rawResponseData['TransactionId'] : null; $defaultResponse['masked_number'] = $rawResponseData['CardNo']; - $defaultResponse['order_status'] = $this->orderStatusMappings[$rawResponseData['RequestStatus']] ?? $rawResponseData['RequestStatus']; - $defaultResponse['transaction_type'] = $this->mapTxType($rawResponseData['TransactionType']); + $defaultResponse['order_status'] = $this->valueMapper->mapOrderStatus($rawResponseData['RequestStatus']); + $defaultResponse['transaction_type'] = $this->valueMapper->mapTxType($rawResponseData['TransactionType']); $defaultResponse['status'] = $status; $defaultResponse['status_detail'] = $this->getStatusDetail($errorCode); @@ -405,15 +377,15 @@ public function mapSingleHistoryResponse(array $rawResponseData): array if (self::TX_APPROVED === $status) { if ($rawResponseData['Currency'] > 0) { - $defaultResponse['currency'] = $this->mapCurrency($rawResponseData['Currency']); + $defaultResponse['currency'] = $this->valueMapper->mapCurrency($rawResponseData['Currency'], $txType); // ex: 20231209154531 - $defaultResponse['transaction_time'] = new \DateTimeImmutable($rawResponseData['CreateDate']); - $defaultResponse['first_amount'] = $this->formatAmount($rawResponseData['Amount']); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime($rawResponseData['CreateDate'], $txType); + $defaultResponse['first_amount'] = $this->valueFormatter->formatAmount($rawResponseData['Amount'], $txType); } if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode && $isPaymentTransaction) { $captureAmount = (float) $rawResponseData['MerchantCommissionAmount'] + (float) $rawResponseData['NetAmount']; - $defaultResponse['capture_amount'] = $this->formatAmount((string) $captureAmount); + $defaultResponse['capture_amount'] = $this->valueFormatter->formatAmount((string) $captureAmount, $txType); $defaultResponse['capture'] = $defaultResponse['first_amount'] <= $defaultResponse['capture_amount']; $defaultResponse['capture_time'] = $defaultResponse['transaction_time']; } diff --git a/src/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapper.php b/src/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapper.php index c6f4ee30..104cd596 100644 --- a/src/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapper.php +++ b/src/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapper.php @@ -7,6 +7,7 @@ namespace Mews\Pos\DataMapper\ResponseDataMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\VakifKatilimPos; use Mews\Pos\PosInterface; class VakifKatilimPosResponseDataMapper extends AbstractResponseDataMapper @@ -23,16 +24,12 @@ class VakifKatilimPosResponseDataMapper extends AbstractResponseDataMapper ]; /** - * Order Status Codes - * - * @var array + * @inheritDoc */ - protected array $orderStatusMappings = [ - 1 => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, - 4 => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, - 5 => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED, - 6 => PosInterface::PAYMENT_STATUS_CANCELED, - ]; + public static function supports(string $gatewayClass): bool + { + return VakifKatilimPos::class === $gatewayClass; + } /** * {@inheritDoc} @@ -73,20 +70,20 @@ public function mapPaymentResponse(array $rawPaymentResponseData, string $txType $vPosMessage = $rawPaymentResponseData['VPosMessage']; // ProvisionNumber: Başarılı işlemlerde kart bankasının vermiş olduğu otorizasyon numarasıdır. - $result['auth_code'] = $rawPaymentResponseData['ProvisionNumber']; + $result['auth_code'] = $rawPaymentResponseData['ProvisionNumber']; // RRN: Pos bankası tarafında verilen referans işlem referans numarasıdır. $result['ref_ret_num'] = $rawPaymentResponseData['RRN']; $result['batch_num'] = $vPosMessage['BatchID']; // Stan: Pos bankası tarafında verilen referans işlem referans numarasıdır. $result['transaction_id'] = $rawPaymentResponseData['Stan']; $result['masked_number'] = $vPosMessage['CardNumber']; - $result['amount'] = $this->formatAmount($vPosMessage['Amount']); - $result['currency'] = $this->mapCurrency($vPosMessage['CurrencyCode']); - $result['installment_count'] = $this->mapInstallment($vPosMessage['InstallmentCount']); + $result['amount'] = $this->valueFormatter->formatAmount($vPosMessage['Amount'], $txType); + $result['currency'] = $this->valueMapper->mapCurrency($vPosMessage['CurrencyCode'], $txType); + $result['installment_count'] = $this->valueFormatter->formatInstallment($vPosMessage['InstallmentCount'], $txType); if ('0001-01-01T00:00:00' !== $rawPaymentResponseData['TransactionTime'] && '00010101T00:00:00' !== $rawPaymentResponseData['TransactionTime']) { - $result['transaction_time'] = new \DateTimeImmutable($rawPaymentResponseData['TransactionTime']); + $result['transaction_time'] = $this->valueFormatter->formatDateTime($rawPaymentResponseData['TransactionTime'], $txType); } else { - $result['transaction_time'] = new \DateTimeImmutable(); + $result['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } @@ -138,7 +135,7 @@ public function map3DPayResponseData(array $raw3DAuthResponseData, string $txTyp public function map3DHostResponseData(array $raw3DAuthResponseData, string $txType, array $order): array { $this->logger->debug('mapping 3D payment data', [ - '3d_auth_response' => $raw3DAuthResponseData, + '3d_auth_response' => $raw3DAuthResponseData, ]); $raw3DAuthResponseData = $this->emptyStringsToNull($raw3DAuthResponseData); @@ -176,7 +173,7 @@ public function map3DHostResponseData(array $raw3DAuthResponseData, string $txTy // Stan: Pos bankası tarafında verilen referans işlem referans numarasıdır. $defaultResponse['transaction_id'] = $raw3DAuthResponseData['Stan']; $defaultResponse['auth_code'] = $raw3DAuthResponseData['ProvisionNumber'] ?? null; - $defaultResponse['transaction_time'] = new \DateTimeImmutable(); + $defaultResponse['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); return $defaultResponse; } @@ -191,7 +188,10 @@ public function mapStatusResponse(array $rawResponseData): array $procReturnCode = $this->getProcReturnCode($rawResponseData); if (self::PROCEDURE_SUCCESS_CODE === $procReturnCode) { - $mappedTransactions = $this->mapSingleHistoryTransaction($rawResponseData['VPosOrderData']['OrderContract']); + $mappedTransactions = $this->mapSingleHistoryTransaction( + $rawResponseData['VPosOrderData']['OrderContract'], + PosInterface::TX_TYPE_STATUS + ); return \array_merge($defaultResponse, $mappedTransactions); } @@ -278,7 +278,7 @@ public function mapHistoryResponse(array $rawResponseData): array if (isset($rawResponseData['VPosOrderData']['OrderContract'])) { foreach ($rawResponseData['VPosOrderData']['OrderContract'] as $tx) { - $mappedTransactions[] = $this->mapSingleHistoryTransaction($tx); + $mappedTransactions[] = $this->mapSingleHistoryTransaction($tx, PosInterface::TX_TYPE_HISTORY); } } @@ -321,7 +321,7 @@ public function mapOrderHistoryResponse(array $rawResponseData): array $remoteOrderId = null; if (isset($rawResponseData['VPosOrderData']['OrderContract'])) { foreach ($rawResponseData['VPosOrderData']['OrderContract'] as $tx) { - $mappedTransactions[] = $this->mapSingleOrderHistoryTransaction($tx); + $mappedTransactions[] = $this->mapSingleOrderHistoryTransaction($tx, PosInterface::TX_TYPE_ORDER_HISTORY); $orderId = $tx['MerchantOrderId']; $remoteOrderId = $tx['OrderId']; } @@ -364,17 +364,6 @@ public function extractMdStatus(array $raw3DAuthResponseData): ?string return $this->getProcReturnCode($raw3DAuthResponseData); } - /** - * "101" => 1.01 - * @param string $amount - * - * @return float - */ - protected function formatAmount(string $amount): float - { - return (float) $amount / 100; - } - /** * Get ProcReturnCode * @@ -387,20 +376,6 @@ protected function getProcReturnCode(array $response): ?string return $response['ResponseCode'] ?? null; } - /** - * @param string $currency currency code that is accepted by bank - * - * @return PosInterface::CURRENCY_*|string - */ - protected function mapCurrency(string $currency): string - { - // 949 => 0949; for the request gateway wants 0949 code, but in response they send 949 code. - $currencyNormalized = \str_pad($currency, 4, '0', STR_PAD_LEFT); - - return parent::mapCurrency($currencyNormalized); - } - - /** * @param string $mdStatus * @@ -449,12 +424,13 @@ protected function map3DCommonResponseData(array $raw3DAuthResponseData): array /** * @param array $rawTx + * @param PosInterface::TX_TYPE_* $txType * * @return array */ - private function mapSingleHistoryTransaction(array $rawTx): array + private function mapSingleHistoryTransaction(array $rawTx, string $txType): array { - $response = $this->mapSingleOrderHistoryTransaction($rawTx); + $response = $this->mapSingleOrderHistoryTransaction($rawTx, $txType); $response['order_id'] = $rawTx['MerchantOrderId']; $response['remote_order_id'] = $rawTx['OrderId']; @@ -464,10 +440,11 @@ private function mapSingleHistoryTransaction(array $rawTx): array /** * @param array $rawTx + * @param PosInterface::TX_TYPE_* $txType * * @return array */ - private function mapSingleOrderHistoryTransaction(array $rawTx): array + private function mapSingleOrderHistoryTransaction(array $rawTx, string $txType): array { $procReturnCode = $this->getProcReturnCode($rawTx); $status = self::TX_DECLINED; @@ -482,22 +459,23 @@ private function mapSingleOrderHistoryTransaction(array $rawTx): array $defaultResponse['status_detail'] = $this->getStatusDetail($procReturnCode); $defaultResponse['error_code'] = self::TX_APPROVED === $status ? null : $procReturnCode; $defaultResponse['error_message'] = self::TX_APPROVED === $status ? null : $rawTx['ResponseExplain']; - $defaultResponse['currency'] = null !== $rawTx['FEC'] ? $this->mapCurrency($rawTx['FEC']) : null; - $defaultResponse['payment_model'] = null !== $rawTx['TransactionSecurity'] ? $this->mapSecurityType($rawTx['TransactionSecurity']) : null; + $defaultResponse['currency'] = null !== $rawTx['FEC'] ? $this->valueMapper->mapCurrency($rawTx['FEC'], $txType) : null; + $defaultResponse['payment_model'] = null !== $rawTx['TransactionSecurity'] ? $this->valueMapper->mapSecureType($rawTx['TransactionSecurity'], $txType) : null; $defaultResponse['ref_ret_num'] = $rawTx['RRN']; $defaultResponse['transaction_id'] = $rawTx['Stan']; - $defaultResponse['transaction_time'] = null !== $rawTx['OrderDate'] ? new \DateTimeImmutable($rawTx['OrderDate']) : null; + $defaultResponse['transaction_time'] = null !== $rawTx['OrderDate'] ? $this->valueFormatter->formatDateTime($rawTx['OrderDate'], $txType) : null; if (self::TX_APPROVED === $status) { $defaultResponse['auth_code'] = $rawTx['ProvNumber'] ?? null; - $defaultResponse['installment_count'] = $this->mapInstallment($rawTx['InstallmentCount']); + $defaultResponse['installment_count'] = $this->valueFormatter->formatInstallment($rawTx['InstallmentCount'], $txType); $defaultResponse['masked_number'] = $rawTx['CardNumber']; - $defaultResponse['first_amount'] = null === $rawTx['FirstAmount'] ? null : (float) $rawTx['FirstAmount']; - $defaultResponse['order_status'] = $this->orderStatusMappings[$rawTx['LastOrderStatus']] ?? $rawTx['LastOrderStatusDescription']; - $initialOrderStatus = $this->orderStatusMappings[$rawTx['OrderStatus']] ?? null; + $defaultResponse['first_amount'] = null === $rawTx['FirstAmount'] ? null : $this->valueFormatter->formatAmount($rawTx['FirstAmount'], $txType); + $rawLastOrderStatus = $rawTx['LastOrderStatus'] ?? $rawTx['LastOrderStatusDescription']; + $defaultResponse['order_status'] = null === $rawLastOrderStatus ? null : $this->valueMapper->mapOrderStatus($rawLastOrderStatus); + $initialOrderStatus = null === $rawTx['OrderStatus'] ? null : $this->valueMapper->mapOrderStatus($rawTx['OrderStatus']); if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $initialOrderStatus) { - $defaultResponse['capture_amount'] = isset($rawTx['TranAmount']) ? (float) $rawTx['TranAmount'] : 0; + $defaultResponse['capture_amount'] = isset($rawTx['TranAmount']) ? $this->valueFormatter->formatAmount($rawTx['TranAmount'], $txType) : 0; $defaultResponse['capture'] = $defaultResponse['first_amount'] === $defaultResponse['capture_amount']; if ($defaultResponse['capture']) { $defaultResponse['capture_time'] = $defaultResponse['transaction_time']; @@ -562,13 +540,13 @@ private function map3DPaymentPaymentResponse(array $rawPaymentResponseData, stri $result['batch_num'] = $vPosMessage['BatchId']; $result['auth_code'] = $rawPaymentResponseData['ProvisionNumber'] ?? null; $result['masked_number'] = $vPosMessage['CardNumber'] ?? null; - $result['currency'] = isset($vPosMessage['CurrencyCode']) ? $this->mapCurrency($vPosMessage['CurrencyCode']) : $order['currency']; - $result['amount'] = $this->formatAmount($vPosMessage['Amount']); - $result['installment_count'] = $this->mapInstallment($vPosMessage['InstallmentCount']); + $result['currency'] = isset($vPosMessage['CurrencyCode']) ? $this->valueMapper->mapCurrency($vPosMessage['CurrencyCode'], $txType) : $order['currency']; + $result['amount'] = $this->valueFormatter->formatAmount($vPosMessage['Amount'], $txType); + $result['installment_count'] = $this->valueFormatter->formatInstallment($vPosMessage['InstallmentCount'], $txType); if ('0001-01-01T00:00:00' !== $rawPaymentResponseData['TransactionTime'] && '00010101T00:00:00' !== $rawPaymentResponseData['TransactionTime']) { - $result['transaction_time'] = new \DateTimeImmutable($rawPaymentResponseData['TransactionTime']); + $result['transaction_time'] = $this->valueFormatter->formatDateTime($rawPaymentResponseData['TransactionTime'], $txType); } else { - $result['transaction_time'] = new \DateTimeImmutable(); + $result['transaction_time'] = $this->valueFormatter->formatDateTime('now', $txType); } $this->logger->debug('mapped payment response', $result); diff --git a/src/DataMapper/ResponseValueFormatter/AbstractResponseValueFormatter.php b/src/DataMapper/ResponseValueFormatter/AbstractResponseValueFormatter.php new file mode 100644 index 00000000..a5cb2eae --- /dev/null +++ b/src/DataMapper/ResponseValueFormatter/AbstractResponseValueFormatter.php @@ -0,0 +1,36 @@ + 1 ? $inst : 0; + } + + /** + * @inheritDoc + */ + public function formatAmount($amount, string $txType): float + { + return (float) $amount; + } + + /** + * @inheritdoc + */ + public function formatDateTime(string $dateTime, string $txType): \DateTimeImmutable + { + return new \DateTimeImmutable($dateTime); + } +} diff --git a/src/DataMapper/ResponseValueFormatter/BasicResponseValueFormatter.php b/src/DataMapper/ResponseValueFormatter/BasicResponseValueFormatter.php new file mode 100644 index 00000000..02fd56a1 --- /dev/null +++ b/src/DataMapper/ResponseValueFormatter/BasicResponseValueFormatter.php @@ -0,0 +1,26 @@ + 1000.01 + * @inheritDoc + */ + public function formatAmount($amount, string $txType): float + { + return ((float) $amount) / 100; + } +} diff --git a/src/DataMapper/ResponseValueFormatter/InterPosResponseValueFormatter.php b/src/DataMapper/ResponseValueFormatter/InterPosResponseValueFormatter.php new file mode 100644 index 00000000..a8119e95 --- /dev/null +++ b/src/DataMapper/ResponseValueFormatter/InterPosResponseValueFormatter.php @@ -0,0 +1,39 @@ + 0.0 + * 1.056,2 => 1056.2 + * @inheritDoc + */ + public function formatAmount($amount, string $txType): float + { + return (float) \str_replace(',', '.', \str_replace('.', '', (string) $amount)); + } +} diff --git a/src/DataMapper/ResponseValueFormatter/ParamPosResponseValueFormatter.php b/src/DataMapper/ResponseValueFormatter/ParamPosResponseValueFormatter.php new file mode 100644 index 00000000..55acb227 --- /dev/null +++ b/src/DataMapper/ResponseValueFormatter/ParamPosResponseValueFormatter.php @@ -0,0 +1,35 @@ + 1.16 + return (float) \str_replace(',', '.', \str_replace('.', '', (string) $amount)); + } + + return ((int) $amount) / 100; + } +} diff --git a/src/DataMapper/ResponseValueFormatter/ResponseValueFormatterInterface.php b/src/DataMapper/ResponseValueFormatter/ResponseValueFormatterInterface.php new file mode 100644 index 00000000..06fb38fc --- /dev/null +++ b/src/DataMapper/ResponseValueFormatter/ResponseValueFormatterInterface.php @@ -0,0 +1,49 @@ + $gatewayClass + * + * @return bool + */ + public static function supports(string $gatewayClass): bool; + + /** + * @param string|null $installment + * @param PosInterface::TX_TYPE_* $txType transaction type of the API request + * + * @return int<2, max>|0 + */ + public function formatInstallment(?string $installment, string $txType): int; + + + /** + * formats purchase amount + * + * @param string|float $amount + * @param PosInterface::TX_TYPE_* $txType transaction type of the API request + * + * @return float + */ + public function formatAmount($amount, string $txType): float; + + /** + * @param string $dateTime + * @param PosInterface::TX_TYPE_* $txType transaction type of the API request + * + * @return \DateTimeImmutable formatted date time + */ + public function formatDateTime(string $dateTime, string $txType): \DateTimeImmutable; +} diff --git a/src/DataMapper/ResponseValueFormatter/ToslaPosResponseValueFormatter.php b/src/DataMapper/ResponseValueFormatter/ToslaPosResponseValueFormatter.php new file mode 100644 index 00000000..37dac1bb --- /dev/null +++ b/src/DataMapper/ResponseValueFormatter/ToslaPosResponseValueFormatter.php @@ -0,0 +1,37 @@ + */ + protected array $currencyMappings = []; + + /** @var array> */ + protected array $txTypeMappings = []; + + /** @var array */ + protected array $secureTypeMappings = []; + + /** + * @var array + */ + protected array $orderStatusMappings = []; + + /** + * @param array $currencyMappings + * @param array> $txTypeMappings + * @param array $secureTypeMappings + */ + public function __construct( + array $currencyMappings, + array $txTypeMappings, + array $secureTypeMappings + ) { + if ([] !== $currencyMappings) { + $this->currencyMappings = \array_flip($currencyMappings); + } + + if ([] !== $txTypeMappings) { + $this->txTypeMappings = $txTypeMappings; + } + + if ([] !== $secureTypeMappings) { + $this->secureTypeMappings = \array_flip($secureTypeMappings); + } + } + + /** + * @inheritDoc + */ + public function mapTxType($txType, ?string $paymentModel = null): ?string + { + if ([] === $this->txTypeMappings) { + throw new \LogicException('Transaction type mapping is not supported'); + } + + foreach ($this->txTypeMappings as $mappedTxType => $mapping) { + if (\is_array($mapping) && \in_array($txType, $mapping, true)) { + return $mappedTxType; + } + + if ($mapping === $txType) { + return $mappedTxType; + } + } + + return null; + } + + /** + * @inheritDoc + */ + public function mapSecureType(string $securityType, ?string $apiRequestTxType = null): ?string + { + if ([] === $this->secureTypeMappings) { + throw new \LogicException('Secure type mapping is not supported'); + } + + return $this->secureTypeMappings[$securityType] ?? null; + } + + /** + * @inheritDoc + */ + public function mapCurrency($currency, ?string $apiRequestTxType = null): ?string + { + return $this->currencyMappings[$currency] ?? null; + } + + /** + * @inheritDoc + */ + public function mapOrderStatus($orderStatus) + { + if ([] === $this->orderStatusMappings) { + throw new \LogicException('Order status mapping is not supported.'); + } + + return $this->orderStatusMappings[$orderStatus] ?? $orderStatus; + } +} diff --git a/src/DataMapper/ResponseValueMapper/AkbankPosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/AkbankPosResponseValueMapper.php new file mode 100644 index 00000000..7754f312 --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/AkbankPosResponseValueMapper.php @@ -0,0 +1,74 @@ + + */ + protected array $orderStatusMappings = [ + 'N' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 'S' => PosInterface::PAYMENT_STATUS_ERROR, + 'V' => PosInterface::PAYMENT_STATUS_CANCELED, + 'R' => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, + + // status that are return on history request + 'Başarılı' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 'Başarısız' => PosInterface::PAYMENT_STATUS_ERROR, + 'İptal' => PosInterface::PAYMENT_STATUS_CANCELED, + ]; + + /** + * @var array + */ + private array $recurringOrderStatusMappings = [ + 'S' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 'W' => PosInterface::PAYMENT_STATUS_PAYMENT_PENDING, + // when fulfilled payment is canceled + 'V' => PosInterface::PAYMENT_STATUS_CANCELED, + // when unfulfilled payment is canceled + 'C' => PosInterface::PAYMENT_STATUS_CANCELED, + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return AkbankPos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function mapOrderStatus($orderStatus, ?string $preAuthStatus = null, bool $isRecurringOrder = false) + { + if ($isRecurringOrder) { + return $this->recurringOrderStatusMappings[$orderStatus] ?? $orderStatus; + } + + $mappedOrderStatus = $this->orderStatusMappings[$orderStatus] ?? $orderStatus; + /** + * preAuthStatus + * "O": Açık + * "C": Kapalı + */ + if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $mappedOrderStatus && 'O' === $preAuthStatus) { + return PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED; + } + + return $mappedOrderStatus; + } +} diff --git a/src/DataMapper/ResponseValueMapper/BoaPosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/BoaPosResponseValueMapper.php new file mode 100644 index 00000000..3fdcb53e --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/BoaPosResponseValueMapper.php @@ -0,0 +1,52 @@ + PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 4 => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, + 5 => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED, + 6 => PosInterface::PAYMENT_STATUS_CANCELED, + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return KuveytPos::class === $gatewayClass + || KuveytSoapApiPos::class === $gatewayClass + || VakifKatilimPos::class === $gatewayClass; + } + + /** + * in '0949' or '949' formats + * @inheritDoc + */ + public function mapCurrency($currency, ?string $apiRequestTxType = null): ?string + { + // 949 => 0949; for the request gateway wants 0949 code, but in response they send 949 code. + $currencyNormalized = \str_pad((string) $currency, 4, '0', STR_PAD_LEFT); + + return parent::mapCurrency($currencyNormalized, $apiRequestTxType); + } +} diff --git a/src/DataMapper/ResponseValueMapper/EstPosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/EstPosResponseValueMapper.php new file mode 100644 index 00000000..c6e328e9 --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/EstPosResponseValueMapper.php @@ -0,0 +1,66 @@ + + */ + private array $historyResponseTxTypeMappings = [ + /** + * S: Auth/PreAuth/PostAuth + * C: Refund + */ + 'S' => PosInterface::TX_TYPE_PAY_AUTH, + 'C' => PosInterface::TX_TYPE_REFUND, + ]; + + /** + * D : Başarısız işlem + * A : Otorizasyon, gün sonu kapanmadan + * C : Ön otorizasyon kapama, gün sonu kapanmadan + * PN : Bekleyen İşlem + * CNCL : İptal Edilmiş İşlem + * ERR : Hata Almış İşlem + * S : Satış + * R : Teknik İptal gerekiyor + * V : İptal + * @inheritdoc + */ + protected array $orderStatusMappings = [ + 'D' => PosInterface::PAYMENT_STATUS_ERROR, + 'ERR' => PosInterface::PAYMENT_STATUS_ERROR, + 'A' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 'C' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 'S' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 'PN' => PosInterface::PAYMENT_STATUS_PAYMENT_PENDING, + 'CNCL' => PosInterface::PAYMENT_STATUS_CANCELED, + 'V' => PosInterface::PAYMENT_STATUS_CANCELED, + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return EstV3Pos::class === $gatewayClass + || EstPos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function mapTxType($txType, ?string $paymentModel = null): ?string + { + return $this->historyResponseTxTypeMappings[$txType] ?? null; + } +} diff --git a/src/DataMapper/ResponseValueMapper/GarantiPosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/GarantiPosResponseValueMapper.php new file mode 100644 index 00000000..a918f768 --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/GarantiPosResponseValueMapper.php @@ -0,0 +1,162 @@ + + */ + private array $historyResponseCurrencyMapping = [ + 'TL' => PosInterface::CURRENCY_TRY, + 'USD' => PosInterface::CURRENCY_USD, + 'EUR' => PosInterface::CURRENCY_EUR, + 'RUB' => PosInterface::CURRENCY_RUB, + 'JPY' => PosInterface::CURRENCY_JPY, + 'GBP' => PosInterface::CURRENCY_GBP, + ]; + + /** + * @var array + */ + private array $historyResponseTxTypes = [ + 'Satis' => PosInterface::TX_TYPE_PAY_AUTH, + 'On Otorizasyon' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'On Otorizasyon Kapama' => PosInterface::TX_TYPE_PAY_POST_AUTH, + 'Iade' => PosInterface::TX_TYPE_REFUND, + 'Iptal' => PosInterface::TX_TYPE_CANCEL, + // ... Odul Sorgulama + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return GarantiPos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function mapTxType($txType, ?string $paymentModel = null): ?string + { + return $this->historyResponseTxTypes[$txType] ?? parent::mapTxType($txType, $paymentModel); + } + + /** + * @inheritDoc + */ + public function mapSecureType(string $securityType, ?string $apiRequestTxType = null): ?string + { + if (PosInterface::TX_TYPE_HISTORY === $apiRequestTxType) { + // mappings for the field SafeType of history response + // 3D Secure => 3D + // 3D Pay => 3D + // NonSecure => '' + if ('3D' === $securityType) { + return PosInterface::MODEL_3D_SECURE; + } + + if ('' === $securityType) { + return PosInterface::MODEL_NON_SECURE; + } + + return null; + } + + return parent::mapSecureType($securityType, $apiRequestTxType); + } + + /** + * @inheritDoc + */ + public function mapCurrency($currency, ?string $apiRequestTxType = null): ?string + { + if (PosInterface::TX_TYPE_HISTORY === $apiRequestTxType) { + return $this->historyResponseCurrencyMapping[$currency] ?? null; + } + + return parent::mapCurrency($currency, $apiRequestTxType); + } + + /** + * @param PosInterface::TX_TYPE_*|null $requestTxType request transaction type + * @param PosInterface::TX_TYPE_*|null $txType txType of the transaction that is being processed + * + * @inheritDoc + */ + public function mapOrderStatus($orderStatus, ?string $requestTxType = null, ?string $txType = null) + { + if (PosInterface::TX_TYPE_STATUS === $requestTxType) { + // todo ChargeType degere gore belki daha duzgun mapping edebiliriz. + // ChargeType hakkinda dokumantasyonda sadece su bilgi var: + // "İşlem tipinin gösterildiği alandır." + // Alabilicegi degerleri hakkinda bir bilgi bulunmamakta. + if ('WAITINGPOSTAUTH' === $orderStatus) { + return PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED; + } + if ('APPROVED' === $orderStatus) { + // how can we map this status? + return $orderStatus; + } + + return $orderStatus; + } + + if (PosInterface::TX_TYPE_HISTORY === $requestTxType) { + if (null === $txType) { + return $orderStatus; + } + + // $orderStatus possible values: + // Basarili + // Basarisiz + // Iptal + // Onaylandi + + if ('Basarili' === $orderStatus || 'Onaylandi' === $orderStatus) { + if (PosInterface::TX_TYPE_CANCEL === $txType) { + return PosInterface::PAYMENT_STATUS_CANCELED; + } + + if (PosInterface::TX_TYPE_REFUND === $txType) { + // todo how can we decide if order is partially or fully refunded? + return PosInterface::PAYMENT_STATUS_FULLY_REFUNDED; + } + + if (PosInterface::TX_TYPE_PAY_AUTH === $txType || PosInterface::TX_TYPE_PAY_POST_AUTH === $txType) { + return PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED; + } + + if (PosInterface::TX_TYPE_PAY_PRE_AUTH === $txType) { + return PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED; + } + + return $orderStatus; + } + + if ('Iptal' === $orderStatus) { + /** + * todo anlasilmayan durumlar: + * - "Status" => "Iptal", "TrxType" => "Satis" + * - "Status" => "Iptal", "TrxType" => "On Otorizasyon" + * - "Status" => "Iptal", "TrxType" => "Iptal" + * - "Status" => "Iptal", "TrxType" => "Iade" + */ + return $orderStatus; + } + + return PosInterface::PAYMENT_STATUS_ERROR; + } + + return $orderStatus; + } +} diff --git a/src/DataMapper/ResponseValueMapper/InterPosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/InterPosResponseValueMapper.php new file mode 100644 index 00000000..d25992d0 --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/InterPosResponseValueMapper.php @@ -0,0 +1,20 @@ + */ + protected array $currencyMappings = [ + 'TRL' => PosInterface::CURRENCY_TRY, + 'TL' => PosInterface::CURRENCY_TRY, + 'EUR' => PosInterface::CURRENCY_EUR, + 'USD' => PosInterface::CURRENCY_USD, + ]; + + /** @var array */ + protected array $secureTypeMappings = [ + 'NONSECURE' => PosInterface::MODEL_NON_SECURE, + '3D' => PosInterface::MODEL_3D_SECURE, + ]; + + /** + * @var array + */ + protected array $orderStatusMappings = [ + 'FAIL' => PosInterface::PAYMENT_STATUS_ERROR, + 'BANK_FAIL' => PosInterface::PAYMENT_STATUS_ERROR, + 'SUCCESS' => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 'CANCEL' => PosInterface::PAYMENT_STATUS_CANCELED, + 'REFUND' => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, + 'PARTIAL_REFUND' => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED, + ]; + + /** + * @var array + */ + private array $statusRequestTxMappings = [ + 'SALE' => PosInterface::TX_TYPE_PAY_AUTH, + 'PRE_AUTH' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'POST_AUTH' => PosInterface::TX_TYPE_PAY_POST_AUTH, + ]; + + /** + * @var array + */ + private array $historyRequestTxMappings = [ + 'Satış' => PosInterface::TX_TYPE_PAY_AUTH, + 'İptal' => PosInterface::TX_TYPE_CANCEL, + 'İade' => PosInterface::TX_TYPE_REFUND, + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return ParamPos::class === $gatewayClass + || Param3DHostPos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function mapTxType($txType, ?string $paymentModel = null): ?string + { + return $this->statusRequestTxMappings[$txType] + ?? $this->historyRequestTxMappings[$txType] + ?? parent::mapTxType($txType); + } +} diff --git a/src/DataMapper/ResponseValueMapper/PayFlexCPV4PosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/PayFlexCPV4PosResponseValueMapper.php new file mode 100644 index 00000000..094432eb --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/PayFlexCPV4PosResponseValueMapper.php @@ -0,0 +1,20 @@ + PosInterface::MODEL_NON_SECURE, + '2' => PosInterface::MODEL_3D_SECURE, + '3' => PosInterface::MODEL_3D_PAY, + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PayFlexV4Pos::class === $gatewayClass; + } +} diff --git a/src/DataMapper/ResponseValueMapper/PayForPosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/PayForPosResponseValueMapper.php new file mode 100644 index 00000000..f3ebbccf --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/PayForPosResponseValueMapper.php @@ -0,0 +1,20 @@ + + */ + private array $orderStatusCurrencyMappings = [ + '949' => PosInterface::CURRENCY_TRY, + '840' => PosInterface::CURRENCY_USD, + '978' => PosInterface::CURRENCY_EUR, + '826' => PosInterface::CURRENCY_GBP, + '392' => PosInterface::CURRENCY_JPY, + '643' => PosInterface::CURRENCY_RUB, + ]; + + /** + * @inheritDoc + */ + protected array $orderStatusMappings = [ + PosInterface::TX_TYPE_PAY_AUTH => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + PosInterface::TX_TYPE_CANCEL => PosInterface::PAYMENT_STATUS_CANCELED, + PosInterface::TX_TYPE_REFUND => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return PosNetV1Pos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function mapCurrency($currency, ?string $apiRequestTxType = null): ?string + { + if (PosInterface::TX_TYPE_STATUS !== $apiRequestTxType) { + return $this->orderStatusCurrencyMappings[$currency] ?? null; + } + + return parent::mapCurrency($currency, $apiRequestTxType); + } +} diff --git a/src/DataMapper/ResponseValueMapper/ResponseValueMapperInterface.php b/src/DataMapper/ResponseValueMapper/ResponseValueMapperInterface.php new file mode 100644 index 00000000..56af6dd2 --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/ResponseValueMapperInterface.php @@ -0,0 +1,55 @@ + $gatewayClass + * + * @return bool + */ + public static function supports(string $gatewayClass): bool; + + /** + * @param string|int $txType + * + * @return PosInterface::TX_TYPE_*|null + */ + public function mapTxType($txType, ?string $paymentModel = null): ?string; + + /** + * @param string $securityType + * @param PosInterface::TX_TYPE_* $apiRequestTxType the transaction type of the API request. + * + * @return PosInterface::MODEL_*|null + */ + public function mapSecureType(string $securityType, string $apiRequestTxType): ?string; + + /** + * @param string|int $currency + * @param PosInterface::TX_TYPE_* $apiRequestTxType the transaction type of the API request. + * + * @return PosInterface::CURRENCY_*|null + */ + public function mapCurrency($currency, string $apiRequestTxType): ?string; + + /** + * maps order status of status and history requests. + * If the order status is not mapped, it should return the original value. + * + * @param string|int $orderStatus + * + * @return PosInterface::PAYMENT_STATUS_*|string|int + */ + public function mapOrderStatus($orderStatus); +} diff --git a/src/DataMapper/ResponseValueMapper/ToslaPosResponseValueMapper.php b/src/DataMapper/ResponseValueMapper/ToslaPosResponseValueMapper.php new file mode 100644 index 00000000..c0f9458f --- /dev/null +++ b/src/DataMapper/ResponseValueMapper/ToslaPosResponseValueMapper.php @@ -0,0 +1,45 @@ + PosInterface::PAYMENT_STATUS_ERROR, + 1 => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED, + 2 => PosInterface::PAYMENT_STATUS_CANCELED, + 3 => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED, + 4 => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED, + 5 => PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED, + ]; + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass): bool + { + return ToslaPos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function mapTxType($txType, ?string $paymentModel = null): ?string + { + if (0 === $txType) { + return null; + } + + return parent::mapTxType((string) $txType); + } +} diff --git a/src/Entity/Account/AbstractPosAccount.php b/src/Entity/Account/AbstractPosAccount.php index e63c7815..df1a3136 100644 --- a/src/Entity/Account/AbstractPosAccount.php +++ b/src/Entity/Account/AbstractPosAccount.php @@ -6,8 +6,6 @@ namespace Mews\Pos\Entity\Account; -use Mews\Pos\PosInterface; - abstract class AbstractPosAccount { protected string $clientId; @@ -21,9 +19,6 @@ abstract class AbstractPosAccount */ protected ?string $storeKey; - /** @var PosInterface::LANG_* */ - protected string $lang; - /** * bank key name used in configuration file */ @@ -32,21 +27,19 @@ abstract class AbstractPosAccount /** * AbstractPosAccount constructor. * - * @param string $bank - * @param string $clientId - * @param string $username - * @param string $password - * @param PosInterface::LANG_* $lang - * @param string|null $storeKey + * @param string $bank + * @param string $clientId + * @param string $username + * @param string $password + * @param string|null $storeKey */ - public function __construct(string $bank, string $clientId, string $username, string $password, string $lang, ?string $storeKey = null) + public function __construct(string $bank, string $clientId, string $username, string $password, ?string $storeKey = null) { $this->clientId = $clientId; $this->username = $username; $this->password = $password; $this->storeKey = $storeKey; - $this->lang = $lang; - $this->bank = $bank; + $this->bank = $bank; } /** @@ -81,14 +74,6 @@ public function getStoreKey(): ?string return $this->storeKey; } - /** - * @return string - */ - public function getLang(): string - { - return $this->lang; - } - /** * @return string */ diff --git a/src/Entity/Account/AkbankPosAccount.php b/src/Entity/Account/AkbankPosAccount.php index b53ac477..128e7ebe 100644 --- a/src/Entity/Account/AkbankPosAccount.php +++ b/src/Entity/Account/AkbankPosAccount.php @@ -6,20 +6,15 @@ namespace Mews\Pos\Entity\Account; -use Mews\Pos\PosInterface; - class AkbankPosAccount extends AbstractPosAccount { private ?string $subMerchantId; /** - * @phpstan-param PosInterface::LANG_* $lang - * * @param string $bank * @param string $merchantSafeId Üye İş Yeri numarası * @param string $terminalSafeId * @param string $secretKey - * @param string $lang * @param string|null $subMerchantId */ public function __construct( @@ -27,10 +22,9 @@ public function __construct( string $merchantSafeId, string $terminalSafeId, string $secretKey, - string $lang, ?string $subMerchantId = null ) { - parent::__construct($bank, $merchantSafeId, $terminalSafeId, '', $lang, $secretKey); + parent::__construct($bank, $merchantSafeId, $terminalSafeId, '', $secretKey); $this->subMerchantId = $subMerchantId; } diff --git a/src/Entity/Account/GarantiPosAccount.php b/src/Entity/Account/GarantiPosAccount.php index 7973eabe..f5ed5749 100644 --- a/src/Entity/Account/GarantiPosAccount.php +++ b/src/Entity/Account/GarantiPosAccount.php @@ -22,13 +22,12 @@ public function __construct( string $merchantId, string $username, string $password, - string $lang, string $terminalId, ?string $storeKey = null, ?string $refundUsername = null, ?string $refundPassword = null ) { - parent::__construct($bank, $merchantId, $username, $password, $lang, $storeKey); + parent::__construct($bank, $merchantId, $username, $password, $storeKey); $this->terminalId = $terminalId; $this->refundUsername = $refundUsername; $this->refundPassword = $refundPassword; diff --git a/src/Entity/Account/KuveytPosAccount.php b/src/Entity/Account/KuveytPosAccount.php index 8226fb14..6f2f8587 100644 --- a/src/Entity/Account/KuveytPosAccount.php +++ b/src/Entity/Account/KuveytPosAccount.php @@ -6,8 +6,6 @@ namespace Mews\Pos\Entity\Account; -use Mews\Pos\PosInterface; - /** * KuveytPosAccount */ @@ -20,13 +18,12 @@ class KuveytPosAccount extends AbstractPosAccount protected ?string $subMerchantId; /** - * @param string $bank - * @param string $merchantId Mağaza Numarası - * @param string $username POS panelinizden kullanıcı işlemleri sayfasında APİ rolünde kullanıcı oluşturulmalıdır - * @param string $customerId CustomerNumber, Müşteri No - * @param string $storeKey Oluşturulan APİ kullanıcısının şifre bilgisidir. - * @param PosInterface::LANG_* $lang - * @param string|null $subMerchantId + * @param string $bank + * @param string $merchantId Mağaza Numarası + * @param string $username POS panelinizden kullanıcı işlemleri sayfasında APİ rolünde kullanıcı oluşturulmalıdır + * @param string $customerId CustomerNumber, Müşteri No + * @param string $storeKey Oluşturulan APİ kullanıcısının şifre bilgisidir. + * @param string|null $subMerchantId */ public function __construct( string $bank, @@ -34,10 +31,9 @@ public function __construct( string $username, string $customerId, string $storeKey, - string $lang, ?string $subMerchantId = null ) { - parent::__construct($bank, $merchantId, $username, $customerId, $lang, $storeKey); + parent::__construct($bank, $merchantId, $username, $customerId, $storeKey); $this->subMerchantId = $subMerchantId; } diff --git a/src/Entity/Account/ParamPosAccount.php b/src/Entity/Account/ParamPosAccount.php index ea0c07dd..db932003 100644 --- a/src/Entity/Account/ParamPosAccount.php +++ b/src/Entity/Account/ParamPosAccount.php @@ -6,8 +6,6 @@ namespace Mews\Pos\Entity\Account; -use Mews\Pos\PosInterface; - class ParamPosAccount extends AbstractPosAccount { /** @@ -24,6 +22,6 @@ public function __construct( string $password, string $secretKey ) { - parent::__construct($bank, (string) $clientId, $username, $password, PosInterface::LANG_TR, $secretKey); + parent::__construct($bank, (string) $clientId, $username, $password, $secretKey); } } diff --git a/src/Entity/Account/PayForAccount.php b/src/Entity/Account/PayForAccount.php index eef9c41d..88beea94 100644 --- a/src/Entity/Account/PayForAccount.php +++ b/src/Entity/Account/PayForAccount.php @@ -6,8 +6,6 @@ namespace Mews\Pos\Entity\Account; -use Mews\Pos\PosInterface; - class PayForAccount extends AbstractPosAccount { public const MBR_ID_FINANSBANK = '5'; @@ -23,7 +21,6 @@ class PayForAccount extends AbstractPosAccount * @param string $merchantId Üye işyeri numarası. * @param string $userCode Otorizasyon sistemi kullanıcı kodu. * @param string $userPassword Otorizasyon sistemi kullanıcı şifresi. - * @param PosInterface::LANG_* $lang * @param string|null $merchantPass 3D Secure şifresidir. * @param self::MBR_ID_* $mbrId Kurum kodudur. */ @@ -32,7 +29,6 @@ public function __construct( string $merchantId, string $userCode, string $userPassword, - string $lang, ?string $merchantPass = null, string $mbrId = self::MBR_ID_FINANSBANK ) { @@ -43,7 +39,6 @@ public function __construct( $merchantId, $userCode, $userPassword, - $lang, $merchantPass ); } diff --git a/src/Entity/Account/PosNetAccount.php b/src/Entity/Account/PosNetAccount.php index 937dfff1..25a003fa 100644 --- a/src/Entity/Account/PosNetAccount.php +++ b/src/Entity/Account/PosNetAccount.php @@ -16,10 +16,9 @@ public function __construct( string $clientId, string $posNetId, string $terminalId, - string $lang, ?string $storeKey = null ) { - parent::__construct($bank, $clientId, $posNetId, $terminalId, $lang, $storeKey); + parent::__construct($bank, $clientId, $posNetId, $terminalId, $storeKey); } /** diff --git a/src/Entity/Card/AbstractCreditCard.php b/src/Entity/Card/AbstractCreditCard.php index 6a36e0a4..799dedae 100644 --- a/src/Entity/Card/AbstractCreditCard.php +++ b/src/Entity/Card/AbstractCreditCard.php @@ -65,25 +65,9 @@ public function getNumber(): string /** * @inheritDoc */ - public function getExpireYear(string $format = 'y'): string + public function getExpirationDate(): \DateTimeImmutable { - return $this->expDate->format($format); - } - - /** - * @inheritDoc - */ - public function getExpireMonth(string $format = 'm'): string - { - return $this->expDate->format($format); - } - - /** - * @inheritDoc - */ - public function getExpirationDate(string $format = 'ym'): string - { - return $this->expDate->format($format); + return $this->expDate; } /** diff --git a/src/Entity/Card/CreditCardInterface.php b/src/Entity/Card/CreditCardInterface.php index 5ef8c7b8..12fdc73c 100644 --- a/src/Entity/Card/CreditCardInterface.php +++ b/src/Entity/Card/CreditCardInterface.php @@ -30,31 +30,9 @@ interface CreditCardInterface public function getNumber(): string; /** - * returns exp year in 2 digit format - * - * @param string $format - * - * @return string - */ - public function getExpireYear(string $format = 'y'): string; - - /** - * returns exp year in 2 digit format. i.e '01' '02' '12' - * - * @param string $format - * - * @return string - */ - public function getExpireMonth(string $format = 'm'): string; - - /** - * returns card exp date month and year combined. - * - * @param string $format - * - * @return string + * @return \DateTimeImmutable */ - public function getExpirationDate(string $format = 'ym'): string; + public function getExpirationDate(): \DateTimeImmutable; /** * @return string diff --git a/src/Factory/AccountFactory.php b/src/Factory/AccountFactory.php index 072a49cf..1b219ea6 100644 --- a/src/Factory/AccountFactory.php +++ b/src/Factory/AccountFactory.php @@ -25,7 +25,6 @@ class AccountFactory { /** - * @phpstan-param PosInterface::LANG_* $lang * @phpstan-param PosInterface::MODEL_* $model * * @param non-empty-string $bank @@ -34,34 +33,30 @@ class AccountFactory * @param non-empty-string $password * @param non-empty-string $model * @param non-empty-string|null $storeKey - * @param non-empty-string $lang * * @return EstPosAccount * * @throws MissingAccountInfoException */ - public static function createEstPosAccount(string $bank, string $clientId, string $kullaniciAdi, string $password, string $model = PosInterface::MODEL_NON_SECURE, ?string $storeKey = null, string $lang = PosInterface::LANG_TR): EstPosAccount + public static function createEstPosAccount(string $bank, string $clientId, string $kullaniciAdi, string $password, string $model = PosInterface::MODEL_NON_SECURE, ?string $storeKey = null): EstPosAccount { self::checkParameters($model, $storeKey); - return new EstPosAccount($bank, $clientId, $kullaniciAdi, $password, $lang, $storeKey); + return new EstPosAccount($bank, $clientId, $kullaniciAdi, $password, $storeKey); } /** - * @phpstan-param PosInterface::LANG_* $lang - * * @param non-empty-string $bank * @param non-empty-string $merchantSafeId 32 karakter üye İş Yeri numarası * @param non-empty-string $terminalSafeId 32 karakter * @param non-empty-string $secretKey - * @param non-empty-string $lang * @param non-empty-string|null $subMerchantId Max 15 karakter * * @return AkbankPosAccount */ - public static function createAkbankPosAccount(string $bank, string $merchantSafeId, string $terminalSafeId, string $secretKey, string $lang = PosInterface::LANG_TR, ?string $subMerchantId = null): AkbankPosAccount + public static function createAkbankPosAccount(string $bank, string $merchantSafeId, string $terminalSafeId, string $secretKey, ?string $subMerchantId = null): AkbankPosAccount { - return new AkbankPosAccount($bank, $merchantSafeId, $terminalSafeId, $secretKey, $lang, $subMerchantId); + return new AkbankPosAccount($bank, $merchantSafeId, $terminalSafeId, $secretKey, $subMerchantId); } /** @@ -74,11 +69,10 @@ public static function createAkbankPosAccount(string $bank, string $merchantSafe */ public static function createToslaPosAccount(string $bank, string $clientId, string $apiUser, string $apiPass): ToslaPosAccount { - return new ToslaPosAccount($bank, $clientId, $apiUser, '', PosInterface::LANG_TR, $apiPass); + return new ToslaPosAccount($bank, $clientId, $apiUser, '', $apiPass); } /** - * @phpstan-param PosInterface::LANG_* $lang * @phpstan-param PosInterface::MODEL_* $model * @phpstan-param PayForAccount::MBR_ID_* $mbrId * @@ -88,7 +82,6 @@ public static function createToslaPosAccount(string $bank, string $clientId, str * @param non-empty-string $userPassword Otorizasyon sistemi kullanıcı şifresi. * @param non-empty-string $model * @param non-empty-string|null $merchantPass 3D Secure şifresidir. - * @param non-empty-string $lang * @param non-empty-string $mbrId Kurum kodudur. * * @return PayForAccount @@ -102,7 +95,6 @@ public static function createPayForAccount( string $userPassword, string $model = PosInterface::MODEL_NON_SECURE, ?string $merchantPass = null, - string $lang = PosInterface::LANG_TR, string $mbrId = PayForAccount::MBR_ID_FINANSBANK ): PayForAccount { self::checkParameters($model, $merchantPass); @@ -112,14 +104,12 @@ public static function createPayForAccount( $merchantId, $userCode, $userPassword, - $lang, $merchantPass, $mbrId ); } /** - * @phpstan-param PosInterface::LANG_* $lang * @phpstan-param PosInterface::MODEL_* $model * * @param non-empty-string $bank @@ -131,22 +121,20 @@ public static function createPayForAccount( * @param non-empty-string|null $storeKey * @param non-empty-string|null $refundUsername * @param non-empty-string|null $refundPassword - * @param non-empty-string $lang * * @return GarantiPosAccount * * @throws MissingAccountInfoException */ - public static function createGarantiPosAccount(string $bank, string $merchantId, string $userId, string $password, string $terminalId, string $model = PosInterface::MODEL_NON_SECURE, ?string $storeKey = null, ?string $refundUsername = null, ?string $refundPassword = null, string $lang = PosInterface::LANG_TR): GarantiPosAccount + public static function createGarantiPosAccount(string $bank, string $merchantId, string $userId, string $password, string $terminalId, string $model = PosInterface::MODEL_NON_SECURE, ?string $storeKey = null, ?string $refundUsername = null, ?string $refundPassword = null): GarantiPosAccount { self::checkParameters($model, $storeKey); - return new GarantiPosAccount($bank, $merchantId, $userId, $password, $lang, $terminalId, $storeKey, $refundUsername, $refundPassword); + return new GarantiPosAccount($bank, $merchantId, $userId, $password, $terminalId, $storeKey, $refundUsername, $refundPassword); } /** - * @phpstan-param PosInterface::LANG_* $lang * @phpstan-param PosInterface::MODEL_* $model * * @param non-empty-string $bank @@ -155,22 +143,20 @@ public static function createGarantiPosAccount(string $bank, string $merchantId, * @param non-empty-string $customerId CustomerNumber, Müşteri No * @param non-empty-string $storeKey Oluşturulan APİ kullanıcısının şifre bilgisidir. * @param non-empty-string $model - * @param non-empty-string $lang * @param non-empty-string|null $subMerchantId * * @return KuveytPosAccount * * @throws MissingAccountInfoException */ - public static function createKuveytPosAccount(string $bank, string $merchantId, string $username, string $customerId, string $storeKey, string $model = PosInterface::MODEL_3D_SECURE, string $lang = PosInterface::LANG_TR, ?string $subMerchantId = null): KuveytPosAccount + public static function createKuveytPosAccount(string $bank, string $merchantId, string $username, string $customerId, string $storeKey, string $model = PosInterface::MODEL_3D_SECURE, ?string $subMerchantId = null): KuveytPosAccount { self::checkParameters($model, $storeKey); - return new KuveytPosAccount($bank, $merchantId, $username, $customerId, $storeKey, $lang, $subMerchantId); + return new KuveytPosAccount($bank, $merchantId, $username, $customerId, $storeKey, $subMerchantId); } /** - * @phpstan-param PosInterface::LANG_* $lang * @phpstan-param PosInterface::MODEL_* $model * * @param non-empty-string $bank @@ -179,17 +165,16 @@ public static function createKuveytPosAccount(string $bank, string $merchantId, * @param non-empty-string $posNetId * @param non-empty-string $model * @param non-empty-string|null $storeKey - * @param non-empty-string $lang * * @return PosNetAccount * * @throws MissingAccountInfoException */ - public static function createPosNetAccount(string $bank, string $merchantId, string $terminalId, string $posNetId, string $model = PosInterface::MODEL_NON_SECURE, ?string $storeKey = null, string $lang = PosInterface::LANG_TR): PosNetAccount + public static function createPosNetAccount(string $bank, string $merchantId, string $terminalId, string $posNetId, string $model = PosInterface::MODEL_NON_SECURE, ?string $storeKey = null): PosNetAccount { self::checkParameters($model, $storeKey); - return new PosNetAccount($bank, $merchantId, $posNetId, $terminalId, $lang, $storeKey); + return new PosNetAccount($bank, $merchantId, $posNetId, $terminalId, $storeKey); } /** @@ -216,7 +201,6 @@ public static function createPayFlexAccount(string $bank, string $merchantId, st } /** - * @phpstan-param PosInterface::LANG_* $lang * @phpstan-param PosInterface::MODEL_* $model * * @param non-empty-string $bank @@ -225,17 +209,16 @@ public static function createPayFlexAccount(string $bank, string $merchantId, st * @param non-empty-string $userPass * @param non-empty-string $model * @param non-empty-string|null $merchantPass - * @param non-empty-string $lang * * @return InterPosAccount * * @throws MissingAccountInfoException */ - public static function createInterPosAccount(string $bank, string $shopCode, string $userCode, string $userPass, string $model = PosInterface::MODEL_NON_SECURE, ?string $merchantPass = null, string $lang = PosInterface::LANG_TR): InterPosAccount + public static function createInterPosAccount(string $bank, string $shopCode, string $userCode, string $userPass, string $model = PosInterface::MODEL_NON_SECURE, ?string $merchantPass = null): InterPosAccount { self::checkParameters($model, $merchantPass); - return new InterPosAccount($bank, $shopCode, $userCode, $userPass, $lang, $merchantPass); + return new InterPosAccount($bank, $shopCode, $userCode, $userPass, $merchantPass); } /** diff --git a/src/Factory/CryptFactory.php b/src/Factory/CryptFactory.php index 9adf3307..196d5e61 100644 --- a/src/Factory/CryptFactory.php +++ b/src/Factory/CryptFactory.php @@ -20,19 +20,6 @@ use Mews\Pos\Crypt\PosNetCrypt; use Mews\Pos\Crypt\PosNetV1PosCrypt; use Mews\Pos\Crypt\ToslaPosCrypt; -use Mews\Pos\Gateways\AkbankPos; -use Mews\Pos\Gateways\EstPos; -use Mews\Pos\Gateways\EstV3Pos; -use Mews\Pos\Gateways\GarantiPos; -use Mews\Pos\Gateways\InterPos; -use Mews\Pos\Gateways\KuveytPos; -use Mews\Pos\Gateways\ParamPos; -use Mews\Pos\Gateways\PayFlexCPV4Pos; -use Mews\Pos\Gateways\PayForPos; -use Mews\Pos\Gateways\PosNet; -use Mews\Pos\Gateways\PosNetV1Pos; -use Mews\Pos\Gateways\ToslaPos; -use Mews\Pos\Gateways\VakifKatilimPos; use Mews\Pos\PosInterface; use Psr\Log\LoggerInterface; @@ -41,6 +28,24 @@ */ class CryptFactory { + /** + * @var class-string[] + */ + private static array $crypts = [ + AkbankPosCrypt::class, + EstPosCrypt::class, + EstV3PosCrypt::class, + GarantiPosCrypt::class, + InterPosCrypt::class, + KuveytPosCrypt::class, + ParamPosCrypt::class, + PayFlexCPV4Crypt::class, + PayForPosCrypt::class, + PosNetCrypt::class, + PosNetV1PosCrypt::class, + ToslaPosCrypt::class, + ]; + /** * @param class-string $gatewayClass * @param LoggerInterface $logger @@ -49,24 +54,11 @@ class CryptFactory */ public static function createGatewayCrypt(string $gatewayClass, LoggerInterface $logger): CryptInterface { - $classMappings = [ - AkbankPos::class => AkbankPosCrypt::class, - EstPos::class => EstPosCrypt::class, - EstV3Pos::class => EstV3PosCrypt::class, - GarantiPos::class => GarantiPosCrypt::class, - InterPos::class => InterPosCrypt::class, - KuveytPos::class => KuveytPosCrypt::class, - ParamPos::class => ParamPosCrypt::class, - PayFlexCPV4Pos::class => PayFlexCPV4Crypt::class, - PayForPos::class => PayForPosCrypt::class, - PosNet::class => PosNetCrypt::class, - PosNetV1Pos::class => PosNetV1PosCrypt::class, - ToslaPos::class => ToslaPosCrypt::class, - VakifKatilimPos::class => KuveytPosCrypt::class, - ]; - - if (isset($classMappings[$gatewayClass])) { - return new $classMappings[$gatewayClass]($logger); + /** @var class-string $crypt */ + foreach (self::$crypts as $crypt) { + if ($crypt::supports($gatewayClass)) { + return new $crypt($logger); + } } return new NullCrypt($logger); diff --git a/src/Factory/HttpClientFactory.php b/src/Factory/HttpClientFactory.php deleted file mode 100644 index fb89ba29..00000000 --- a/src/Factory/HttpClientFactory.php +++ /dev/null @@ -1,49 +0,0 @@ -, gateway_endpoints: array}>, currencies?: array} $config + * @phpstan-param array{ + * banks: array, + * lang?: PosInterface::LANG_*, + * gateway_endpoints: array{ + * payment_api: non-empty-string, + * payment_api2?: non-empty-string, + * query_api?: non-empty-string} + * }> + * } $config * - * @param AbstractPosAccount $posAccount - * @param array $config - * @param EventDispatcherInterface $eventDispatcher - * @param HttpClient|null $httpClient - * @param LoggerInterface|null $logger + * @param AbstractPosAccount $posAccount + * @param array $config + * @param EventDispatcherInterface $eventDispatcher + * @param HttpClientStrategyInterface|null $httpClientStrategy + * @param LoggerInterface|null $logger * * @return PosInterface * @@ -35,58 +45,109 @@ class PosFactory * @throws BankNotFoundException */ public static function createPosGateway( - AbstractPosAccount $posAccount, - array $config, - EventDispatcherInterface $eventDispatcher, - ?HttpClient $httpClient = null, - ?LoggerInterface $logger = null + AbstractPosAccount $posAccount, + array $config, + EventDispatcherInterface $eventDispatcher, + ?HttpClientStrategyInterface $httpClientStrategy = null, + ?LoggerInterface $logger = null ): PosInterface { if (!$logger instanceof \Psr\Log\LoggerInterface) { $logger = new NullLogger(); } - if (!$httpClient instanceof \Mews\Pos\Client\HttpClient) { - $httpClient = HttpClientFactory::createDefaultHttpClient(); - } - - // Bank API Exist + // Bank Config Exist if (!\array_key_exists($posAccount->getBank(), $config['banks'])) { throw new BankNotFoundException(); } - $class = $config['banks'][$posAccount->getBank()]['class'] ?? null; + $gatewayClass = $config['banks'][$posAccount->getBank()]['class'] ?? null; - if (null === $class) { + if (null === $gatewayClass) { throw new BankClassNullException(); } - if (!\in_array(PosInterface::class, \class_implements($class), true)) { + if (!\in_array(PosInterface::class, \class_implements($gatewayClass), true)) { throw new \InvalidArgumentException( \sprintf('gateway class must be implementation of %s', PosInterface::class) ); } - $currencies = []; - if (isset($config['currencies'])) { - $currencies = $config['currencies']; - } - $logger->debug('creating gateway for bank', ['bank' => $posAccount->getBank()]); - $crypt = CryptFactory::createGatewayCrypt($class, $logger); - $requestDataMapper = RequestDataMapperFactory::createGatewayRequestMapper($class, $eventDispatcher, $crypt, $currencies); - $responseDataMapper = ResponseDataMapperFactory::createGatewayResponseMapper($class, $requestDataMapper, $logger); - $serializer = SerializerFactory::createGatewaySerializer($class); + return self::doCreatePosGateway( + $gatewayClass, + $posAccount, + $config['banks'][$posAccount->getBank()], + $eventDispatcher, + $logger, + $httpClientStrategy + ); + } + + /** + * @param class-string $gatewayClass + * @param AbstractPosAccount $posAccount + * @param array{ + * name: string, + * class?: class-string, + * lang?: PosInterface::LANG_*, + * gateway_endpoints: array + * } $apiConfig + * @param EventDispatcherInterface $eventDispatcher + * @param LoggerInterface $logger + * @param HttpClientStrategyInterface|null $httpClientStrategy + * + * @return PosInterface + */ + private static function doCreatePosGateway( + string $gatewayClass, + AbstractPosAccount $posAccount, + array $apiConfig, + EventDispatcherInterface $eventDispatcher, + LoggerInterface $logger, + ?HttpClientStrategyInterface $httpClientStrategy = null + ): PosInterface { + + + $crypt = CryptFactory::createGatewayCrypt($gatewayClass, $logger); + $requestValueMapper = RequestValueMapperFactory::createForGateway($gatewayClass); + $requestValueFormatter = RequestValueFormatterFactory::createForGateway($gatewayClass); + $defaultLang = $apiConfig['lang'] ?? PosInterface::LANG_TR; + + $requestDataMapper = RequestDataMapperFactory::createGatewayRequestMapper( + $gatewayClass, + $requestValueMapper, + $requestValueFormatter, + $eventDispatcher, + $crypt, + $defaultLang + ); + + $responseValueFormatter = ResponseValueFormatterFactory::createForGateway($gatewayClass); + $responseValueMapper = ResponseValueMapperFactory::createForGateway($gatewayClass, $requestValueMapper); + $responseDataMapper = ResponseDataMapperFactory::createGatewayResponseMapper($gatewayClass, $responseValueFormatter, $responseValueMapper, $logger); + $serializer = SerializerFactory::createGatewaySerializer($gatewayClass); + + if (!$httpClientStrategy instanceof HttpClientStrategyInterface) { + $httpClientStrategy = PosHttpClientStrategyFactory::createForGateway( + $gatewayClass, + $apiConfig['gateway_endpoints'], + $crypt, + $requestValueMapper, + $logger + ); + } // Create Bank Class Instance - return new $class( - $config['banks'][$posAccount->getBank()], + return new $gatewayClass( + $apiConfig, $posAccount, + $requestValueMapper, $requestDataMapper, $responseDataMapper, $serializer, $eventDispatcher, - $httpClient, + $httpClientStrategy, $logger ); } diff --git a/src/Factory/PosHttpClientFactory.php b/src/Factory/PosHttpClientFactory.php new file mode 100644 index 00000000..c4dc555a --- /dev/null +++ b/src/Factory/PosHttpClientFactory.php @@ -0,0 +1,79 @@ + $clientClass + * @param non-empty-string $baseApiUrl + * @param SerializerInterface $serializer + * @param CryptInterface $crypt + * @param RequestValueMapperInterface $requestValueMapper + * @param LoggerInterface $logger + * @param ClientInterface $psr18client + * @param RequestFactoryInterface $requestFactory + * @param StreamFactoryInterface $streamFactory + * + * @return HttpClientInterface + */ + public static function create( + string $clientClass, + string $baseApiUrl, + SerializerInterface $serializer, + CryptInterface $crypt, + RequestValueMapperInterface $requestValueMapper, + LoggerInterface $logger, + ClientInterface $psr18client, + RequestFactoryInterface $requestFactory, + StreamFactoryInterface $streamFactory + ): HttpClientInterface { + if (AkbankPosHttpClient::class === $clientClass) { + return new $clientClass( + $baseApiUrl, + $psr18client, + $requestFactory, + $streamFactory, + $serializer, + $logger, + $crypt + ); + } + if (PosNetV1PosHttpClient::class === $clientClass || KuveytSoapApiPosHttpClient::class === $clientClass) { + return new $clientClass( + $baseApiUrl, + $psr18client, + $requestFactory, + $streamFactory, + $serializer, + $logger, + $requestValueMapper + ); + } + + return new $clientClass( + $baseApiUrl, + $psr18client, + $requestFactory, + $streamFactory, + $serializer, + $logger + ); + } +} diff --git a/src/Factory/PosHttpClientStrategyFactory.php b/src/Factory/PosHttpClientStrategyFactory.php new file mode 100644 index 00000000..2383b922 --- /dev/null +++ b/src/Factory/PosHttpClientStrategyFactory.php @@ -0,0 +1,120 @@ +> + */ + private static array $clientClasses = [ + AkbankPosHttpClient::class, + EstPosHttpClient::class, + GarantiPosHttpClient::class, + InterPosHttpClient::class, + KuveytPos3DFormHttpClient::class, + KuveytPosHttpClient::class, + KuveytSoapApiPosHttpClient::class, + ParamPosHttpClient::class, + PayFlexCPV4Pos3DFormHttpClient::class, + PayFlexCPV4PosHttpClient::class, + PayFlexV4Pos3DFormHttpClient::class, + PayFlexV4PosHttpClient::class, + PayForPosHttpClient::class, + PosNetPosHttpClient::class, + PosNetV1PosHttpClient::class, + ToslaPosHttpClient::class, + VakifKatilimPos3DFormHttpClient::class, + VakifKatilimPosHttpClient::class, + ]; + + /** + * @param class-string $gatewayClass + * @param array $gatewayEndpoints + * @param CryptInterface $crypt + * @param RequestValueMapperInterface $requestValueMapper + * @param LoggerInterface $logger + * @param ClientInterface|null $psr18client + * @param RequestFactoryInterface|null $requestFactory + * @param StreamFactoryInterface|null $streamFactory + * + * @return HttpClientStrategyInterface + */ + public static function createForGateway( + string $gatewayClass, + array $gatewayEndpoints, + CryptInterface $crypt, + RequestValueMapperInterface $requestValueMapper, + LoggerInterface $logger, + ?ClientInterface $psr18client = null, + ?RequestFactoryInterface $requestFactory = null, + ?StreamFactoryInterface $streamFactory = null + ): HttpClientStrategyInterface { + $clients = []; + $psr18client ??= Psr18ClientDiscovery::find(); + $requestFactory ??= Psr17FactoryDiscovery::findRequestFactory(); + $streamFactory ??= Psr17FactoryDiscovery::findStreamFactory(); + + + foreach ($gatewayEndpoints as $apiName => $endpoint) { + foreach (self::$clientClasses as $clientClass) { + if ($clientClass::supports($gatewayClass, $apiName)) { + $serializer = SerializerFactory::createGatewaySerializer($gatewayClass, $apiName); + + $clients[$apiName] = PosHttpClientFactory::create( + $clientClass, + $endpoint, + $serializer, + $crypt, + $requestValueMapper, + $logger, + $psr18client, + $requestFactory, + $streamFactory + ); + } + } + } + + if ([] === $clients) { + throw new \DomainException(\sprintf('Client not found for the gateway %s', $gatewayClass)); + } + + return new GenericPosHttpClientStrategy($clients); + } +} diff --git a/src/Factory/RequestDataMapperFactory.php b/src/Factory/RequestDataMapperFactory.php index cf8c2e5e..79ff889c 100644 --- a/src/Factory/RequestDataMapperFactory.php +++ b/src/Factory/RequestDataMapperFactory.php @@ -14,6 +14,8 @@ use Mews\Pos\DataMapper\RequestDataMapper\GarantiPosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\InterPosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\KuveytPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestDataMapper\KuveytSoapApiPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestDataMapper\Param3DHostPosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\ParamPosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\PayFlexCPV4PosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\PayFlexV4PosRequestDataMapper; @@ -23,20 +25,8 @@ use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; use Mews\Pos\DataMapper\RequestDataMapper\ToslaPosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\VakifKatilimPosRequestDataMapper; -use Mews\Pos\Gateways\AkbankPos; -use Mews\Pos\Gateways\EstPos; -use Mews\Pos\Gateways\EstV3Pos; -use Mews\Pos\Gateways\GarantiPos; -use Mews\Pos\Gateways\InterPos; -use Mews\Pos\Gateways\KuveytPos; -use Mews\Pos\Gateways\ParamPos; -use Mews\Pos\Gateways\PayFlexCPV4Pos; -use Mews\Pos\Gateways\PayFlexV4Pos; -use Mews\Pos\Gateways\PayForPos; -use Mews\Pos\Gateways\PosNet; -use Mews\Pos\Gateways\PosNetV1Pos; -use Mews\Pos\Gateways\ToslaPos; -use Mews\Pos\Gateways\VakifKatilimPos; +use Mews\Pos\DataMapper\RequestValueFormatter\RequestValueFormatterInterface; +use Mews\Pos\DataMapper\RequestValueMapper\RequestValueMapperInterface; use Mews\Pos\PosInterface; use Psr\EventDispatcher\EventDispatcherInterface; @@ -46,35 +36,59 @@ class RequestDataMapperFactory { /** - * @param class-string $gatewayClass - * @param EventDispatcherInterface $eventDispatcher - * @param CryptInterface $crypt - * @param array $currencies + * @var class-string[] + */ + private static array $requestDataMapperClasses = [ + AkbankPosRequestDataMapper::class, + EstPosRequestDataMapper::class, + EstV3PosRequestDataMapper::class, + GarantiPosRequestDataMapper::class, + InterPosRequestDataMapper::class, + KuveytPosRequestDataMapper::class, + KuveytSoapApiPosRequestDataMapper::class, + ParamPosRequestDataMapper::class, + Param3DHostPosRequestDataMapper::class, + PayFlexCPV4PosRequestDataMapper::class, + PayFlexV4PosRequestDataMapper::class, + PayForPosRequestDataMapper::class, + PosNetRequestDataMapper::class, + PosNetV1PosRequestDataMapper::class, + ToslaPosRequestDataMapper::class, + VakifKatilimPosRequestDataMapper::class, + ]; + + /** + * @param class-string $gatewayClass + * @param RequestValueMapperInterface $valueMapper + * @param RequestValueFormatterInterface $valueFormatter + * @param EventDispatcherInterface $eventDispatcher + * @param CryptInterface $crypt + * @param PosInterface::LANG_* $defaultLang * * @return RequestDataMapperInterface */ - public static function createGatewayRequestMapper(string $gatewayClass, EventDispatcherInterface $eventDispatcher, CryptInterface $crypt, array $currencies = []): RequestDataMapperInterface - { - $classMappings = [ - AkbankPos::class => AkbankPosRequestDataMapper::class, - EstPos::class => EstPosRequestDataMapper::class, - EstV3Pos::class => EstV3PosRequestDataMapper::class, - GarantiPos::class => GarantiPosRequestDataMapper::class, - InterPos::class => InterPosRequestDataMapper::class, - KuveytPos::class => KuveytPosRequestDataMapper::class, - ParamPos::class => ParamPosRequestDataMapper::class, - PayFlexCPV4Pos::class => PayFlexCPV4PosRequestDataMapper::class, - PayFlexV4Pos::class => PayFlexV4PosRequestDataMapper::class, - PayForPos::class => PayForPosRequestDataMapper::class, - PosNet::class => PosNetRequestDataMapper::class, - PosNetV1Pos::class => PosNetV1PosRequestDataMapper::class, - ToslaPos::class => ToslaPosRequestDataMapper::class, - VakifKatilimPos::class => VakifKatilimPosRequestDataMapper::class, - ]; - if (isset($classMappings[$gatewayClass])) { - return new $classMappings[$gatewayClass]($eventDispatcher, $crypt, $currencies); + public static function createGatewayRequestMapper( + string $gatewayClass, + RequestValueMapperInterface $valueMapper, + RequestValueFormatterInterface $valueFormatter, + EventDispatcherInterface $eventDispatcher, + CryptInterface $crypt, + string $defaultLang + ): RequestDataMapperInterface { + /** @var class-string $requestDataMapperClass */ + foreach (self::$requestDataMapperClasses as $requestDataMapperClass) { + if ($requestDataMapperClass::supports($gatewayClass)) { + return new $requestDataMapperClass( + $valueMapper, + $valueFormatter, + $eventDispatcher, + $crypt, + $defaultLang + ); + } } + throw new DomainException(\sprintf('Request data mapper not found for the gateway %s', $gatewayClass)); } } diff --git a/src/Factory/RequestValueFormatterFactory.php b/src/Factory/RequestValueFormatterFactory.php new file mode 100644 index 00000000..b6e82cf2 --- /dev/null +++ b/src/Factory/RequestValueFormatterFactory.php @@ -0,0 +1,66 @@ +[] + */ + private static array $requestValueFormatterClasses = [ + ToslaPosRequestValueFormatter::class, + AkbankPosRequestValueFormatter::class, + EstPosRequestValueFormatter::class, + GarantiPosRequestValueFormatter::class, + InterPosRequestValueFormatter::class, + KuveytPosRequestValueFormatter::class, + VakifKatilimPosRequestValueFormatter::class, + ParamPosRequestValueFormatter::class, + PayForPosRequestValueFormatter::class, + PosNetRequestValueFormatter::class, + PosNetV1PosRequestValueFormatter::class, + PayFlexCPV4PosRequestValueFormatter::class, + PayFlexV4PosRequestValueFormatter::class, + ]; + + /** + * @param class-string $gatewayClass + * + * @return RequestValueFormatterInterface + */ + public static function createForGateway(string $gatewayClass): RequestValueFormatterInterface + { + /** @var class-string $valueFormatterClass */ + foreach (self::$requestValueFormatterClasses as $valueFormatterClass) { + if ($valueFormatterClass::supports($gatewayClass)) { + return new $valueFormatterClass(); + } + } + + throw new DomainException('unsupported gateway'); + } +} diff --git a/src/Factory/RequestValueMapperFactory.php b/src/Factory/RequestValueMapperFactory.php new file mode 100644 index 00000000..b6a80b5f --- /dev/null +++ b/src/Factory/RequestValueMapperFactory.php @@ -0,0 +1,69 @@ +[] + */ + private static array $requestValueMapperClasses = [ + ToslaPosRequestValueMapper::class, + AkbankPosRequestValueMapper::class, + EstPosRequestValueMapper::class, + EstPosRequestValueMapper::class, + GarantiPosRequestValueMapper::class, + InterPosRequestValueMapper::class, + KuveytPosRequestValueMapper::class, + KuveytPosRequestValueMapper::class, + VakifKatilimPosRequestValueMapper::class, + PayForPosRequestValueMapper::class, + PosNetRequestValueMapper::class, + PosNetV1PosRequestValueMapper::class, + ParamPosRequestValueMapper::class, + PayFlexCPV4PosRequestValueMapper::class, + PayFlexV4PosRequestValueMapper::class, + ]; + + /** + * @param class-string $gatewayClass + * + * @return RequestValueMapperInterface + */ + public static function createForGateway(string $gatewayClass): RequestValueMapperInterface + { + + /** @var class-string $valueMapperClass */ + foreach (self::$requestValueMapperClasses as $valueMapperClass) { + if ($valueMapperClass::supports($gatewayClass)) { + return new $valueMapperClass(); + } + } + + throw new DomainException('unsupported gateway'); + } +} diff --git a/src/Factory/ResponseDataMapperFactory.php b/src/Factory/ResponseDataMapperFactory.php index 1d5965aa..0b729095 100644 --- a/src/Factory/ResponseDataMapperFactory.php +++ b/src/Factory/ResponseDataMapperFactory.php @@ -7,12 +7,12 @@ namespace Mews\Pos\Factory; use DomainException; -use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; use Mews\Pos\DataMapper\ResponseDataMapper\AkbankPosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\EstPosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\GarantiPosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\InterPosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\KuveytPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\KuveytSoapApiPosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ParamPosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayFlexCPV4PosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayFlexV4PosResponseDataMapper; @@ -22,20 +22,8 @@ use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\DataMapper\ResponseDataMapper\ToslaPosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\VakifKatilimPosResponseDataMapper; -use Mews\Pos\Gateways\AkbankPos; -use Mews\Pos\Gateways\EstPos; -use Mews\Pos\Gateways\EstV3Pos; -use Mews\Pos\Gateways\GarantiPos; -use Mews\Pos\Gateways\InterPos; -use Mews\Pos\Gateways\KuveytPos; -use Mews\Pos\Gateways\ParamPos; -use Mews\Pos\Gateways\PayFlexCPV4Pos; -use Mews\Pos\Gateways\PayFlexV4Pos; -use Mews\Pos\Gateways\PayForPos; -use Mews\Pos\Gateways\PosNet; -use Mews\Pos\Gateways\PosNetV1Pos; -use Mews\Pos\Gateways\ToslaPos; -use Mews\Pos\Gateways\VakifKatilimPos; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\PosInterface; use Psr\Log\LoggerInterface; @@ -45,38 +33,49 @@ class ResponseDataMapperFactory { /** - * @param class-string $gatewayClass - * @param RequestDataMapperInterface $requestDataMapper - * @param LoggerInterface $logger + * @var class-string[] + */ + private static array $responseDataMapperClasses = [ + AkbankPosResponseDataMapper::class, + EstPosResponseDataMapper::class, + GarantiPosResponseDataMapper::class, + InterPosResponseDataMapper::class, + KuveytPosResponseDataMapper::class, + KuveytSoapApiPosResponseDataMapper::class, + ParamPosResponseDataMapper::class, + PayFlexCPV4PosResponseDataMapper::class, + PayFlexV4PosResponseDataMapper::class, + PayForPosResponseDataMapper::class, + PosNetResponseDataMapper::class, + PosNetV1PosResponseDataMapper::class, + ToslaPosResponseDataMapper::class, + VakifKatilimPosResponseDataMapper::class, + ]; + + /** + * @param class-string $gatewayClass + * @param ResponseValueFormatterInterface $valueFormatter + * @param ResponseValueMapperInterface $valueMapper + * @param LoggerInterface $logger * * @return ResponseDataMapperInterface */ - public static function createGatewayResponseMapper(string $gatewayClass, RequestDataMapperInterface $requestDataMapper, LoggerInterface $logger): ResponseDataMapperInterface - { - $classMappings = [ - AkbankPos::class => AkbankPosResponseDataMapper::class, - EstPos::class => EstPosResponseDataMapper::class, - EstV3Pos::class => EstPosResponseDataMapper::class, - GarantiPos::class => GarantiPosResponseDataMapper::class, - InterPos::class => InterPosResponseDataMapper::class, - KuveytPos::class => KuveytPosResponseDataMapper::class, - ParamPos::class => ParamPosResponseDataMapper::class, - PayFlexCPV4Pos::class => PayFlexCPV4PosResponseDataMapper::class, - PayFlexV4Pos::class => PayFlexV4PosResponseDataMapper::class, - PayForPos::class => PayForPosResponseDataMapper::class, - PosNet::class => PosNetResponseDataMapper::class, - PosNetV1Pos::class => PosNetV1PosResponseDataMapper::class, - ToslaPos::class => ToslaPosResponseDataMapper::class, - VakifKatilimPos::class => VakifKatilimPosResponseDataMapper::class, - ]; + public static function createGatewayResponseMapper( + string $gatewayClass, + ResponseValueFormatterInterface $valueFormatter, + ResponseValueMapperInterface $valueMapper, + LoggerInterface $logger + ): ResponseDataMapperInterface { - if (isset($classMappings[$gatewayClass])) { - return new $classMappings[$gatewayClass]( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $logger - ); + /** @var class-string $responseDataMapperClass */ + foreach (self::$responseDataMapperClasses as $responseDataMapperClass) { + if ($responseDataMapperClass::supports($gatewayClass)) { + return new $responseDataMapperClass( + $valueFormatter, + $valueMapper, + $logger + ); + } } throw new DomainException(\sprintf('Response data mapper not found for the gateway %s', $gatewayClass)); diff --git a/src/Factory/ResponseValueFormatterFactory.php b/src/Factory/ResponseValueFormatterFactory.php new file mode 100644 index 00000000..27342f97 --- /dev/null +++ b/src/Factory/ResponseValueFormatterFactory.php @@ -0,0 +1,57 @@ +[] + */ + private static array $valueFormatterClasses = [ + BasicResponseValueFormatter::class, + EstPosResponseValueFormatter::class, + GarantiPosResponseValueFormatter::class, + InterPosResponseValueFormatter::class, + BoaPosResponseValueFormatter::class, + ParamPosResponseValueFormatter::class, + PosNetResponseValueFormatter::class, + ToslaPosResponseValueFormatter::class, + BoaPosResponseValueFormatter::class, + ]; + + /** + * @param class-string $gatewayClass + * + * @return ResponseValueFormatterInterface + */ + public static function createForGateway(string $gatewayClass): ResponseValueFormatterInterface + { + /** @var class-string $formatterClass */ + foreach (self::$valueFormatterClasses as $formatterClass) { + if ($formatterClass::supports($gatewayClass)) { + return new $formatterClass(); + } + } + + throw new DomainException('unsupported gateway'); + } +} diff --git a/src/Factory/ResponseValueMapperFactory.php b/src/Factory/ResponseValueMapperFactory.php new file mode 100644 index 00000000..ff5e27b0 --- /dev/null +++ b/src/Factory/ResponseValueMapperFactory.php @@ -0,0 +1,130 @@ +[] + */ + private static array $responseValueMapperClasses = [ + AkbankPosResponseValueMapper::class, + BoaPosResponseValueMapper::class, + EstPosResponseValueMapper::class, + GarantiPosResponseValueMapper::class, + InterPosResponseValueMapper::class, + ParamPosResponseValueMapper::class, + PayFlexCPV4PosResponseValueMapper::class, + PayFlexV4PosResponseValueMapper::class, + PayForPosResponseValueMapper::class, + PosNetResponseValueMapper::class, + PosNetV1PosResponseValueMapper::class, + ToslaPosResponseValueMapper::class, + ]; + + /** + * @param class-string $gatewayClass + * @param RequestValueMapperInterface $requestValueMapper + * + * @return ResponseValueMapperInterface + */ + public static function createForGateway(string $gatewayClass, RequestValueMapperInterface $requestValueMapper): ResponseValueMapperInterface + { + /** @var class-string $valueMapperClass */ + foreach (self::$responseValueMapperClasses as $valueMapperClass) { + if (!$valueMapperClass::supports($gatewayClass)) { + continue; + } + + $secureTypeMappings = []; + $txTypeMappings = []; + $currencyMappings = []; + + if (self::areTxMappingsRequired($valueMapperClass)) { + $txTypeMappings = $requestValueMapper->getTxTypeMappings(); + } + + if (self::areSecurityTypeMappingsRequired($valueMapperClass)) { + $secureTypeMappings = $requestValueMapper->getSecureTypeMappings(); + } + + if (self::areCurrencyMappingsRequired($valueMapperClass)) { + $currencyMappings = $requestValueMapper->getCurrencyMappings(); + } + + return new $valueMapperClass( + $currencyMappings, + $txTypeMappings, + $secureTypeMappings, + ); + } + + throw new DomainException('unsupported gateway'); + } + + private static function areTxMappingsRequired(string $valueMapperClass): bool + { + return \in_array($valueMapperClass, [ + AkbankPosResponseValueMapper::class, + GarantiPosResponseValueMapper::class, + BoaPosResponseValueMapper::class, + PayFlexCPV4PosResponseValueMapper::class, + PayFlexV4PosResponseValueMapper::class, + PayForPosResponseValueMapper::class, + PosNetResponseValueMapper::class, + PosNetV1PosResponseValueMapper::class, + ToslaPosResponseValueMapper::class, + ], true); + } + + private static function areCurrencyMappingsRequired(string $valueMapperClass): bool + { + return \in_array($valueMapperClass, [ + AkbankPosResponseValueMapper::class, + BoaPosResponseValueMapper::class, + EstPosResponseValueMapper::class, + GarantiPosResponseValueMapper::class, + InterPosResponseValueMapper::class, + PayFlexCPV4PosResponseValueMapper::class, + PayFlexV4PosResponseValueMapper::class, + PayForPosResponseValueMapper::class, + PosNetResponseValueMapper::class, + PosNetV1PosResponseValueMapper::class, + ToslaPosResponseValueMapper::class, + ], true); + } + + private static function areSecurityTypeMappingsRequired(string $valueMapperClass): bool + { + return \in_array($valueMapperClass, [ + EstPosResponseValueMapper::class, + GarantiPosResponseValueMapper::class, + BoaPosResponseValueMapper::class, + PayForPosResponseValueMapper::class, + ], true); + } +} diff --git a/src/Factory/SerializerFactory.php b/src/Factory/SerializerFactory.php index ccfcd6d4..f0246dcb 100644 --- a/src/Factory/SerializerFactory.php +++ b/src/Factory/SerializerFactory.php @@ -7,14 +7,17 @@ namespace Mews\Pos\Factory; use DomainException; +use Mews\Pos\Client\HttpClientInterface; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\AkbankPosSerializer; use Mews\Pos\Serializer\EstPosSerializer; use Mews\Pos\Serializer\GarantiPosSerializer; use Mews\Pos\Serializer\InterPosSerializer; use Mews\Pos\Serializer\KuveytPosSerializer; +use Mews\Pos\Serializer\KuveytSoapApiPosSerializer; use Mews\Pos\Serializer\ParamPosSerializer; use Mews\Pos\Serializer\PayFlexCPV4PosSerializer; +use Mews\Pos\Serializer\PayFlexV4PosSearchApiSerializer; use Mews\Pos\Serializer\PayFlexV4PosSerializer; use Mews\Pos\Serializer\PayForPosSerializer; use Mews\Pos\Serializer\PosNetSerializer; @@ -29,20 +32,25 @@ class SerializerFactory { /** - * @param class-string $gatewayClass + * @param class-string $gatewayClass + * @param HttpClientInterface::API_NAME_* $apiName * * @return SerializerInterface */ - public static function createGatewaySerializer(string $gatewayClass): SerializerInterface - { + public static function createGatewaySerializer( + string $gatewayClass, + ?string $apiName = null + ): SerializerInterface { $serializers = [ AkbankPosSerializer::class, EstPosSerializer::class, GarantiPosSerializer::class, InterPosSerializer::class, KuveytPosSerializer::class, + KuveytSoapApiPosSerializer::class, ParamPosSerializer::class, PayFlexCPV4PosSerializer::class, + PayFlexV4PosSearchApiSerializer::class, PayFlexV4PosSerializer::class, PayForPosSerializer::class, PosNetSerializer::class, @@ -53,7 +61,7 @@ public static function createGatewaySerializer(string $gatewayClass): Serializer /** @var class-string $serializer */ foreach ($serializers as $serializer) { - if ($serializer::supports($gatewayClass)) { + if ($serializer::supports($gatewayClass, $apiName)) { return new $serializer(); } } diff --git a/src/Gateways/AbstractGateway.php b/src/Gateways/AbstractGateway.php index 1a3201f3..0f6e8245 100644 --- a/src/Gateways/AbstractGateway.php +++ b/src/Gateways/AbstractGateway.php @@ -7,18 +7,17 @@ namespace Mews\Pos\Gateways; use LogicException; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\RequestValueMapperInterface; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\RequestDataPreparedEvent; use Mews\Pos\Exceptions\UnsupportedPaymentModelException; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Http\Client\ClientExceptionInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; @@ -31,11 +30,8 @@ abstract class AbstractGateway implements PosInterface * disable_3d_hash_check?: bool * }, * gateway_endpoints: array{ - * payment_api: non-empty-string, - * payment_api_2?: non-empty-string, * gateway_3d: non-empty-string, - * gateway_3d_host?: non-empty-string, - * query_api?: non-empty-string + * gateway_3d_host?: non-empty-string * } * } */ @@ -57,7 +53,9 @@ abstract class AbstractGateway implements PosInterface */ protected ?array $data; - protected HttpClient $client; + protected HttpClientStrategyInterface $clientStrategy; + + protected RequestValueMapperInterface $valueMapper; protected RequestDataMapperInterface $requestDataMapper; @@ -102,33 +100,32 @@ abstract class AbstractGateway implements PosInterface * disable_3d_hash_check?: bool * }, * gateway_endpoints: array{ - * payment_api: non-empty-string, - * payment_api_2?: non-empty-string, * gateway_3d: non-empty-string, - * gateway_3d_host?: non-empty-string, - * query_api?: non-empty-string + * gateway_3d_host?: non-empty-string * } * } $config */ public function __construct( - array $config, - AbstractPosAccount $posAccount, - RequestDataMapperInterface $requestDataMapper, - ResponseDataMapperInterface $responseDataMapper, - SerializerInterface $serializer, - EventDispatcherInterface $eventDispatcher, - HttpClient $httpClient, - LoggerInterface $logger + array $config, + AbstractPosAccount $posAccount, + RequestValueMapperInterface $valueMapper, + RequestDataMapperInterface $requestDataMapper, + ResponseDataMapperInterface $responseDataMapper, + SerializerInterface $serializer, + EventDispatcherInterface $eventDispatcher, + HttpClientStrategyInterface $httpClientStrategy, + LoggerInterface $logger ) { + $this->valueMapper = $valueMapper; $this->requestDataMapper = $requestDataMapper; $this->responseDataMapper = $responseDataMapper; $this->serializer = $serializer; $this->eventDispatcher = $eventDispatcher; - $this->config = $config; - $this->account = $posAccount; - $this->client = $httpClient; - $this->logger = $logger; + $this->config = $config; + $this->account = $posAccount; + $this->clientStrategy = $httpClientStrategy; + $this->logger = $logger; if (isset($this->config['gateway_configs']['test_mode'])) { $this->setTestMode($this->config['gateway_configs']['test_mode']); @@ -148,7 +145,7 @@ public function getResponse(): ?array */ public function getCurrencies(): array { - return \array_keys($this->requestDataMapper->getCurrencyMappings()); + return \array_keys($this->valueMapper->getCurrencyMappings()); } /** @@ -158,11 +155,8 @@ public function getCurrencies(): array * disable_3d_hash_check?: bool * }, * gateway_endpoints: array{ - * payment_api: non-empty-string, - * payment_api_2?: non-empty-string, * gateway_3d: non-empty-string, - * gateway_3d_host?: non-empty-string, - * query_api?: non-empty-string + * gateway_3d_host?: non-empty-string * } * } */ @@ -181,22 +175,6 @@ public function isSuccess(): bool return isset($this->response['status']) && $this->responseDataMapper::TX_APPROVED === $this->response['status']; } - /** - * @phpstan-param self::TX_TYPE_* $txType - * @phpstan-param self::MODEL_* $paymentModel - * @phpstan-param self::TX_TYPE_PAY_* $orderTxType - * - * @param string|null $txType - * @param string|null $paymentModel - * @param string|null $orderTxType - * - * @return non-empty-string - */ - public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string - { - return $this->config['gateway_endpoints']['payment_api']; - } - /** * @param PosInterface::MODEL_3D_* $paymentModel * @@ -211,34 +189,6 @@ public function get3DGatewayURL(string $paymentModel = PosInterface::MODEL_3D_SE return $this->config['gateway_endpoints']['gateway_3d']; } - /** - * @return non-empty-string - * - * @deprecated use get3DGatewayURL() instead - */ - public function get3DHostGatewayURL(): string - { - return $this->get3DGatewayURL(PosInterface::MODEL_3D_HOST); - } - - /** - * @phpstan-param self::TX_TYPE_* $txType - * @phpstan-param self::TX_TYPE_PAY_* $orderTxType - * - * @param string|null $txType - * @param string|null $orderTxType transaction type of order when it was made - * - * @return non-empty-string - */ - public function getQueryAPIUrl(?string $txType = null, ?string $orderTxType = null): string - { - return $this->config['gateway_endpoints']['query_api'] ?? $this->getApiURL( - $txType, - PosInterface::MODEL_NON_SECURE, - $orderTxType - ); - } - /** * @return bool */ @@ -290,13 +240,15 @@ public function payment(string $paymentModel, array $order, string $txType, ?Cre */ public function makeRegularPayment(array $order, CreditCardInterface $creditCard, string $txType): PosInterface { + $paymentModel = PosInterface::MODEL_NON_SECURE; $this->logger->debug('making payment', [ - 'model' => PosInterface::MODEL_NON_SECURE, + 'model' => $paymentModel, 'tx_type' => $txType, ]); if (!\in_array($txType, [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::TX_TYPE_PAY_PRE_AUTH], true)) { throw new LogicException(\sprintf('Invalid transaction type "%s" provided', $txType)); } + $requestData = $this->requestDataMapper->createNonSecurePaymentRequestData($this->account, $order, $txType, $creditCard); $event = new RequestDataPreparedEvent( @@ -305,7 +257,7 @@ public function makeRegularPayment(array $order, CreditCardInterface $creditCard $txType, \get_class($this), $order, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -319,12 +271,17 @@ public function makeRegularPayment(array $order, CreditCardInterface $creditCard $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_NON_SECURE, - $this->getApiURL($txType, PosInterface::MODEL_NON_SECURE) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order, + null, + $this->account ); $this->response = $this->responseDataMapper->mapPaymentResponse($bankResponse, $txType, $order); @@ -336,9 +293,10 @@ public function makeRegularPayment(array $order, CreditCardInterface $creditCard */ public function makeRegularPostPayment(array $order): PosInterface { - $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; + $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; + $paymentModel = PosInterface::MODEL_NON_SECURE; $this->logger->debug('making payment', [ - 'model' => PosInterface::MODEL_NON_SECURE, + 'model' => $paymentModel, 'tx_type' => $txType, ]); @@ -350,7 +308,7 @@ public function makeRegularPostPayment(array $order): PosInterface $txType, \get_class($this), $order, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -364,13 +322,19 @@ public function makeRegularPostPayment(array $order): PosInterface $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( $txType, - PosInterface::MODEL_NON_SECURE, - $this->getApiURL($txType, PosInterface::MODEL_NON_SECURE) + $paymentModel, + $requestData, + $order, + null, + $this->account ); + $this->response = $this->responseDataMapper->mapPaymentResponse($bankResponse, $txType, $order); return $this; @@ -381,7 +345,8 @@ public function makeRegularPostPayment(array $order): PosInterface */ public function refund(array $order): PosInterface { - $txType = PosInterface::TX_TYPE_REFUND; + $txType = PosInterface::TX_TYPE_REFUND; + $paymentModel = PosInterface::MODEL_NON_SECURE; if (isset($order['order_amount']) && $order['amount'] < $order['order_amount']) { $txType = PosInterface::TX_TYPE_REFUND_PARTIAL; } @@ -394,7 +359,7 @@ public function refund(array $order): PosInterface $txType, \get_class($this), $order, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -408,16 +373,17 @@ public function refund(array $order): PosInterface $requestData = $event->getRequestData(); } - $data = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $data, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_NON_SECURE, - $this->getApiURL( - $txType, - PosInterface::MODEL_NON_SECURE, - $order['transaction_type'] ?? null - ) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order, + null, + $this->account ); $this->response = $this->responseDataMapper->mapRefundResponse($bankResponse); @@ -429,7 +395,8 @@ public function refund(array $order): PosInterface */ public function cancel(array $order): PosInterface { - $txType = PosInterface::TX_TYPE_CANCEL; + $txType = PosInterface::TX_TYPE_CANCEL; + $paymentModel = PosInterface::MODEL_NON_SECURE; $requestData = $this->requestDataMapper->createCancelRequestData($this->account, $order); $event = new RequestDataPreparedEvent( @@ -438,7 +405,7 @@ public function cancel(array $order): PosInterface $txType, \get_class($this), $order, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -452,16 +419,17 @@ public function cancel(array $order): PosInterface $requestData = $event->getRequestData(); } - $data = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $data, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_NON_SECURE, - $this->getApiURL( - $txType, - PosInterface::MODEL_NON_SECURE, - $order['transaction_type'] ?? null - ) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order, + null, + $this->account ); $this->response = $this->responseDataMapper->mapCancelResponse($bankResponse); @@ -473,7 +441,8 @@ public function cancel(array $order): PosInterface */ public function status(array $order): PosInterface { - $txType = PosInterface::TX_TYPE_STATUS; + $txType = PosInterface::TX_TYPE_STATUS; + $paymentModel = PosInterface::MODEL_NON_SECURE; $requestData = $this->requestDataMapper->createStatusRequestData($this->account, $order); $event = new RequestDataPreparedEvent( @@ -482,7 +451,7 @@ public function status(array $order): PosInterface $txType, \get_class($this), $order, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -496,13 +465,19 @@ public function status(array $order): PosInterface $requestData = $event->getRequestData(); } - $data = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $data, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( $txType, - PosInterface::MODEL_NON_SECURE, - $this->getQueryAPIUrl($txType) + $paymentModel, + $requestData, + $order, + null, + $this->account ); + $this->response = $this->responseDataMapper->mapStatusResponse($bankResponse); return $this; @@ -513,7 +488,8 @@ public function status(array $order): PosInterface */ public function history(array $data): PosInterface { - $txType = PosInterface::TX_TYPE_HISTORY; + $txType = PosInterface::TX_TYPE_HISTORY; + $paymentModel = PosInterface::MODEL_NON_SECURE; $requestData = $this->requestDataMapper->createHistoryRequestData($this->account, $data); $event = new RequestDataPreparedEvent( @@ -522,7 +498,7 @@ public function history(array $data): PosInterface $txType, \get_class($this), $data, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -536,13 +512,19 @@ public function history(array $data): PosInterface $requestData = $event->getRequestData(); } - $encodedRequestData = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $encodedRequestData, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_NON_SECURE, - $this->getApiURL($txType, PosInterface::MODEL_NON_SECURE) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $data, + null, + $this->account ); + $this->response = $this->responseDataMapper->mapHistoryResponse($bankResponse); return $this; @@ -553,7 +535,8 @@ public function history(array $data): PosInterface */ public function orderHistory(array $order): PosInterface { - $txType = PosInterface::TX_TYPE_ORDER_HISTORY; + $txType = PosInterface::TX_TYPE_ORDER_HISTORY; + $paymentModel = PosInterface::MODEL_NON_SECURE; $requestData = $this->requestDataMapper->createOrderHistoryRequestData($this->account, $order); $event = new RequestDataPreparedEvent( @@ -562,7 +545,7 @@ public function orderHistory(array $order): PosInterface $txType, \get_class($this), $order, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -576,13 +559,19 @@ public function orderHistory(array $order): PosInterface $requestData = $event->getRequestData(); } - $data = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $data, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( $txType, - PosInterface::MODEL_NON_SECURE, - $this->getApiURL($txType, PosInterface::MODEL_NON_SECURE) + $paymentModel, + $requestData, + $order, + null, + $this->account ); + $this->response = $this->responseDataMapper->mapOrderHistoryResponse($bankResponse); return $this; @@ -593,7 +582,8 @@ public function orderHistory(array $order): PosInterface */ public function customQuery(array $requestData, ?string $apiUrl = null): PosInterface { - $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $paymentModel = PosInterface::MODEL_NON_SECURE; $updatedRequestData = $this->requestDataMapper->createCustomQueryRequestData($this->account, $requestData); $event = new RequestDataPreparedEvent( @@ -602,7 +592,7 @@ public function customQuery(array $requestData, ?string $apiUrl = null): PosInte $txType, \get_class($this), $requestData, - PosInterface::MODEL_NON_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ @@ -617,15 +607,21 @@ public function customQuery(array $requestData, ?string $apiUrl = null): PosInte $updatedRequestData = $event->getRequestData(); } - $data = $this->serializer->encode($updatedRequestData, $txType); - $apiUrl ??= $this->getQueryAPIUrl($txType); - $this->response = $this->send( - $data, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( $txType, - PosInterface::MODEL_NON_SECURE, - $apiUrl + $paymentModel, + $updatedRequestData, + $requestData, + $apiUrl, + $this->account ); + $this->response = $bankResponse; + return $this; } @@ -646,7 +642,7 @@ public function setTestMode(bool $testMode): PosInterface */ public function getCardTypeMapping(): array { - return $this->requestDataMapper->getCardTypeMapping(); + return $this->valueMapper->getCardTypeMappings(); } /** @@ -654,7 +650,7 @@ public function getCardTypeMapping(): array */ public function getLanguages(): array { - return [PosInterface::LANG_TR, PosInterface::LANG_EN]; + return \array_keys($this->valueMapper->getLangMappings()); } /** @@ -673,24 +669,6 @@ public static function isSupportedTransaction(string $txType, string $paymentMod return \in_array($paymentModel, static::$supportedTransactions[$txType], true); } - /** - * Send requests to bank APIs - * - * @phpstan-param PosInterface::TX_TYPE_* $txType - * @phpstan-param PosInterface::MODEL_* $paymentModel - * - * @param array|string $contents data to send - * @param string $txType - * @param string $paymentModel - * @param non-empty-string $url URL address of the API - * - * @return array - * - * @throws ClientExceptionInterface - * @throws UnsupportedTransactionTypeException - */ - abstract protected function send($contents, string $txType, string $paymentModel, string $url): array; - /** * @param array $responseData * @@ -721,7 +699,7 @@ protected function is3DAuthSuccess(array $responseData): bool */ protected function check3DFormInputs(string $paymentModel, string $txType, ?CreditCardInterface $card = null, bool $createWithoutCard = false): void { - $paymentModels = self::getSupported3DPaymentModelsForPaymentTransaction($txType); + $paymentModels = $this->getSupported3DPaymentModelsForPaymentTransaction($txType); if (!self::isSupportedTransaction($txType, $paymentModel)) { throw new \LogicException(\sprintf( '%s ödeme altyapıda [%s] işlem tipi [%s] ödeme model(ler) desteklemektedir. Sağlanan ödeme model: [%s].', @@ -736,7 +714,7 @@ protected function check3DFormInputs(string $paymentModel, string $txType, ?Cred throw new \LogicException(\sprintf( 'Kart bilgileri ile form verisi oluşturmak icin [%s] ödeme modeli kullanmayınız! Yerine [%s] ödeme model(ler)ini kullanınız.', $paymentModel, - \implode(', ', self::getSupported3DPaymentModelsForPaymentTransaction($txType, true)) + \implode(', ', $this->getSupported3DPaymentModelsForPaymentTransaction($txType, true)) )); } @@ -745,7 +723,7 @@ protected function check3DFormInputs(string $paymentModel, string $txType, ?Cred } if ((PosInterface::MODEL_3D_SECURE === $paymentModel || PosInterface::MODEL_3D_PAY === $paymentModel) - && null === $card + && !$card instanceof \Mews\Pos\Entity\Card\CreditCardInterface ) { throw new \LogicException('Bu ödeme modeli için kart bilgileri zorunlu!'); } @@ -762,7 +740,7 @@ protected function is3DHashCheckDisabled(): bool /** * @return array */ - private static function getSupport3DTxTypes(): array + private function getSupport3DTxTypes(): array { $threeDSupportedTxTypes = []; $txTypes = [ @@ -785,9 +763,9 @@ private static function getSupport3DTxTypes(): array * * @return array */ - private static function getSupported3DPaymentModelsForPaymentTransaction(string $txType, ?bool $withCard = null): array + private function getSupported3DPaymentModelsForPaymentTransaction(string $txType, ?bool $withCard = null): array { - $supported3DPaymentTxs = self::getSupport3DTxTypes(); + $supported3DPaymentTxs = $this->getSupport3DTxTypes(); if (!\in_array($txType, $supported3DPaymentTxs, true)) { throw new \LogicException(\sprintf( 'Hatalı işlem tipi! Desteklenen işlem tipleri: [%s].', diff --git a/src/Gateways/AkbankPos.php b/src/Gateways/AkbankPos.php index d9c41c31..b5160afe 100644 --- a/src/Gateways/AkbankPos.php +++ b/src/Gateways/AkbankPos.php @@ -57,20 +57,6 @@ class AkbankPos extends AbstractGateway PosInterface::TX_TYPE_CUSTOM_QUERY => true, ]; - /** - * @inheritDoc - * - * @throws \InvalidArgumentException when transaction type is not provided - */ - public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string - { - if (null !== $txType) { - return parent::getApiURL().'/'.$this->getRequestURIByTransactionType($txType); - } - - throw new \InvalidArgumentException('Transaction type is required to generate API URL'); - } - /** @return AkbankPosAccount */ public function getAccount(): AbstractPosAccount { @@ -82,11 +68,12 @@ public function getAccount(): AbstractPosAccount */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = PosInterface::MODEL_3D_SECURE; - if (!$this->is3DAuthSuccess($request->all())) { + if (!$this->is3DAuthSuccess($postParameters->all())) { $this->response = $this->responseDataMapper->map3DPaymentData( - $request->all(), + $postParameters->all(), null, $txType, $order @@ -97,12 +84,17 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C if ( !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } - $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $request->all()); + $requestData = $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + $order, + $txType, + $postParameters->all() + ); $event = new RequestDataPreparedEvent( $requestData, @@ -110,7 +102,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -124,16 +116,21 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $provisionResponse = $this->send( - $contents, + /** @var array $provisionResponse */ + $provisionResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL($txType) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order, + null, + $this->account ); $this->response = $this->responseDataMapper->map3DPaymentData( - $request->all(), + $postParameters->all(), $provisionResponse, $txType, $order @@ -205,57 +202,4 @@ public function status(array $order): PosInterface { throw new UnsupportedTransactionTypeException(); } - - /** - * @inheritDoc - * - * @return array - * - * @throws \RuntimeException thrown when we get HTTP 400 error - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - if (!\is_string($contents)) { - throw new \InvalidArgumentException(\sprintf('Argument type must be string, %s provided.', \gettype($contents))); - } - - $hash = $this->requestDataMapper->getCrypt()->hashString($contents, $this->account->getStoreKey()); - - $response = $this->client->post($url, [ - 'headers' => [ - 'Content-Type' => 'application/json', - 'auth-hash' => $hash, - ], - 'body' => $contents, - ]); - - if ($response->getStatusCode() === 400) { - $this->logger->error('api error', ['status_code' => $response->getStatusCode()]); - - // when the data is sent fails validation checks we get 400 error - $data = $this->serializer->decode($response->getBody()->getContents(), $txType); - throw new \RuntimeException($data['message'], $data['code']); - } - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } - - /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * - * @param string $txType - * - * @return string - */ - private function getRequestURIByTransactionType(string $txType): string - { - $arr = [ - PosInterface::TX_TYPE_HISTORY => 'portal/report/transaction', - ]; - - return $arr[$txType] ?? 'transaction/process'; - } } diff --git a/src/Gateways/EstPos.php b/src/Gateways/EstPos.php index 3d17001f..c70f3f95 100644 --- a/src/Gateways/EstPos.php +++ b/src/Gateways/EstPos.php @@ -66,7 +66,8 @@ public function getAccount(): AbstractPosAccount */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = PosInterface::MODEL_3D_SECURE; /** * TODO hata durumu ele alinmasi gerekiyor @@ -74,9 +75,9 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C * ["ProcReturnCode" => "99", "mdStatus" => "7", "mdErrorMsg" => "Isyeri kullanim tipi desteklenmiyor.", * "ErrMsg" => "Isyeri kullanim tipi desteklenmiyor.", "Response" => "Error", "ErrCode" => "3D-1007", ...] */ - if (!$this->is3DAuthSuccess($request->all())) { + if (!$this->is3DAuthSuccess($postParameters->all())) { $this->response = $this->responseDataMapper->map3DPaymentData( - $request->all(), + $postParameters->all(), null, $txType, $order @@ -87,13 +88,13 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C if ( !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } /** @var array{md: string, xid: string, eci: string, cavv: string} $bankPostData */ - $bankPostData = $request->all(); + $bankPostData = $postParameters->all(); $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $bankPostData); @@ -103,7 +104,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -117,16 +118,19 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $provisionResponse = $this->send( - $contents, + /** @var array $provisionResponse */ + $provisionResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order, ); $this->response = $this->responseDataMapper->map3DPaymentData( - $request->all(), + $postParameters->all(), $provisionResponse, $txType, $order @@ -198,19 +202,4 @@ public function history(array $data): PosInterface { throw new UnsupportedTransactionTypeException(); } - - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - $response = $this->client->post($url, ['body' => $contents]); - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } } diff --git a/src/Gateways/GarantiPos.php b/src/Gateways/GarantiPos.php index b2a1c103..1e8b1fbb 100644 --- a/src/Gateways/GarantiPos.php +++ b/src/Gateways/GarantiPos.php @@ -70,22 +70,28 @@ public function getAccount(): AbstractPosAccount */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = PosInterface::MODEL_3D_SECURE; - if (!$this->is3DAuthSuccess($request->all())) { - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), null, $txType, $order); + if (!$this->is3DAuthSuccess($postParameters->all())) { + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), null, $txType, $order); return $this; } if ( !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } - $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $request->all()); + $requestData = $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + $order, + $txType, + $postParameters->all() + ); $event = new RequestDataPreparedEvent( $requestData, @@ -93,7 +99,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -107,15 +113,18 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), $bankResponse, $txType, $order); + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), $bankResponse, $txType, $order); $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); return $this; @@ -159,19 +168,4 @@ public function make3DHostPayment(Request $request, array $order, string $txType { throw new UnsupportedPaymentModelException(); } - - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - - $response = $this->client->post($url, ['body' => $contents]); - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } } diff --git a/src/Gateways/InterPos.php b/src/Gateways/InterPos.php index ccfda0c5..2ca7421e 100644 --- a/src/Gateways/InterPos.php +++ b/src/Gateways/InterPos.php @@ -6,7 +6,6 @@ namespace Mews\Pos\Gateways; -use InvalidArgumentException; use Mews\Pos\DataMapper\RequestDataMapper\InterPosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; use Mews\Pos\DataMapper\ResponseDataMapper\InterPosResponseDataMapper; @@ -73,9 +72,11 @@ public function getAccount(): AbstractPosAccount */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = PosInterface::MODEL_3D_SECURE; + /** @var array{"3DStatus": string, MD: string, PayerTxnId: string, Eci: string, PayerAuthenticationCode: string} $gatewayResponse */ - $gatewayResponse = $request->all(); + $gatewayResponse = $postParameters->all(); if (!$this->is3DAuthSuccess($gatewayResponse)) { $this->response = $this->responseDataMapper->map3DPaymentData($gatewayResponse, null, $txType, $order); @@ -100,7 +101,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -114,12 +115,15 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); $this->response = $this->responseDataMapper->map3DPaymentData($gatewayResponse, $bankResponse, $txType, $order); @@ -185,28 +189,4 @@ public function get3DFormData(array $order, string $paymentModel, string $txType $creditCard ); } - - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - if (!\is_string($contents)) { - throw new InvalidArgumentException(\sprintf('Argument type must be string, %s provided.', \gettype($contents))); - } - - $response = $this->client->post($url, [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => $contents, - ]); - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } } diff --git a/src/Gateways/KuveytPos.php b/src/Gateways/KuveytPos.php index 968d8ac5..3472d663 100644 --- a/src/Gateways/KuveytPos.php +++ b/src/Gateways/KuveytPos.php @@ -47,10 +47,10 @@ class KuveytPos extends AbstractGateway ], PosInterface::TX_TYPE_PAY_PRE_AUTH => false, PosInterface::TX_TYPE_PAY_POST_AUTH => false, - PosInterface::TX_TYPE_STATUS => true, - PosInterface::TX_TYPE_CANCEL => true, - PosInterface::TX_TYPE_REFUND => true, - PosInterface::TX_TYPE_REFUND_PARTIAL => true, + PosInterface::TX_TYPE_STATUS => false, + PosInterface::TX_TYPE_CANCEL => false, + PosInterface::TX_TYPE_REFUND => false, + PosInterface::TX_TYPE_REFUND_PARTIAL => false, PosInterface::TX_TYPE_HISTORY => false, PosInterface::TX_TYPE_ORDER_HISTORY => false, PosInterface::TX_TYPE_CUSTOM_QUERY => false, @@ -64,46 +64,42 @@ public function getAccount(): AbstractPosAccount /** * @inheritDoc - * - * @throws UnsupportedTransactionTypeException - * @throws \InvalidArgumentException when transaction type is not provided */ - public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string + public function make3DPayPayment(Request $request, array $order, string $txType): PosInterface { - if (\in_array( - $txType, - [ - PosInterface::TX_TYPE_REFUND, - PosInterface::TX_TYPE_REFUND_PARTIAL, - PosInterface::TX_TYPE_STATUS, - PosInterface::TX_TYPE_CANCEL, - ], - true - )) { - return $this->getQueryAPIUrl(); - } + throw new UnsupportedPaymentModelException(); + } - if (null !== $txType && null !== $paymentModel) { - return parent::getApiURL().'/'.$this->getRequestURIByTransactionType($txType, $paymentModel); - } + /** + * @inheritDoc + */ + public function make3DHostPayment(Request $request, array $order, string $txType): PosInterface + { + throw new UnsupportedPaymentModelException(); + } - throw new \InvalidArgumentException('Transaction type is required to generate API URL'); + /** + * @inheritDoc + */ + public function status(array $order): PosInterface + { + throw new UnsupportedTransactionTypeException('Bu işlem için KuveytSoapApiPos gateway kullanılmalıdır!'); } /** * @inheritDoc */ - public function make3DPayPayment(Request $request, array $order, string $txType): PosInterface + public function cancel(array $order): PosInterface { - throw new UnsupportedPaymentModelException(); + throw new UnsupportedTransactionTypeException('Bu işlem için KuveytSoapApiPos gateway kullanılmalıdır!'); } /** * @inheritDoc */ - public function make3DHostPayment(Request $request, array $order, string $txType): PosInterface + public function refund(array $order): PosInterface { - throw new UnsupportedPaymentModelException(); + throw new UnsupportedTransactionTypeException('Bu işlem için KuveytSoapApiPos gateway kullanılmalıdır!'); } /** @@ -127,9 +123,9 @@ public function orderHistory(array $order): PosInterface /** * @inheritDoc * - * @return array{gateway: string, method: 'POST', inputs: array} + * @return string */ - public function get3DFormData(array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null, bool $createWithoutCard = true): array + public function get3DFormData(array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null, bool $createWithoutCard = true): string { $this->check3DFormInputs($paymentModel, $txType, $creditCard, $createWithoutCard); @@ -140,7 +136,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType $order, $paymentModel, $txType, - $this->get3DGatewayURL($paymentModel), $creditCard ); } @@ -158,6 +153,7 @@ public function makeRegularPostPayment(array $order): PosInterface */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { + $paymentModel = PosInterface::MODEL_3D_SECURE; $gatewayResponse = $request->request->get('AuthenticationResponse'); if (!\is_string($gatewayResponse)) { throw new LogicException('AuthenticationResponse is missing'); @@ -182,7 +178,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -196,12 +192,15 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL($txType, PosInterface::MODEL_3D_SECURE) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); $this->response = $this->responseDataMapper->map3DPaymentData($gatewayResponse, $bankResponse, $txType, $order); @@ -210,94 +209,6 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C return $this; } - - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - if (!\is_string($contents)) { - throw new \InvalidArgumentException(\sprintf('Argument type must be string, %s provided.', \gettype($contents))); - } - - if (\in_array($txType, [ - PosInterface::TX_TYPE_REFUND, - PosInterface::TX_TYPE_REFUND_PARTIAL, - PosInterface::TX_TYPE_STATUS, - PosInterface::TX_TYPE_CANCEL, - ], true)) { - return $this->data = $this->sendSoapRequest($contents, $txType, $url); - } - - $this->logger->debug('sending request', ['url' => $url]); - $body = [ - 'body' => $contents, - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - ], - ]; - $response = $this->client->post($url, $body); - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } - - /** - * @phpstan-param PosInterface::TX_TYPE_STATUS|PosInterface::TX_TYPE_REFUND|PosInterface::TX_TYPE_REFUND_PARTIAL|PosInterface::TX_TYPE_CANCEL|PosInterface::TX_TYPE_CUSTOM_QUERY $txType - * - * @param string $contents - * @param string $txType - * @param string $url - * - * @return array - * - * @throws ClientExceptionInterface - * @throws UnsupportedTransactionTypeException - */ - private function sendSoapRequest(string $contents, string $txType, string $url): array - { - $soapActionHeader = 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/'.$this->requestDataMapper->mapTxType($txType); - $this->logger->debug('sending soap request', [ - 'txType' => $txType, - 'url' => $url, - 'action' => $soapActionHeader, - ]); - - $body = [ - 'body' => $contents, - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - 'SOAPAction' => $soapActionHeader, - ], - ]; - - $response = $this->client->post($url, $body); - $responseContent = $response->getBody()->getContents(); - if ('' === $responseContent) { - $this->logger->error('soap error response', [ - 'status_code' => $response->getStatusCode(), - ]); - - throw new \RuntimeException('Bankaya istek başarısız!', 9303); - } - - $this->logger->debug('soap request completed', ['status_code' => $response->getStatusCode()]); - $decodedData = $this->serializer->decode($responseContent, $txType); - - if (isset($decodedData['s:Fault'])) { - $this->logger->error('soap error response', [ - 'status_code' => $response->getStatusCode(), - 'response' => $decodedData, - ]); - - throw new \RuntimeException($decodedData['s:Fault']['faultstring']['#'] ?? 'Bankaya istek başarısız!'); - } - - return $this->data = $decodedData; - } - /** * @phpstan-param PosInterface::MODEL_3D_* $paymentModel * @phpstan-param PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType @@ -306,16 +217,15 @@ private function sendSoapRequest(string $contents, string $txType, string $url): * @param array $order * @param string $paymentModel * @param string $txType - * @param non-empty-string $gatewayURL * @param CreditCardInterface|null $creditCard * - * @return array{gateway: string, method: 'POST', inputs: array} + * @return string HTML form * * @throws RuntimeException * @throws UnsupportedTransactionTypeException * @throws ClientExceptionInterface */ - private function getCommon3DFormData(KuveytPosAccount $kuveytPosAccount, array $order, string $paymentModel, string $txType, string $gatewayURL, ?CreditCardInterface $creditCard = null): array + private function getCommon3DFormData(KuveytPosAccount $kuveytPosAccount, array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null): string { $requestData = $this->requestDataMapper->create3DEnrollmentCheckRequestData( $kuveytPosAccount, @@ -345,41 +255,17 @@ private function getCommon3DFormData(KuveytPosAccount $kuveytPosAccount, array $ $requestData = $event->getRequestData(); } - $data = $this->serializer->encode($requestData, $txType); - - /** - * @var array{form_inputs: array, gateway: string} $decodedResponse - */ - $decodedResponse = $this->send($data, $txType, $paymentModel, $gatewayURL); - - return $this->requestDataMapper->create3DFormData($this->account, $decodedResponse['form_inputs'], $paymentModel, $txType, $decodedResponse['gateway'], $creditCard); - } - - /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * @phpstan-param PosInterface::MODEL_* $paymentModel - * - * @return string - * - * @throws UnsupportedTransactionTypeException - */ - private function getRequestURIByTransactionType(string $txType, string $paymentModel): string - { - $arr = [ - PosInterface::TX_TYPE_PAY_AUTH => [ - PosInterface::MODEL_NON_SECURE => 'Non3DPayGate', - PosInterface::MODEL_3D_SECURE => 'ThreeDModelProvisionGate', - ], - ]; - - if (!isset($arr[$txType])) { - throw new UnsupportedTransactionTypeException(); - } - - if (!isset($arr[$txType][$paymentModel])) { - throw new UnsupportedTransactionTypeException(); - } + /** @var string $result */ + $result = $this->clientStrategy->getClient( + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order, + ); - return $arr[$txType][$paymentModel]; + return $result; } } diff --git a/src/Gateways/KuveytSoapApiPos.php b/src/Gateways/KuveytSoapApiPos.php new file mode 100644 index 00000000..c4bcecc2 --- /dev/null +++ b/src/Gateways/KuveytSoapApiPos.php @@ -0,0 +1,131 @@ + false, + PosInterface::TX_TYPE_PAY_PRE_AUTH => false, + PosInterface::TX_TYPE_PAY_POST_AUTH => false, + PosInterface::TX_TYPE_STATUS => true, + PosInterface::TX_TYPE_CANCEL => true, + PosInterface::TX_TYPE_REFUND => true, + PosInterface::TX_TYPE_REFUND_PARTIAL => true, + PosInterface::TX_TYPE_HISTORY => false, + PosInterface::TX_TYPE_ORDER_HISTORY => false, + PosInterface::TX_TYPE_CUSTOM_QUERY => false, + ]; + + /** @return KuveytPosAccount */ + public function getAccount(): AbstractPosAccount + { + return $this->account; + } + + /** + * @inheritDoc + */ + public function make3DPayPayment(Request $request, array $order, string $txType): PosInterface + { + throw new UnsupportedPaymentModelException(); + } + + /** + * @inheritDoc + */ + public function make3DHostPayment(Request $request, array $order, string $txType): PosInterface + { + throw new UnsupportedPaymentModelException(); + } + + /** + * Kuveyt bank dokumantasyonunda history sorgusu ile alakali hic bir bilgi yok + * @inheritDoc + */ + public function history(array $data): PosInterface + { + throw new UnsupportedTransactionTypeException(); + } + + /** + * Kuveyt bank dokumantasyonunda history sorgusu ile alakali hic bir bilgi yok + * @inheritDoc + */ + public function orderHistory(array $order): PosInterface + { + throw new UnsupportedTransactionTypeException(); + } + + /** + * @inheritDoc + */ + public function get3DFormData(array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null, bool $createWithoutCard = true) + { + throw new UnsupportedPaymentModelException('Bu işlem için KuveytPos gateway kullanılmalıdır.'); + } + + /** + * @inheritDoc + */ + public function makeRegularPayment(array $order, CreditCardInterface $creditCard, string $txType): PosInterface + { + throw new UnsupportedPaymentModelException(); + } + + /** + * @inheritDoc + */ + public function makeRegularPostPayment(array $order): PosInterface + { + throw new UnsupportedPaymentModelException(); + } + + /** + * @inheritDoc + */ + public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface + { + throw new UnsupportedPaymentModelException('Bu işlem için KuveytPos gateway kullanılmalıdır.'); + } + + /** + * @inheritDoc + */ + public function customQuery(array $requestData, ?string $apiUrl = null): PosInterface + { + throw new UnsupportedTransactionTypeException(); + } +} diff --git a/src/Gateways/Param3DHostPos.php b/src/Gateways/Param3DHostPos.php new file mode 100644 index 00000000..2fd102e9 --- /dev/null +++ b/src/Gateways/Param3DHostPos.php @@ -0,0 +1,254 @@ + [ + PosInterface::MODEL_3D_HOST, + ], + PosInterface::TX_TYPE_HISTORY => false, + PosInterface::TX_TYPE_ORDER_HISTORY => false, + PosInterface::TX_TYPE_PAY_POST_AUTH => false, + PosInterface::TX_TYPE_CANCEL => false, + PosInterface::TX_TYPE_REFUND => false, + PosInterface::TX_TYPE_REFUND_PARTIAL => false, + PosInterface::TX_TYPE_STATUS => false, + PosInterface::TX_TYPE_CUSTOM_QUERY => false, + ]; + + /** + * @return ParamPosAccount + */ + public function getAccount(): AbstractPosAccount + { + return $this->account; + } + + /** + * @inheritDoc + */ + public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface + { + throw new UnsupportedPaymentModelException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function make3DPayPayment(Request $request, array $order, string $txType): PosInterface + { + throw new UnsupportedPaymentModelException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function make3DHostPayment(Request $request, array $order, string $txType): PosInterface + { + if ( + !$this->is3DHashCheckDisabled() + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->request->all()) + ) { + throw new HashMismatchException(); + } + + $this->response = $this->responseDataMapper->map3DHostResponseData($request->request->all(), $txType, $order); + + $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); + + return $this; + } + + /** + * @inheritDoc + */ + public function makeRegularPayment(array $order, CreditCardInterface $creditCard, string $txType): PosInterface + { + throw new UnsupportedPaymentModelException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function makeRegularPostPayment(array $order): PosInterface + { + throw new UnsupportedTransactionTypeException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function get3DFormData(array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null, bool $createWithoutCard = true) + { + $this->check3DFormInputs($paymentModel, $txType, $creditCard); + + $data = $this->registerPayment($order, $paymentModel, $txType); + + return $this->requestDataMapper->create3DFormData( + $this->account, + $order, + $paymentModel, + $txType, + $this->get3DGatewayURL($paymentModel), + null, + $data + ); + } + + /** + * @inheritDoc + */ + public function status(array $order): PosInterface + { + throw new UnsupportedTransactionTypeException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function cancel(array $order): PosInterface + { + throw new UnsupportedTransactionTypeException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function refund(array $order): PosInterface + { + throw new UnsupportedTransactionTypeException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function history(array $data): PosInterface + { + throw new UnsupportedTransactionTypeException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @inheritDoc + */ + public function orderHistory(array $order): PosInterface + { + throw new UnsupportedTransactionTypeException(); + } + + /** + * @inheritDoc + */ + public function customQuery(array $requestData, ?string $apiUrl = null): PosInterface + { + throw new UnsupportedTransactionTypeException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', ParamPos::class) + ); + } + + /** + * @param array $order + * @param PosInterface::MODEL_3D_* $paymentModel + * @param PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType + * + * @return array + * + * @throws UnsupportedTransactionTypeException + * @throws ClientExceptionInterface + */ + private function registerPayment(array $order, string $paymentModel, string $txType): array + { + $requestData = $this->requestDataMapper->create3DEnrollmentCheckRequestData( + $this->account, + $order, + $txType + ); + + $event = new RequestDataPreparedEvent( + $requestData, + $this->account->getBank(), + $txType, + \get_class($this), + $order, + $paymentModel + ); + /** @var RequestDataPreparedEvent $event */ + $event = $this->eventDispatcher->dispatch($event); + if ($requestData !== $event->getRequestData()) { + $this->logger->debug('Request data is changed via listeners', [ + 'txType' => $event->getTxType(), + 'bank' => $event->getBank(), + 'initialData' => $requestData, + 'updatedData' => $event->getRequestData(), + ]); + $requestData = $event->getRequestData(); + } + + /** @var array $result */ + $result = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order + ); + + return $result; + } +} diff --git a/src/Gateways/ParamPos.php b/src/Gateways/ParamPos.php index a931726c..4817649d 100644 --- a/src/Gateways/ParamPos.php +++ b/src/Gateways/ParamPos.php @@ -15,6 +15,7 @@ use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\RequestDataPreparedEvent; use Mews\Pos\Exceptions\HashMismatchException; +use Mews\Pos\Exceptions\UnsupportedPaymentModelException; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\PosInterface; use Psr\Http\Client\ClientExceptionInterface; @@ -44,7 +45,6 @@ class ParamPos extends AbstractGateway PosInterface::TX_TYPE_PAY_AUTH => [ PosInterface::MODEL_3D_SECURE, PosInterface::MODEL_3D_PAY, - PosInterface::MODEL_3D_HOST, PosInterface::MODEL_NON_SECURE, ], PosInterface::TX_TYPE_PAY_PRE_AUTH => [ @@ -70,37 +70,23 @@ public function getAccount(): AbstractPosAccount return $this->account; } - /** - * @inheritDoc - */ - public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string - { - if (PosInterface::MODEL_3D_HOST === $paymentModel) { - if (!isset($this->config['gateway_endpoints']['payment_api_2'])) { - throw new \RuntimeException('3D Host ödemeyi kullanabilmek için "payment_api_2" endpointi tanımlanmalıdır.'); - } - - return $this->config['gateway_endpoints']['payment_api_2']; - } - - return parent::getApiURL($txType, $paymentModel, $orderTxType); - } - /** * @inheritDoc */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - if ($request->request->get('TURKPOS_RETVAL_Sonuc') !== null) { + $paymentModel = PosInterface::MODEL_3D_SECURE; + $postParameters = $request->request; + + if ($postParameters->get('TURKPOS_RETVAL_Sonuc') !== null) { // Doviz ile odeme return $this->make3DPayPayment($request, $order, $txType); } - $request = $request->request; - if (!$this->is3DAuthSuccess($request->all())) { + if (!$this->is3DAuthSuccess($postParameters->all())) { $this->response = $this->responseDataMapper->map3DPaymentData( - $request->all(), + $postParameters->all(), null, $txType, $order @@ -111,12 +97,17 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C if ( !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } - $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $request->all()); + $requestData = $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + $order, + $txType, + $postParameters->all() + ); $event = new RequestDataPreparedEvent( $requestData, @@ -124,7 +115,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -138,16 +129,19 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $provisionResponse = $this->send( - $contents, + /** @var array $provisionResponse */ + $provisionResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL($txType) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); $this->response = $this->responseDataMapper->map3DPaymentData( - $request->all(), + $postParameters->all(), $provisionResponse, $txType, $order @@ -179,18 +173,9 @@ public function make3DPayPayment(Request $request, array $order, string $txType) */ public function make3DHostPayment(Request $request, array $order, string $txType): PosInterface { - if ( - !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->request->all()) - ) { - throw new HashMismatchException(); - } - - $this->response = $this->responseDataMapper->map3DHostResponseData($request->request->all(), $txType, $order); - - $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); - - return $this; + throw new UnsupportedPaymentModelException( + \sprintf('Bu işlem için %s gateway kullanılmalıdır.', Param3DHostPos::class) + ); } /** @@ -202,18 +187,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType $data = $this->registerPayment($order, $paymentModel, $txType, $creditCard); - if (PosInterface::MODEL_3D_HOST === $paymentModel) { - return $this->requestDataMapper->create3DFormData( - $this->account, - $order, - $paymentModel, - $txType, - $this->get3DGatewayURL($paymentModel), - null, - $data - ); - } - $result = $data['TP_WMD_UCDResponse']['TP_WMD_UCDResult'] ?? $data['TP_Islem_Odeme_WDResponse']['TP_Islem_Odeme_WDResult'] ?? $data['TP_Islem_Odeme_OnProv_WMDResponse']['TP_Islem_Odeme_OnProv_WMDResult'] // on provizyon @@ -236,16 +209,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType ); } - /** - * @inheritDoc - */ - public function customQuery(array $requestData, ?string $apiUrl = null): PosInterface - { - $apiUrl ??= $this->getApiURL(PosInterface::TX_TYPE_CUSTOM_QUERY); - - return parent::customQuery($requestData, $apiUrl); - } - /** * @inheritDoc */ @@ -254,41 +217,6 @@ public function orderHistory(array $order): PosInterface throw new UnsupportedTransactionTypeException(); } - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - - - $response = $this->client->post($url, [ - 'headers' => [ - 'Content-Type' => 'text/xml', - ], - 'body' => $contents, - ]); - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - $responseContent = $response->getBody()->getContents(); - - $decodedData = $this->serializer->decode($responseContent, $txType); - - if (isset($decodedData['soap:Fault'])) { - $this->logger->error('soap error response', [ - 'status_code' => $response->getStatusCode(), - 'response' => $decodedData, - ]); - - throw new \RuntimeException($decodedData['soap:Fault']['faultstring'] ?? 'Bankaya istek başarısız!'); - } - - return $this->data = $decodedData; - } - /** * @param array $order * @param PosInterface::MODEL_3D_* $paymentModel @@ -329,13 +257,17 @@ private function registerPayment(array $order, string $paymentModel, string $txT $requestData = $event->getRequestData(); } - $requestData = $this->serializer->encode($requestData, $txType); - - return $this->send( - $requestData, + /** @var array $result */ + $result = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( $txType, $paymentModel, - $this->getApiURL($txType, $paymentModel) + $requestData, + $order ); + + return $result; } } diff --git a/src/Gateways/PayFlexCPV4Pos.php b/src/Gateways/PayFlexCPV4Pos.php index ba687646..872855a2 100644 --- a/src/Gateways/PayFlexCPV4Pos.php +++ b/src/Gateways/PayFlexCPV4Pos.php @@ -202,33 +202,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType ); } - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - if (!\is_string($contents)) { - throw new \InvalidArgumentException(\sprintf('Argument type must be string, %s provided.', \gettype($contents))); - } - - $response = $this->client->post($url, [ - 'headers' => [ - 'Accept' => 'text/xml', - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => $contents, - ]); - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - $responseContent = $response->getBody()->getContents(); - - return $this->data = $this->serializer->decode($responseContent, $txType); - } - /** * * ORTAK ÖDEME SİSTEMİNE İŞLEM KAYDETME @@ -280,21 +253,22 @@ private function registerPayment(array $order, string $txType, string $paymentMo $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - /** @var array{CommonPaymentUrl: string|null, PaymentToken: string|null, ErrorCode: string|null, ResponseMessage: string|null} $response */ - $response = $this->send( - $contents, + $response = $this->clientStrategy->getClient( + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, + $paymentModel, + )->request( $txType, $paymentModel, - $this->get3DGatewayURL() + $requestData, + $order ); return $response; } /** - * get 3D Payment status to make sure that payment was successful + * get 3D Payment status to make sure that payment was successful * @param Request $request * @param array $order * @@ -342,16 +316,17 @@ private function get3DPaymentStatus(Request $request, array $order): array $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - - /** - * sending request to make sure that payment was successful - */ - return $this->send( - $contents, + /** @var array $result */ + $result = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( $txType, $paymentModel, - $this->getApiURL() + $requestData, + $order ); + + return $result; } } diff --git a/src/Gateways/PayFlexV4Pos.php b/src/Gateways/PayFlexV4Pos.php index 3de8c6e4..54d2b5dc 100644 --- a/src/Gateways/PayFlexV4Pos.php +++ b/src/Gateways/PayFlexV4Pos.php @@ -71,16 +71,17 @@ public function getAccount(): AbstractPosAccount */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = PosInterface::MODEL_3D_SECURE; - if (!$this->is3DAuthSuccess($request->all())) { - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), null, $txType, $order); + if (!$this->is3DAuthSuccess($postParameters->all())) { + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), null, $txType, $order); return $this; } /** @var array{Eci: string, Cavv: string, VerifyEnrollmentRequestId: string} $requestData */ - $requestData = $request->all(); + $requestData = $postParameters->all(); // NOT: diger gatewaylerden farkli olarak payflex kredit bilgilerini bu asamada da istiyor. $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $requestData, $creditCard); @@ -90,7 +91,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -104,15 +105,18 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order, ); - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), $bankResponse, $txType, $order); + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), $bankResponse, $txType, $order); $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); return $this; @@ -134,14 +138,6 @@ public function make3DHostPayment(Request $request, array $order, string $txType throw new UnsupportedPaymentModelException(); } - /** - * @inheritDoc - */ - public function customQuery(array $requestData, ?string $apiUrl = null): PosInterface - { - return parent::customQuery($requestData, $apiUrl ?? $this->getApiURL()); - } - /** * @inheritDoc */ @@ -206,25 +202,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType ); } - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - - $isXML = \is_string($contents); - - $response = $this->client->post($url, [ - 'form_params' => $isXML ? ['prmstr' => $contents] : $contents, - ]); - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } - /** * Müşteriden kredi kartı bilgilerini aldıktan sonra GET 7/24 MPI’a kart “Kredi Kartı Kayıt Durumu”nun * (Enrollment Status) sorulması, yani kart 3-D Secure programına dâhil mi yoksa değil mi sorgusu @@ -243,7 +220,11 @@ protected function send($contents, string $txType, string $paymentModel, string */ private function sendEnrollmentRequest(array $order, CreditCardInterface $creditCard, string $txType, string $paymentModel): array { - $requestData = $this->requestDataMapper->create3DEnrollmentCheckRequestData($this->account, $order, $creditCard); + $requestData = $this->requestDataMapper->create3DEnrollmentCheckRequestData( + $this->account, + $order, + $creditCard + ); $event = new RequestDataPreparedEvent( $requestData, @@ -265,6 +246,17 @@ private function sendEnrollmentRequest(array $order, CreditCardInterface $credit $requestData = $event->getRequestData(); } - return $this->send($requestData, $txType, PosInterface::MODEL_3D_SECURE, $this->get3DGatewayURL()); + /** @var array $result */ + $result = $this->clientStrategy->getClient( + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order + ); + + return $result; } } diff --git a/src/Gateways/PayForPos.php b/src/Gateways/PayForPos.php index 3f07483a..4d8a0aa8 100644 --- a/src/Gateways/PayForPos.php +++ b/src/Gateways/PayForPos.php @@ -70,23 +70,29 @@ public function getAccount(): AbstractPosAccount */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = PosInterface::MODEL_3D_SECURE; - if (!$this->is3DAuthSuccess($request->all())) { - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), null, $txType, $order); + if (!$this->is3DAuthSuccess($postParameters->all())) { + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), null, $txType, $order); return $this; } if ( !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } // valid ProcReturnCode is V033 in case of success 3D Authentication - $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $request->all()); + $requestData = $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + $order, + $txType, + $postParameters->all() + ); $event = new RequestDataPreparedEvent( $requestData, @@ -94,7 +100,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -108,15 +114,18 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), $bankResponse, $txType, $order); + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), $bankResponse, $txType, $order); return $this; } @@ -196,24 +205,4 @@ public function get3DFormData(array $order, string $paymentModel, string $txType $creditCard ); } - - - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - $response = $this->client->post($url, [ - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - ], - 'body' => $contents, - ]); - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } } diff --git a/src/Gateways/PosNet.php b/src/Gateways/PosNet.php index 8068e01b..1faaf955 100644 --- a/src/Gateways/PosNet.php +++ b/src/Gateways/PosNet.php @@ -6,7 +6,6 @@ namespace Mews\Pos\Gateways; -use InvalidArgumentException; use Mews\Pos\DataMapper\RequestDataMapper\PosNetRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; use Mews\Pos\DataMapper\ResponseDataMapper\PosNetResponseDataMapper; @@ -65,13 +64,14 @@ class PosNet extends AbstractGateway */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = PosInterface::MODEL_3D_SECURE; $this->logger->debug('getting merchant request data'); $requestData = $this->requestDataMapper->create3DResolveMerchantRequestData( $this->account, $order, - $request->all() + $postParameters->all() ); $event = new RequestDataPreparedEvent( @@ -80,7 +80,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -94,12 +94,15 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $userVerifyResponse = $this->send( - $contents, + /** @var array $userVerifyResponse */ + $userVerifyResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); if (!$this->is3DAuthSuccess($userVerifyResponse)) { @@ -116,7 +119,12 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C throw new HashMismatchException(); } - $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $request->all()); + $requestData = $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + $order, + $txType, + $postParameters->all() + ); $event = new RequestDataPreparedEvent( $requestData, @@ -124,7 +132,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -137,13 +145,15 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C ]); $requestData = $event->getRequestData(); } - - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send( - $contents, + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); $this->response = $this->responseDataMapper->map3DPaymentData($userVerifyResponse, $bankResponse, $txType, $order); @@ -222,36 +232,6 @@ public function orderHistory(array $order): PosInterface throw new UnsupportedTransactionTypeException(); } - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - - if (!\is_string($contents)) { - throw new InvalidArgumentException( - \sprintf( - 'Argument type must be XML string, %s provided.', - \gettype($contents) - ) - ); - } - - $response = $this->client->post($url, [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => \sprintf('xmldata=%s', $contents), - ]); - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } - /** * Get OOS transaction data * siparis bilgileri ve kart bilgilerinin şifrelendiği adımdır. @@ -298,13 +278,17 @@ private function getOosTransactionData(array $order, string $txType, string $pay $requestData = $event->getRequestData(); } - $xml = $this->serializer->encode($requestData, $txType); - - return $this->send( - $xml, + /** @var array $result */ + $result = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL() + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); + + return $result; } } diff --git a/src/Gateways/PosNetV1Pos.php b/src/Gateways/PosNetV1Pos.php index fae506dc..c060c0f5 100644 --- a/src/Gateways/PosNetV1Pos.php +++ b/src/Gateways/PosNetV1Pos.php @@ -6,7 +6,6 @@ namespace Mews\Pos\Gateways; -use InvalidArgumentException; use Mews\Pos\DataMapper\RequestDataMapper\PosNetV1PosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; use Mews\Pos\DataMapper\ResponseDataMapper\PosNetV1PosResponseDataMapper; @@ -20,7 +19,6 @@ use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\PosInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Serializer\Exception\NotEncodableValueException; class PosNetV1Pos extends AbstractGateway { @@ -62,43 +60,34 @@ public function getAccount(): AbstractPosAccount return $this->account; } - /** - * @inheritDoc - * - * @throws UnsupportedTransactionTypeException - * @throws \InvalidArgumentException when transaction type is not provided - */ - public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string - { - if (null !== $txType) { - return parent::getApiURL().'/'.$this->requestDataMapper->mapTxType($txType); - } - - throw new \InvalidArgumentException('Transaction type is required to generate API URL'); - } - /** * Kullanıcı doğrulama sonucunun sorgulanması ve verilerin doğruluğunun teyit edilmesi için kullanılır. * @inheritDoc */ public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { - $request = $request->request; + $postParameters = $request->request; + $paymentModel = self::MODEL_3D_SECURE; - if (!$this->is3DAuthSuccess($request->all())) { - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), null, $txType, $order); + if (!$this->is3DAuthSuccess($postParameters->all())) { + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), null, $txType, $order); return $this; } if ( !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } - $requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $request->all()); + $requestData = $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + $order, + $txType, + $postParameters->all() + ); $event = new RequestDataPreparedEvent( $requestData, @@ -106,7 +95,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -120,16 +109,19 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $provisionResponse = $this->send( - $contents, + /** @var array $provisionResponse */ + $provisionResponse = $this->clientStrategy->getClient( $txType, - PosInterface::MODEL_3D_SECURE, - $this->getApiURL($txType) + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order ); $this->logger->debug('send $provisionResponse', ['$provisionResponse' => $provisionResponse]); - $this->response = $this->responseDataMapper->map3DPaymentData($request->all(), $provisionResponse, $txType, $order); + $this->response = $this->responseDataMapper->map3DPaymentData($postParameters->all(), $provisionResponse, $txType, $order); $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); return $this; @@ -172,18 +164,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType ); } - /** - * @inheritDoc - */ - public function customQuery(array $requestData, ?string $apiUrl = null): PosInterface - { - if (null === $apiUrl) { - throw new InvalidArgumentException('API URL is required for custom query'); - } - - return parent::customQuery($requestData, $apiUrl); - } - /** * @inheritDoc */ @@ -199,42 +179,4 @@ public function orderHistory(array $order): PosInterface { throw new UnsupportedTransactionTypeException(); } - - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - - if (!\is_string($contents)) { - throw new InvalidArgumentException('Invalid data provided'); - } - - $body = $contents; - - $response = $this->client->post($url, [ - 'headers' => [ - 'Content-Type' => 'application/json', - ], - 'body' => $body, - ]); - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - try { - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } catch (NotEncodableValueException $notEncodableValueException) { - $response->getBody()->rewind(); - $this->logger->error('parsing bank JSON response failed', [ - 'status_code' => $response->getStatusCode(), - 'response' => $response->getBody()->getContents(), - 'message' => $notEncodableValueException->getMessage(), - ]); - - throw $notEncodableValueException; - } - } } diff --git a/src/Gateways/ToslaPos.php b/src/Gateways/ToslaPos.php index 819d6fd2..b08ad8e3 100644 --- a/src/Gateways/ToslaPos.php +++ b/src/Gateways/ToslaPos.php @@ -70,21 +70,6 @@ public function getAccount(): AbstractPosAccount return $this->account; } - /** - * @inheritDoc - * - * @throws UnsupportedTransactionTypeException - * @throws \InvalidArgumentException when transaction type or payment model are not provided - */ - public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string - { - if (null !== $txType && null !== $paymentModel) { - return parent::getApiURL().'/'.$this->getRequestURIByTransactionType($txType, $paymentModel); - } - - throw new \InvalidArgumentException('Transaction type and payment model are required to generate API URL'); - } - /** * @inheritDoc * @@ -112,17 +97,17 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C */ public function make3DPayPayment(Request $request, array $order, string $txType): PosInterface { - $request = $request->request; + $postParameters = $request->request; if ( - $this->is3DAuthSuccess($request->all()) + $this->is3DAuthSuccess($postParameters->all()) && !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } - $this->response = $this->responseDataMapper->map3DPayResponseData($request->all(), $txType, $order); + $this->response = $this->responseDataMapper->map3DPayResponseData($postParameters->all(), $txType, $order); $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); @@ -134,17 +119,17 @@ public function make3DPayPayment(Request $request, array $order, string $txType) */ public function make3DHostPayment(Request $request, array $order, string $txType): PosInterface { - $request = $request->request; + $postParameters = $request->request; if ( - $this->is3DAuthSuccess($request->all()) + $this->is3DAuthSuccess($postParameters->all()) && !$this->is3DHashCheckDisabled() - && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $request->all()) + && !$this->requestDataMapper->getCrypt()->check3DHash($this->account, $postParameters->all()) ) { throw new HashMismatchException(); } - $this->response = $this->responseDataMapper->map3DHostResponseData($request->all(), $txType, $order); + $this->response = $this->responseDataMapper->map3DHostResponseData($postParameters->all(), $txType, $order); $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); @@ -182,18 +167,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType ); } - /** - * @inheritDoc - */ - public function customQuery(array $requestData, ?string $apiUrl = null): PosInterface - { - if (null === $apiUrl) { - throw new \InvalidArgumentException('API URL is required for custom query'); - } - - return parent::customQuery($requestData, $apiUrl); - } - /** * @inheritDoc */ @@ -202,34 +175,6 @@ public function history(array $data): PosInterface throw new UnsupportedTransactionTypeException(); } - /** - * @inheritDoc - * - * @return array - */ - protected function send($contents, string $txType, string $paymentModel, string $url): array - { - $this->logger->debug('sending request', ['url' => $url]); - $response = $this->client->post($url, [ - 'headers' => [ - 'Content-Type' => 'application/json', - ], - 'body' => $contents, - ]); - - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - if ($response->getStatusCode() === 204) { - $this->logger->warning('response from api is empty'); - - return $this->data = []; - } - - $responseContent = $response->getBody()->getContents(); - - return $this->data = $this->serializer->decode($responseContent, $txType); - } - /** * Ödeme İşlem Başlatma * @@ -276,56 +221,17 @@ private function registerPayment(array $order, string $paymentModel, string $txT $requestData = $event->getRequestData(); } - $requestData = $this->serializer->encode($requestData, $txType); - - return $this->send( - $requestData, + /** @var array $result */ + $result = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( $txType, $paymentModel, - $this->getApiURL($txType, $paymentModel) + $requestData, + $order ); - } - - /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * @phpstan-param PosInterface::MODEL_* $paymentModel - * - * @return string - * - * @throws UnsupportedTransactionTypeException - */ - private function getRequestURIByTransactionType(string $txType, string $paymentModel): string - { - $arr = [ - PosInterface::TX_TYPE_PAY_AUTH => [ - PosInterface::MODEL_NON_SECURE => 'Payment', - PosInterface::MODEL_3D_PAY => 'threeDPayment', - PosInterface::MODEL_3D_HOST => 'threeDPayment', - ], - PosInterface::TX_TYPE_PAY_PRE_AUTH => [ - PosInterface::MODEL_3D_PAY => 'threeDPreAuth', - PosInterface::MODEL_3D_HOST => 'threeDPreAuth', - ], - PosInterface::TX_TYPE_PAY_POST_AUTH => 'postAuth', - PosInterface::TX_TYPE_CANCEL => 'void', - PosInterface::TX_TYPE_REFUND => 'refund', - PosInterface::TX_TYPE_REFUND_PARTIAL => 'refund', - PosInterface::TX_TYPE_STATUS => 'inquiry', - PosInterface::TX_TYPE_ORDER_HISTORY => 'history', - ]; - - if (!isset($arr[$txType])) { - throw new UnsupportedTransactionTypeException(); - } - - if (\is_string($arr[$txType])) { - return $arr[$txType]; - } - - if (!isset($arr[$txType][$paymentModel])) { - throw new UnsupportedTransactionTypeException(); - } - return $arr[$txType][$paymentModel]; + return $result; } } diff --git a/src/Gateways/VakifKatilimPos.php b/src/Gateways/VakifKatilimPos.php index b7fc7fd8..8f81f64b 100644 --- a/src/Gateways/VakifKatilimPos.php +++ b/src/Gateways/VakifKatilimPos.php @@ -17,7 +17,6 @@ use Mews\Pos\Exceptions\UnsupportedPaymentModelException; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\PosInterface; -use Psr\Http\Client\ClientExceptionInterface; use Symfony\Component\HttpFoundation\Request; /** @@ -64,21 +63,6 @@ public function getAccount(): AbstractPosAccount return $this->account; } - /** - * @inheritDoc - * - * @throws UnsupportedTransactionTypeException - * @throws \InvalidArgumentException when transaction type or payment model are not provided - */ - public function getApiURL(?string $txType = null, ?string $paymentModel = null, ?string $orderTxType = null): string - { - if (null !== $txType && null !== $paymentModel) { - return parent::getApiURL().'/'.$this->getRequestURIByTransactionType($txType, $paymentModel, $orderTxType); - } - - throw new \InvalidArgumentException('Transaction type and payment model are required to generate API URL'); - } - /** * @inheritDoc */ @@ -98,11 +82,11 @@ public function make3DHostPayment(Request $request, array $order, string $txType } /** + * 3D Host Model'de array döner, + * 3D Model'de ise HTML form içeren string döner. * @inheritDoc - * - * @return array{gateway: string, method: 'POST'|'GET', inputs: array} */ - public function get3DFormData(array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null, bool $createWithoutCard = true): array + public function get3DFormData(array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null, bool $createWithoutCard = true) { $this->check3DFormInputs($paymentModel, $txType, $creditCard, $createWithoutCard); @@ -118,21 +102,11 @@ public function get3DFormData(array $order, string $paymentModel, string $txType ); } - $response = $this->sendEnrollmentRequest( + return $this->sendEnrollmentRequest( $this->account, $order, $paymentModel, $txType, - $this->get3DGatewayURL($paymentModel), - $creditCard - ); - - return $this->requestDataMapper->create3DFormData( - $this->account, - $response['form_inputs'], - $paymentModel, - $txType, - $response['gateway'], $creditCard ); } @@ -143,6 +117,7 @@ public function get3DFormData(array $order, string $paymentModel, string $txType public function make3DPayment(Request $request, array $order, string $txType, ?CreditCardInterface $creditCard = null): PosInterface { $gatewayResponse = $request->request->all(); + $paymentModel = self::MODEL_3D_SECURE; if (!$this->is3DAuthSuccess($gatewayResponse)) { $this->response = $this->responseDataMapper->map3DPaymentData($gatewayResponse, null, $txType, $order); @@ -160,7 +135,7 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $txType, \get_class($this), $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); /** @var RequestDataPreparedEvent $event */ $event = $this->eventDispatcher->dispatch($event); @@ -174,8 +149,16 @@ public function make3DPayment(Request $request, array $order, string $txType, ?C $requestData = $event->getRequestData(); } - $contents = $this->serializer->encode($requestData, $txType); - $bankResponse = $this->send($contents, $txType, PosInterface::MODEL_3D_SECURE); + /** @var array $bankResponse */ + $bankResponse = $this->clientStrategy->getClient( + $txType, + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order + ); $this->response = $this->responseDataMapper->map3DPaymentData($gatewayResponse, $bankResponse, $txType, $order); $this->logger->debug('finished 3D payment', ['mapped_response' => $this->response]); @@ -196,30 +179,6 @@ public function customQuery(array $requestData, ?string $apiUrl = null): PosInte return parent::customQuery($requestData, $apiUrl); } - /** - * @inheritDoc - * - * @return array - * - * @throws UnsupportedTransactionTypeException - */ - protected function send($contents, string $txType, string $paymentModel, ?string $url = null): array - { - $url ??= $this->getApiURL($txType, $paymentModel); - - $this->logger->debug('sending request', ['url' => $url]); - $body = [ - 'body' => $contents, - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - ], - ]; - $response = $this->client->post($url, $body); - $this->logger->debug('request completed', ['status_code' => $response->getStatusCode()]); - - return $this->data = $this->serializer->decode($response->getBody()->getContents(), $txType); - } - /** * @phpstan-param PosInterface::MODEL_3D_* $paymentModel * @phpstan-param PosInterface::TX_TYPE_PAY_AUTH|PosInterface::TX_TYPE_PAY_PRE_AUTH $txType @@ -228,15 +187,13 @@ protected function send($contents, string $txType, string $paymentModel, ?string * @param array $order * @param string $paymentModel * @param string $txType - * @param non-empty-string $gatewayURL * @param CreditCardInterface|null $creditCard * - * @return array{gateway: string, form_inputs: array} + * @return non-empty-string HTML string containing form inputs to be submitted to the bank * * @throws UnsupportedTransactionTypeException - * @throws ClientExceptionInterface */ - private function sendEnrollmentRequest(KuveytPosAccount $kuveytPosAccount, array $order, string $paymentModel, string $txType, string $gatewayURL, ?CreditCardInterface $creditCard = null): array + private function sendEnrollmentRequest(KuveytPosAccount $kuveytPosAccount, array $order, string $paymentModel, string $txType, ?CreditCardInterface $creditCard = null): string { $requestData = $this->requestDataMapper->create3DEnrollmentCheckRequestData($kuveytPosAccount, $order, $paymentModel, $txType, $creditCard); @@ -260,81 +217,17 @@ private function sendEnrollmentRequest(KuveytPosAccount $kuveytPosAccount, array $requestData = $event->getRequestData(); } - $data = $this->serializer->encode($requestData, $txType); - - /** - * @var array{form_inputs: array, gateway: string} $decodedResponse - */ - $decodedResponse = $this->send($data, $txType, $paymentModel, $gatewayURL); - - return $decodedResponse; - } - - - /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * @phpstan-param PosInterface::MODEL_* $paymentModel - * @phpstan-param PosInterface::TX_TYPE_PAY_* $orderTxType - * - * @return string - * - * @throws UnsupportedTransactionTypeException - */ - private function getRequestURIByTransactionType(string $txType, string $paymentModel, ?string $orderTxType = null): string - { - $orderTxType ??= PosInterface::TX_TYPE_PAY_AUTH; - - $arr = [ - PosInterface::TX_TYPE_PAY_AUTH => [ - PosInterface::MODEL_NON_SECURE => 'Non3DPayGate', - PosInterface::MODEL_3D_SECURE => 'ThreeDModelProvisionGate', - ], - PosInterface::TX_TYPE_PAY_PRE_AUTH => [ - PosInterface::MODEL_NON_SECURE => 'PreAuthorizaten', - ], - PosInterface::TX_TYPE_PAY_POST_AUTH => 'PreAuthorizatenClose', - PosInterface::TX_TYPE_CANCEL => [ - PosInterface::MODEL_NON_SECURE => [ - PosInterface::TX_TYPE_PAY_AUTH => 'SaleReversal', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuthorizationReversal', - ], - ], - PosInterface::TX_TYPE_REFUND => [ - PosInterface::MODEL_NON_SECURE => [ - PosInterface::TX_TYPE_PAY_AUTH => 'DrawBack', - PosInterface::TX_TYPE_PAY_PRE_AUTH => 'PreAuthorizationDrawBack', - ], - ], - PosInterface::TX_TYPE_REFUND_PARTIAL => [ - PosInterface::MODEL_NON_SECURE => [ - PosInterface::TX_TYPE_PAY_AUTH => 'PartialDrawBack', - ], - ], - PosInterface::TX_TYPE_STATUS => 'SelectOrderByMerchantOrderId', - PosInterface::TX_TYPE_ORDER_HISTORY => 'SelectOrder', - PosInterface::TX_TYPE_HISTORY => 'SelectOrder', - ]; - - if (!isset($arr[$txType])) { - throw new UnsupportedTransactionTypeException(); - } - - if (\is_string($arr[$txType])) { - return $arr[$txType]; - } - - if (!isset($arr[$txType][$paymentModel])) { - throw new UnsupportedTransactionTypeException(); - } - - if (\is_string($arr[$txType][$paymentModel])) { - return $arr[$txType][$paymentModel]; - } - - if (!isset($arr[$txType][$paymentModel][$orderTxType])) { - throw new UnsupportedTransactionTypeException(); - } + /** @var non-empty-string $result */ + $result = $this->clientStrategy->getClient( + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, + $paymentModel, + )->request( + $txType, + $paymentModel, + $requestData, + $order + ); - return $arr[$txType][$paymentModel][$orderTxType]; + return $result; } } diff --git a/src/PosInterface.php b/src/PosInterface.php index 4f6acc27..78f3c3db 100644 --- a/src/PosInterface.php +++ b/src/PosInterface.php @@ -52,6 +52,9 @@ interface PosInterface /** @var string */ public const TX_TYPE_HISTORY = 'history'; + /** @var string */ + public const TX_TYPE_INTERNAL_3D_FORM_BUILD = '3d_form_build'; + /** @var string */ public const TX_TYPE_CUSTOM_QUERY = 'custom_query'; diff --git a/src/Serializer/AkbankPosSerializer.php b/src/Serializer/AkbankPosSerializer.php index 624e3b38..31efa535 100644 --- a/src/Serializer/AkbankPosSerializer.php +++ b/src/Serializer/AkbankPosSerializer.php @@ -6,6 +6,7 @@ namespace Mews\Pos\Serializer; +use Mews\Pos\Client\HttpClientInterface; use Mews\Pos\Gateways\AkbankPos; use Mews\Pos\PosInterface; use Symfony\Component\Serializer\Encoder\JsonEncoder; @@ -23,17 +24,26 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { + if (null !== $apiName && HttpClientInterface::API_NAME_PAYMENT_API !== $apiName) { + return false; + } + return AkbankPos::class === $gatewayClass; } /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return $this->serializer->encode($data, JsonEncoder::FORMAT); + $format = self::FORMAT_JSON; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/EncodedData.php b/src/Serializer/EncodedData.php new file mode 100644 index 00000000..a419923d --- /dev/null +++ b/src/Serializer/EncodedData.php @@ -0,0 +1,43 @@ +data = $data; + $this->format = $format; + } + + /** + * @return SerializerInterface::FORMAT_* + */ + public function getFormat(): string + { + return $this->format; + } + + public function getData(): string + { + return $this->data; + } +} diff --git a/src/Serializer/EstPosSerializer.php b/src/Serializer/EstPosSerializer.php index 45f71608..2a0442ed 100644 --- a/src/Serializer/EstPosSerializer.php +++ b/src/Serializer/EstPosSerializer.php @@ -28,7 +28,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return \in_array($gatewayClass, [EstPos::class, EstV3Pos::class]); } @@ -36,9 +36,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return $this->serializer->encode($data, XmlEncoder::FORMAT); + $format = self::FORMAT_XML; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/GarantiPosSerializer.php b/src/Serializer/GarantiPosSerializer.php index b3d47c86..0ed71133 100644 --- a/src/Serializer/GarantiPosSerializer.php +++ b/src/Serializer/GarantiPosSerializer.php @@ -27,7 +27,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return GarantiPos::class === $gatewayClass; } @@ -35,9 +35,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return $this->serializer->encode($data, XmlEncoder::FORMAT); + $format = self::FORMAT_XML; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/InterPosSerializer.php b/src/Serializer/InterPosSerializer.php index 708c7d7e..3933e1e4 100644 --- a/src/Serializer/InterPosSerializer.php +++ b/src/Serializer/InterPosSerializer.php @@ -14,19 +14,22 @@ class InterPosSerializer implements SerializerInterface /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return InterPos::class === $gatewayClass; } /** * @inheritDoc - * - * @return string */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return \http_build_query($data); + $format = self::FORMAT_FORM; + + return new EncodedData( + \http_build_query($data), + $format + ); } /** diff --git a/src/Serializer/KuveytPosSerializer.php b/src/Serializer/KuveytPosSerializer.php index 64736ee6..07c53cde 100644 --- a/src/Serializer/KuveytPosSerializer.php +++ b/src/Serializer/KuveytPosSerializer.php @@ -6,30 +6,15 @@ namespace Mews\Pos\Serializer; -use DOMAttr; -use DOMDocument; -use DOMElement; -use DOMNamedNodeMap; -use DOMNodeList; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Gateways\KuveytPos; -use Mews\Pos\PosInterface; +use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder; -use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\Serializer; class KuveytPosSerializer implements SerializerInterface { use SerializerUtilTrait; - /** @var string[] */ - private array $nonPaymentTransactions = [ - PosInterface::TX_TYPE_REFUND, - PosInterface::TX_TYPE_REFUND_PARTIAL, - PosInterface::TX_TYPE_STATUS, - PosInterface::TX_TYPE_CANCEL, - ]; - private Serializer $serializer; public function __construct() @@ -39,13 +24,13 @@ public function __construct() XmlEncoder::ENCODING => 'ISO-8859-1', ]); - $this->serializer = new Serializer([new XmlPrefixNormalizer()], [$encoder]); + $this->serializer = new Serializer([], [$encoder, new JsonEncoder()]); } /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return KuveytPos::class === $gatewayClass; } @@ -53,33 +38,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, string $txType) + public function encode(array $data, string $txType): EncodedData { - if (PosInterface::TX_TYPE_HISTORY === $txType || PosInterface::TX_TYPE_ORDER_HISTORY === $txType) { - throw new UnsupportedTransactionTypeException( - \sprintf('Serialization of the transaction %s is not supported', $txType) - ); - } - - if (!\in_array($txType, $this->nonPaymentTransactions, true)) { - return $this->serializer->encode($data, XmlEncoder::FORMAT); - } - - /** @var array $data */ - $data = $this->serializer->normalize($data, XmlEncoder::FORMAT, ['xml_prefix' => 'ser']); - - $context = [ - XmlEncoder::ROOT_NODE_NAME => 'soapenv:Envelope', - XmlEncoder::ENCODER_IGNORED_NODE_TYPES => [ - XML_PI_NODE, - ], - ]; + $format = self::FORMAT_XML; - $soapEnvelope['soapenv:Body'] = $data; - $soapEnvelope['@xmlns:soapenv'] = 'http://schemas.xmlsoap.org/soap/envelope/'; - $soapEnvelope['@xmlns:ser'] = 'http://boa.net/BOA.Integration.VirtualPos/Service'; - - return $this->serializer->serialize($soapEnvelope, XmlEncoder::FORMAT, $context); + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** @@ -87,114 +53,6 @@ public function encode(array $data, string $txType) */ public function decode(string $data, string $txType): array { - try { - $decodedData = $this->serializer->decode($data, XmlEncoder::FORMAT); - if (\in_array($txType, $this->nonPaymentTransactions, true)) { - // soap response - return $decodedData['s:Body']; - } - - return $decodedData; - } catch (NotEncodableValueException $notEncodableValueException) { - if ($this->isHTML($data)) { - // 3D form data icin enrollment istegi gonderiyoruz, o istegin cevabi icinde form olan HTML donuyor. - return $this->transformReceived3DFormData($data); - } - - throw new \RuntimeException($data, $notEncodableValueException->getCode(), $notEncodableValueException); - } - } - - /** - * Diger Gateway'lerden farkli olarak bu gateway HTML form olan bir response doner. - * Kutupahenin islem akisina uymasi icin bu HTML form verilerini array'e donusturup, kendimiz post ediyoruz. - * - * @param string $response - * - * @return array{gateway: string, form_inputs: array} - */ - private function transformReceived3DFormData(string $response): array - { - $dom = new DOMDocument(); - /** - * Kuveyt Pos started sending HTML with custom HTML tags such as . - * Without LIBXML_NOERROR flag loadHTML throws "Tag apm_do_not_touch invalid in Entity" exception - */ - $dom->loadHTML($response, LIBXML_NOERROR); - - $gatewayURL = ''; - /** @var DOMElement $formNode */ - $formNode = $dom->getElementsByTagName('form')->item(0); - /** @var DOMNamedNodeMap $attributes */ - $attributes = $formNode->attributes; - for ($i = 0; $i < $attributes->length; ++$i) { - /** @var DOMAttr $attribute */ - $attribute = $attributes->item($i); - if ('action' === $attribute->name) { - /** - * banka onayladiginda gatewayURL=bankanin gateway url - * onaylanmadiginda (hatali istek oldugunda) ise gatewayURL = istekte yer alan failURL - */ - $gatewayURL = $attribute->value; - break; - } - } - - $els = $dom->getElementsByTagName('input'); - $inputs = $this->builtInputsFromHTMLDoc($els); - - return [ - 'gateway' => $gatewayURL, - 'form_inputs' => $inputs, - ]; - } - - /** - * html form'da gelen input degeleri array'e donusturur - * - * @param DOMNodeList $domNodeList - * - * @return array - */ - private function builtInputsFromHTMLDoc(DOMNodeList $domNodeList): array - { - $inputs = []; - foreach ($domNodeList as $el) { - $key = null; - $value = null; - - /** @var DOMNamedNodeMap $attributes */ - $attributes = $el->attributes; - // for each input element select name and value attribute values - for ($i = 0; $i < $attributes->length; ++$i) { - /** @var DOMAttr $attribute */ - $attribute = $attributes->item($i); - if ('name' === $attribute->name) { - /** @var string|null $key */ - $key = $attribute->value; - } - - if ('value' === $attribute->name) { - /** @var string|null $value */ - $value = $attribute->value; - } - } - - if (!$key) { - continue; - } - - if (null === $value) { - continue; - } - - if (\in_array($key, ['submit', 'submitBtn'])) { - continue; - } - - $inputs[$key] = $value; - } - - return $inputs; + return $this->serializer->decode($data, XmlEncoder::FORMAT); } } diff --git a/src/Serializer/KuveytSoapApiPosSerializer.php b/src/Serializer/KuveytSoapApiPosSerializer.php new file mode 100644 index 00000000..581898fe --- /dev/null +++ b/src/Serializer/KuveytSoapApiPosSerializer.php @@ -0,0 +1,69 @@ + 'soapenv:Envelope', + XmlEncoder::ENCODER_IGNORED_NODE_TYPES => [ + XML_PI_NODE, + ], + ]); + + $this->serializer = new Serializer([new XmlPrefixNormalizer()], [$encoder, new JsonEncoder()]); + } + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass, ?string $apiName = null): bool + { + return KuveytSoapApiPos::class === $gatewayClass; + } + + /** + * @inheritDoc + */ + public function encode(array $data, string $txType): EncodedData + { + $format = self::FORMAT_XML; + + /** @var array $data */ + $data = $this->serializer->normalize($data, $format, ['xml_prefix' => 'ser']); + + $serializeData['soapenv:Body'] = $data; + $serializeData['@xmlns:soapenv'] = 'http://schemas.xmlsoap.org/soap/envelope/'; + $serializeData['@xmlns:ser'] = 'http://boa.net/BOA.Integration.VirtualPos/Service'; + + return new EncodedData( + $this->serializer->serialize($serializeData, $format), + $format + ); + } + + /** + * @inheritDoc + */ + public function decode(string $data, string $txType): array + { + $decodedData = $this->serializer->decode($data, XmlEncoder::FORMAT); + + return $decodedData['s:Body']; + } +} diff --git a/src/Serializer/ParamPosSerializer.php b/src/Serializer/ParamPosSerializer.php index 84beec5a..629629d4 100644 --- a/src/Serializer/ParamPosSerializer.php +++ b/src/Serializer/ParamPosSerializer.php @@ -6,6 +6,7 @@ namespace Mews\Pos\Serializer; +use Mews\Pos\Gateways\Param3DHostPos; use Mews\Pos\Gateways\ParamPos; use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Serializer; @@ -26,21 +27,27 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { - return $gatewayClass === ParamPos::class; + return $gatewayClass === ParamPos::class + || $gatewayClass === Param3DHostPos::class; } /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { $data['@xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance'; $data['@xmlns:xsd'] = 'http://www.w3.org/2001/XMLSchema'; $data['@xmlns:soap'] = 'http://schemas.xmlsoap.org/soap/envelope/'; - return $this->serializer->encode($data, XmlEncoder::FORMAT); + $format = self::FORMAT_XML; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/PayFlexCPV4PosSerializer.php b/src/Serializer/PayFlexCPV4PosSerializer.php index 1815629c..f7d81175 100644 --- a/src/Serializer/PayFlexCPV4PosSerializer.php +++ b/src/Serializer/PayFlexCPV4PosSerializer.php @@ -27,7 +27,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return PayFlexCPV4Pos::class === $gatewayClass; } @@ -35,9 +35,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, string $txType): string + public function encode(array $data, string $txType): EncodedData { - return \http_build_query($data); + $format = self::FORMAT_FORM; + + return new EncodedData( + \http_build_query($data), + $format + ); } /** diff --git a/src/Serializer/PayFlexV4PosSearchApiSerializer.php b/src/Serializer/PayFlexV4PosSearchApiSerializer.php new file mode 100644 index 00000000..6e7a01ea --- /dev/null +++ b/src/Serializer/PayFlexV4PosSearchApiSerializer.php @@ -0,0 +1,82 @@ + 'SearchRequest', + XmlEncoder::ENCODING => 'UTF-8', + XmlEncoder::ENCODER_IGNORED_NODE_TYPES => [], + ]); + + $this->serializer = new Serializer([], [$encoder]); + } + + /** + * @inheritDoc + */ + public static function supports(string $gatewayClass, ?string $apiName = null): bool + { + return PayFlexV4Pos::class === $gatewayClass && HttpClientInterface::API_NAME_QUERY_API === $apiName; + } + + /** + * @inheritDoc + */ + public function encode(array $data, string $txType): EncodedData + { + if (!in_array($txType, [ + PosInterface::TX_TYPE_STATUS, + PosInterface::TX_TYPE_HISTORY, + PosInterface::TX_TYPE_ORDER_HISTORY, + ], true)) { + throw new UnsupportedTransactionTypeException(sprintf( + 'Unsupported transaction type for %s', + self::class + )); + } + + $format = self::FORMAT_XML; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); + } + + /** + * @inheritDoc + */ + public function decode(string $data, ?string $txType = null): array + { + try { + return $this->serializer->decode($data, XmlEncoder::FORMAT); + } catch (NotEncodableValueException $notEncodableValueException) { + if ($this->isHTML($data)) { + // if something wrong server responds with HTML content + throw new \RuntimeException($data, $notEncodableValueException->getCode(), $notEncodableValueException); + } + + throw $notEncodableValueException; + } + } +} diff --git a/src/Serializer/PayFlexV4PosSerializer.php b/src/Serializer/PayFlexV4PosSerializer.php index 105abe9c..5d5da87d 100644 --- a/src/Serializer/PayFlexV4PosSerializer.php +++ b/src/Serializer/PayFlexV4PosSerializer.php @@ -6,6 +6,7 @@ namespace Mews\Pos\Serializer; +use Mews\Pos\Client\HttpClientInterface; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Gateways\PayFlexV4Pos; use Mews\Pos\PosInterface; @@ -35,31 +36,34 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { - return PayFlexV4Pos::class === $gatewayClass; + return PayFlexV4Pos::class === $gatewayClass + && HttpClientInterface::API_NAME_QUERY_API !== $apiName; } /** * @inheritDoc */ - public function encode(array $data, string $txType): string + public function encode(array $data, string $txType): EncodedData { - if (PosInterface::TX_TYPE_HISTORY === $txType || PosInterface::TX_TYPE_ORDER_HISTORY === $txType) { - throw new UnsupportedTransactionTypeException( - \sprintf('Serialization of the transaction %s is not supported', $txType) - ); + if (in_array($txType, [ + PosInterface::TX_TYPE_STATUS, + PosInterface::TX_TYPE_HISTORY, + PosInterface::TX_TYPE_ORDER_HISTORY, + ], true)) { + throw new UnsupportedTransactionTypeException(sprintf( + 'Unsupported transaction type for %s', + self::class + )); } - if (PosInterface::TX_TYPE_STATUS === $txType) { - return $this->serializer->encode($data, XmlEncoder::FORMAT, [ - XmlEncoder::ROOT_NODE_NAME => 'SearchRequest', - XmlEncoder::ENCODING => 'UTF-8', - XmlEncoder::ENCODER_IGNORED_NODE_TYPES => [], - ]); - } + $format = self::FORMAT_XML; - return $this->serializer->encode($data, XmlEncoder::FORMAT); + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/PayForPosSerializer.php b/src/Serializer/PayForPosSerializer.php index 54d08f10..6677345d 100644 --- a/src/Serializer/PayForPosSerializer.php +++ b/src/Serializer/PayForPosSerializer.php @@ -28,7 +28,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return PayForPos::class === $gatewayClass; } @@ -36,9 +36,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return $this->serializer->encode($data, XmlEncoder::FORMAT); + $format = self::FORMAT_XML; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/PosNetSerializer.php b/src/Serializer/PosNetSerializer.php index b55e1672..e4548552 100644 --- a/src/Serializer/PosNetSerializer.php +++ b/src/Serializer/PosNetSerializer.php @@ -27,7 +27,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return PosNet::class === $gatewayClass; } @@ -35,9 +35,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return $this->serializer->encode($data, XmlEncoder::FORMAT); + $format = self::FORMAT_XML; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/PosNetV1PosSerializer.php b/src/Serializer/PosNetV1PosSerializer.php index 3ceca09e..d26f3f5a 100644 --- a/src/Serializer/PosNetV1PosSerializer.php +++ b/src/Serializer/PosNetV1PosSerializer.php @@ -22,7 +22,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return PosNetV1Pos::class === $gatewayClass; } @@ -30,9 +30,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return $this->serializer->encode($data, JsonEncoder::FORMAT); + $format = self::FORMAT_JSON; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format, + ); } /** diff --git a/src/Serializer/SerializerInterface.php b/src/Serializer/SerializerInterface.php index 77c647ba..907c2b94 100644 --- a/src/Serializer/SerializerInterface.php +++ b/src/Serializer/SerializerInterface.php @@ -8,27 +8,34 @@ use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\PosInterface; +use Symfony\Component\Serializer\Encoder\JsonEncoder; +use Symfony\Component\Serializer\Encoder\XmlEncoder; interface SerializerInterface { + public const FORMAT_XML = XmlEncoder::FORMAT; + + public const FORMAT_JSON = JsonEncoder::FORMAT; + + public const FORMAT_FORM = 'form'; + /** * @param class-string $gatewayClass + * @param string|null $apiName todo strict type * * @return bool */ - public static function supports(string $gatewayClass): bool; + public static function supports(string $gatewayClass, ?string $apiName = null): bool; /** - * @phpstan-param PosInterface::TX_TYPE_* $txType - * - * @param array $data - * @param string $txType + * @param array $data + * @param PosInterface::TX_TYPE_* $txType * - * @return string|array returns XML/JSON string or $data itself when encoding is not needed + * @return EncodedData * * @throws UnsupportedTransactionTypeException */ - public function encode(array $data, string $txType); + public function encode(array $data, string $txType): EncodedData; /** * @phpstan-param PosInterface::TX_TYPE_* $txType diff --git a/src/Serializer/ToslaPosSerializer.php b/src/Serializer/ToslaPosSerializer.php index 14cdb9bd..1de62960 100644 --- a/src/Serializer/ToslaPosSerializer.php +++ b/src/Serializer/ToslaPosSerializer.php @@ -22,7 +22,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return ToslaPos::class === $gatewayClass; } @@ -30,9 +30,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, ?string $txType = null): string + public function encode(array $data, ?string $txType = null): EncodedData { - return $this->serializer->encode($data, JsonEncoder::FORMAT); + $format = self::FORMAT_JSON; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** diff --git a/src/Serializer/VakifKatilimPosSerializer.php b/src/Serializer/VakifKatilimPosSerializer.php index e2800e4f..c423bdf2 100644 --- a/src/Serializer/VakifKatilimPosSerializer.php +++ b/src/Serializer/VakifKatilimPosSerializer.php @@ -6,15 +6,9 @@ namespace Mews\Pos\Serializer; -use DOMAttr; -use DOMDocument; -use DOMElement; -use DOMNamedNodeMap; -use DOMNodeList; use Mews\Pos\Gateways\VakifKatilimPos; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder; -use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\Serializer; class VakifKatilimPosSerializer implements SerializerInterface @@ -36,7 +30,7 @@ public function __construct() /** * @inheritDoc */ - public static function supports(string $gatewayClass): bool + public static function supports(string $gatewayClass, ?string $apiName = null): bool { return VakifKatilimPos::class === $gatewayClass; } @@ -44,9 +38,14 @@ public static function supports(string $gatewayClass): bool /** * @inheritDoc */ - public function encode(array $data, string $txType): string + public function encode(array $data, string $txType): EncodedData { - return $this->serializer->encode($data, XmlEncoder::FORMAT); + $format = self::FORMAT_XML; + + return new EncodedData( + $this->serializer->encode($data, $format), + $format + ); } /** @@ -54,111 +53,10 @@ public function encode(array $data, string $txType): string */ public function decode(string $data, string $txType): array { - try { - $data = \str_replace("�", '', $data); - $data = \str_replace(' encoding="utf-16"', '', $data); - - return $this->serializer->decode($data, XmlEncoder::FORMAT); - } catch (NotEncodableValueException $notEncodableValueException) { - if ($this->isHTML($data)) { - // 3D form data icin enrollment istegi gonderiyoruz, o istegin cevabi icinde form olan HTML donuyor. - return $this->transformReceived3DFormData($data); - } - - throw new \RuntimeException($data, $notEncodableValueException->getCode(), $notEncodableValueException); - } - } - - /** - * Diger Gateway'lerden farkli olarak bu gateway HTML form olan bir response doner. - * Kutupahenin islem akisina uymasi icin bu HTML form verilerini array'e donusturup, kendimiz post ediyoruz. - * - * @param string $response - * - * @return array{gateway: string, form_inputs: array} - */ - private function transformReceived3DFormData(string $response): array - { - $dom = new DOMDocument(); - /** - * Kuveyt Pos started sending HTML with custom HTML tags such as . - * Without LIBXML_NOERROR flag loadHTML throws "Tag apm_do_not_touch invalid in Entity" exception - */ - $dom->loadHTML($response, LIBXML_NOERROR); - - $gatewayURL = ''; - /** @var DOMElement|null $formNode */ - $formNode = $dom->getElementsByTagName('form')->item(0); - if (null === $formNode) { - throw new \RuntimeException($response, 974); - } - - /** @var DOMNamedNodeMap $attributes */ - $attributes = $formNode->attributes; - for ($i = 0; $i < $attributes->length; ++$i) { - /** @var DOMAttr $attribute */ - $attribute = $attributes->item($i); - if ('action' === $attribute->name) { - /** - * banka onayladiginda gatewayURL=bankanin gateway url - * onaylanmadiginda (hatali istek oldugunda) ise gatewayURL = istekte yer alan failURL - */ - $gatewayURL = $attribute->value; - break; - } - } - - $els = $dom->getElementsByTagName('input'); - $inputs = $this->builtInputsFromHTMLDoc($els); - - return [ - 'gateway' => $gatewayURL, - 'form_inputs' => $inputs, - ]; - } - - /** - * html form'da gelen input degeleri array'e donusturur - * - * @param DOMNodeList $domNodeList - * - * @return array - */ - private function builtInputsFromHTMLDoc(DOMNodeList $domNodeList): array - { - $inputs = []; - foreach ($domNodeList as $el) { - $key = null; - $value = ''; - - /** @var DOMNamedNodeMap $attributes */ - $attributes = $el->attributes; - // for each input element select name and value attribute values - for ($i = 0; $i < $attributes->length; ++$i) { - /** @var DOMAttr $attribute */ - $attribute = $attributes->item($i); - if ('name' === $attribute->name) { - /** @var string|null $key */ - $key = $attribute->value; - } - - if ('value' === $attribute->name) { - /** @var string|null $value */ - $value = $attribute->value; - } - } - - if (!$key) { - continue; - } - - if (\in_array($key, ['submit', 'submitBtn'])) { - continue; - } - - $inputs[$key] = $value; - } + // this is a workaround for the Vakif Katilim POS XML responses, which is mentioned in their documentation. + $data = \str_replace("�", '', $data); + $data = \str_replace(' encoding="utf-16"', '', $data); - return $inputs; + return $this->serializer->decode($data, XmlEncoder::FORMAT); } } diff --git a/tests/Functional/AkbankPosTest.php b/tests/Functional/AkbankPosTest.php index 8e9f9c14..458836be 100644 --- a/tests/Functional/AkbankPosTest.php +++ b/tests/Functional/AkbankPosTest.php @@ -293,7 +293,7 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro $response = $this->recurringPos->getResponse(); - $this->assertTrue($this->recurringPos->isSuccess()); + $this->assertTrue($this->recurringPos->isSuccess(), $response['error_message'] ?? ''); $this->assertIsArray($response); $this->assertNotEmpty($response); diff --git a/tests/Functional/KuveytPosTest.php b/tests/Functional/KuveytPosTest.php index 079101d0..5da0e83c 100644 --- a/tests/Functional/KuveytPosTest.php +++ b/tests/Functional/KuveytPosTest.php @@ -4,6 +4,8 @@ * @license MIT */ +namespace Mews\Pos\Tests\Functional; + use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\RequestDataPreparedEvent; use Mews\Pos\Factory\CreditCardFactory; @@ -26,6 +28,9 @@ class KuveytPosTest extends TestCase /** @var \Mews\Pos\Gateways\KuveytPos */ private PosInterface $pos; + /** @var \Mews\Pos\Gateways\KuveytSoapApiPos */ + private PosInterface $soapApiPos; + protected function setUp(): void { parent::setUp(); @@ -40,10 +45,23 @@ protected function setUp(): void 'api123', PosInterface::MODEL_3D_SECURE ); + $soapApiAccount = \Mews\Pos\Factory\AccountFactory::createKuveytPosAccount( + 'kuveytsoappos', + '496', + 'apitest', + '400235', + 'api123', + PosInterface::MODEL_3D_SECURE + ); $this->eventDispatcher = new EventDispatcher(); - $this->pos = PosFactory::createPosGateway($account, $config, $this->eventDispatcher); + $this->pos = PosFactory::createPosGateway($account, $config, $this->eventDispatcher); + $this->soapApiPos = PosFactory::createPosGateway( + $soapApiAccount, + $config, + $this->eventDispatcher + ); $this->card = CreditCardFactory::createForGateway( $this->pos, @@ -135,7 +153,7 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro $this->card, ); - $this->assertIsArray($formData); + $this->assertIsString($formData); $this->assertNotEmpty($formData); $this->assertTrue($eventIsThrown); } @@ -176,7 +194,7 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro */ public function testCancelSuccess(array $lastResponse): array { - $statusOrder = $this->createCancelOrder(\get_class($this->pos), $lastResponse); + $statusOrder = $this->createCancelOrder(\get_class($this->soapApiPos), $lastResponse); $eventIsThrown = false; $this->eventDispatcher->addListener( @@ -188,10 +206,10 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro } ); - $this->pos->cancel($statusOrder); + $this->soapApiPos->cancel($statusOrder); - $this->assertTrue($this->pos->isSuccess()); - $response = $this->pos->getResponse(); + $this->assertTrue($this->soapApiPos->isSuccess()); + $response = $this->soapApiPos->getResponse(); $this->assertIsArray($response); $this->assertNotEmpty($response); $this->assertTrue($eventIsThrown); @@ -204,7 +222,7 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro */ public function testStatusSuccess(array $lastResponse): array { - $statusOrder = $this->createStatusOrder(\get_class($this->pos), $lastResponse); + $statusOrder = $this->createStatusOrder(\get_class($this->soapApiPos), $lastResponse); $eventIsThrown = false; $this->eventDispatcher->addListener( @@ -216,10 +234,10 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro } ); - $this->pos->status($statusOrder); + $this->soapApiPos->status($statusOrder); - $this->assertTrue($this->pos->isSuccess()); - $response = $this->pos->getResponse(); + $this->assertTrue($this->soapApiPos->isSuccess()); + $response = $this->soapApiPos->getResponse(); $this->assertIsArray($response); $this->assertNotEmpty($response); $this->assertTrue($eventIsThrown); @@ -248,7 +266,7 @@ public function testNonSecurePaymentSuccessForRefundTest(): array */ public function testFullRefundFail(array $lastResponse): array { - $refundOrder = $this->createRefundOrder(\get_class($this->pos), $lastResponse); + $refundOrder = $this->createRefundOrder(\get_class($this->soapApiPos), $lastResponse); $eventIsThrown = false; $this->eventDispatcher->addListener( @@ -260,10 +278,10 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro } ); - $this->pos->refund($refundOrder); - $response = $this->pos->getResponse(); + $this->soapApiPos->refund($refundOrder); + $response = $this->soapApiPos->getResponse(); - $this->assertFalse($this->pos->isSuccess()); + $this->assertFalse($this->soapApiPos->isSuccess()); $this->assertIsArray($response); $this->assertNotEmpty($response); $this->assertTrue($eventIsThrown); @@ -281,7 +299,7 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro public function testPartialRefundSuccess(array $lastResponse): array { $refundOrder = $this->createRefundOrder( - \get_class($this->pos), + \get_class($this->soapApiPos), $lastResponse, $lastResponse['amount'] - 3, ); @@ -296,10 +314,10 @@ function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThro } ); - $this->pos->refund($refundOrder); - $response = $this->pos->getResponse(); + $this->soapApiPos->refund($refundOrder); + $response = $this->soapApiPos->getResponse(); - $this->assertTrue($this->pos->isSuccess(), $response['error_message'] ?? 'error'); + $this->assertTrue($this->soapApiPos->isSuccess(), $response['error_message'] ?? 'error'); $this->assertIsArray($response); $this->assertNotEmpty($response); $this->assertTrue($eventIsThrown); diff --git a/tests/Functional/Param3dHostPosTest.php b/tests/Functional/Param3dHostPosTest.php new file mode 100644 index 00000000..858062b8 --- /dev/null +++ b/tests/Functional/Param3dHostPosTest.php @@ -0,0 +1,485 @@ +eventDispatcher = new EventDispatcher(); + + $this->pos = PosFactory::createPosGateway($account, $config, $this->eventDispatcher); + + $this->card = CreditCardFactory::createForGateway( + $this->pos, + '5456165456165454', + '26', + '12', + '000', + 'John Doe' + ); + } + + public function testNonSecurePaymentSuccess(): array + { + $card = CreditCardFactory::createForGateway( + $this->pos, + '5818775818772285', + '26', + '12', + '001', + 'John Doe' + ); + $order = $this->createPaymentOrder(PosInterface::MODEL_NON_SECURE); + + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_PAY_AUTH, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->payment( + PosInterface::MODEL_NON_SECURE, + $order, + PosInterface::TX_TYPE_PAY_AUTH, + $card + ); + + $response = $this->pos->getResponse(); + + $this->assertTrue($this->pos->isSuccess(), $response['error_message'] ?? 'hata'); + + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertTrue($eventIsThrown); + + return $this->pos->getResponse(); + } + + public function testNonSecureForeignCurrencyPaymentSuccess(): array + { + $order = $this->createPaymentOrder(PosInterface::MODEL_NON_SECURE); + $order['currency'] = PosInterface::CURRENCY_USD; + + $card = CreditCardFactory::createForGateway( + $this->pos, + '4546711234567894', + '26', + '12', + '000', + 'John Doe' + ); + + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_PAY_AUTH, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->payment( + PosInterface::MODEL_NON_SECURE, + $order, + PosInterface::TX_TYPE_PAY_AUTH, + $card + ); + + $response = $this->pos->getResponse(); + + $this->assertTrue($this->pos->isSuccess(), $response['error_message'] ?? 'hata'); + + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertTrue($eventIsThrown); + + return $this->pos->getResponse(); + } + + public function testNonSecurePaymentWithInstallment(): array + { + $order = $this->createPaymentOrder(PosInterface::MODEL_NON_SECURE); + $order['installment'] = 2; + + $this->pos->payment( + PosInterface::MODEL_NON_SECURE, + $order, + PosInterface::TX_TYPE_PAY_AUTH, + $this->card + ); + + $response = $this->pos->getResponse(); + + $this->assertTrue($this->pos->isSuccess(), $response['error_message'] ?? 'hata'); + + $this->assertIsArray($response); + $this->assertNotEmpty($response); + + return $this->pos->getResponse(); + } + + public function testNonSecurePrePaymentSuccess(): array + { + $order = $this->createPaymentOrder(PosInterface::MODEL_NON_SECURE); + + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_PAY_PRE_AUTH, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->payment( + PosInterface::MODEL_NON_SECURE, + $order, + PosInterface::TX_TYPE_PAY_PRE_AUTH, + $this->card + ); + + $response = $this->pos->getResponse(); + + $this->assertTrue($this->pos->isSuccess(), $response['error_message'] ?? 'hata'); + + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertTrue($eventIsThrown); + + return $this->pos->getResponse(); + } + + /** + * @depends testNonSecurePrePaymentSuccess + */ + public function testNonSecurePostPaymentSuccess(array $lastResponse): array + { + $order = $this->createPostPayOrder(\get_class($this->pos), $lastResponse); + + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_PAY_POST_AUTH, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->payment( + PosInterface::MODEL_NON_SECURE, + $order, + PosInterface::TX_TYPE_PAY_POST_AUTH, + $this->card + ); + + $response = $this->pos->getResponse(); + + $this->assertTrue($this->pos->isSuccess(), $response['error_message'] ?? 'hata'); + + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertTrue($eventIsThrown); + + return $this->pos->getResponse(); + } + + /** + * @depends testNonSecurePaymentSuccess + */ + public function testStatusSuccess(array $lastResponse): array + { + $statusOrder = $this->createStatusOrder(\get_class($this->pos), $lastResponse); + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_STATUS, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->status($statusOrder); + + $this->assertTrue($this->pos->isSuccess()); + $response = $this->pos->getResponse(); + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertTrue($eventIsThrown); + + return $lastResponse; + } + + /** + * @depends testNonSecurePaymentSuccess + * @depends testStatusSuccess + */ + public function testCancelSuccess(array $lastResponse): array + { + $cancelOrder = $this->createCancelOrder(\get_class($this->pos), $lastResponse); + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_CANCEL, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->cancel($cancelOrder); + + $this->assertTrue($this->pos->isSuccess()); + $response = $this->pos->getResponse(); + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertTrue($eventIsThrown); + + return $lastResponse; + } + + public function testCancelPrePay(): void + { + $order = $this->createPaymentOrder(PosInterface::MODEL_NON_SECURE); + + $this->pos->payment( + PosInterface::MODEL_NON_SECURE, + $order, + PosInterface::TX_TYPE_PAY_PRE_AUTH, + $this->card + ); + + $lastResponse = $this->pos->getResponse(); + + $this->assertTrue($this->pos->isSuccess(), $response['error_message'] ?? 'hata'); + + $cancelOrder = $this->createCancelOrder(\get_class($this->pos), $lastResponse); + + $this->pos->cancel($cancelOrder); + + $this->assertTrue($this->pos->isSuccess()); + } + + public function testGet3DFormData(): void + { + $order = $this->createPaymentOrder(PosInterface::MODEL_3D_SECURE); + $card = CreditCardFactory::createForGateway( + $this->pos, + '5818775818772285', + '26', + '12', + '001', + 'John Doe' + ); + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + $this->assertSame(PosInterface::TX_TYPE_PAY_AUTH, $requestDataPreparedEvent->getTxType()); + } + ); + $formData = $this->pos->get3DFormData( + $order, + PosInterface::MODEL_3D_SECURE, + PosInterface::TX_TYPE_PAY_AUTH, + $card + ); + + $this->assertIsString($formData); + $this->assertTrue($eventIsThrown); + } + + public function testGet3DFormDataForeignCurrency(): void + { + $order = $this->createPaymentOrder(PosInterface::MODEL_3D_SECURE); + $order['currency'] = PosInterface::CURRENCY_USD; + $card = CreditCardFactory::createForGateway( + $this->pos, + '4546711234567894', + '26', + '12', + '000', + 'John Doe' + ); + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + $this->assertSame(PosInterface::TX_TYPE_PAY_AUTH, $requestDataPreparedEvent->getTxType()); + } + ); + $formData = $this->pos->get3DFormData( + $order, + PosInterface::MODEL_3D_SECURE, + PosInterface::TX_TYPE_PAY_AUTH, + $card + ); + + $this->assertIsArray($formData); + $this->assertNotEmpty($formData['gateway']); + $this->assertTrue($eventIsThrown); + } + + public function testGet3DHostFormData(): void + { + $order = $this->createPaymentOrder(PosInterface::MODEL_3D_HOST); + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Header']); + $this->assertSame(PosInterface::TX_TYPE_PAY_AUTH, $requestDataPreparedEvent->getTxType()); + } + ); + $formData = $this->pos->get3DFormData( + $order, + PosInterface::MODEL_3D_HOST, + PosInterface::TX_TYPE_PAY_AUTH + ); + + $this->assertIsArray($formData); + $this->assertArrayHasKey('inputs', $formData); + $this->assertNotEmpty($formData['inputs']); + $this->assertTrue($eventIsThrown); + } + + public function testRefund(): array + { + $order = $this->createPaymentOrder(PosInterface::MODEL_NON_SECURE); + + $this->pos->payment( + PosInterface::MODEL_NON_SECURE, + $order, + PosInterface::TX_TYPE_PAY_AUTH, + $this->card + ); + + $this->assertTrue($this->pos->isSuccess()); + + $lastResponse = $this->pos->getResponse(); + $this->assertTrue($this->pos->isSuccess(), $lastResponse['error_message'] ?? 'hata'); + + $refundOrder = $this->createRefundOrder(\get_class($this->pos), $lastResponse); + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_REFUND, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->refund($refundOrder); + $response = $this->pos->getResponse(); + // fails with error: Failed, Bu işlem geri alınamaz, lüften asıl işlemi iptal edin. + $this->assertFalse($this->pos->isSuccess(), $response['error_message'] ?? 'hata'); + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertTrue($eventIsThrown); + + return $lastResponse; + } + + public function testCustomQuery(): void + { + $customQuery = [ + 'TP_Ozel_Oran_Liste' => [ + '@xmlns' => 'https://turkpos.com.tr/', + ], + ]; + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_CUSTOM_QUERY, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->customQuery($customQuery); + + $response = $this->pos->getResponse(); + $this->assertIsArray($response); + $this->assertNotEmpty($response); + $this->assertArrayHasKey('TP_Ozel_Oran_ListeResponse', $response); + $this->assertArrayHasKey('TP_Ozel_Oran_ListeResult', $response['TP_Ozel_Oran_ListeResponse']); + $this->assertArrayHasKey('DT_Bilgi', $response['TP_Ozel_Oran_ListeResponse']['TP_Ozel_Oran_ListeResult']); + $this->assertTrue($eventIsThrown); + } + + public function testHistorySuccess(): void + { + $historyOrder = $this->createHistoryOrder(\get_class($this->pos), [], '127.0.0.1'); + + $eventIsThrown = false; + $this->eventDispatcher->addListener( + RequestDataPreparedEvent::class, + function (RequestDataPreparedEvent $requestDataPreparedEvent) use (&$eventIsThrown): void { + $eventIsThrown = true; + $this->assertSame(PosInterface::TX_TYPE_HISTORY, $requestDataPreparedEvent->getTxType()); + $this->assertCount(1, $requestDataPreparedEvent->getRequestData()['soap:Body']); + } + ); + + $this->pos->history($historyOrder); + + $response = $this->pos->getResponse(); + $this->assertIsArray($response); + $this->assertTrue($eventIsThrown); + $this->assertNotEmpty($response['transactions']); + } +} diff --git a/tests/Functional/PaymentTestTrait.php b/tests/Functional/PaymentTestTrait.php index 0d817e70..d02bec59 100644 --- a/tests/Functional/PaymentTestTrait.php +++ b/tests/Functional/PaymentTestTrait.php @@ -107,7 +107,7 @@ private function createStatusOrder(string $gatewayClass, array $lastResponse): a 'currency' => $lastResponse['currency'], 'ip' => '127.0.0.1', ]; - if (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + if (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $statusOrder['remote_order_id'] = $lastResponse['remote_order_id']; // OrderId } @@ -162,7 +162,7 @@ public function createCancelOrder(string $gatewayClass, array $lastResponse): ar $cancelOrder['amount'] = $lastResponse['amount']; // on otorizasyon islemin iptali icin PosInterface::TX_TYPE_PAY_PRE_AUTH saglanmasi gerekiyor $cancelOrder['transaction_type'] = $lastResponse['transaction_type'] ?? PosInterface::TX_TYPE_PAY_AUTH; - } elseif (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + } elseif (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $cancelOrder['remote_order_id'] = $lastResponse['remote_order_id']; // banka tarafındaki order id $cancelOrder['auth_code'] = $lastResponse['auth_code']; $cancelOrder['transaction_id'] = $lastResponse['transaction_id']; @@ -328,7 +328,7 @@ private function createRefundOrder(string $gatewayClass, array $lastResponse, ?f 'ip' => '127.0.0.1', ]; - if (\Mews\Pos\Gateways\KuveytPos::class === $gatewayClass) { + if (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { $refundOrder['remote_order_id'] = $lastResponse['remote_order_id']; // banka tarafındaki order id $refundOrder['auth_code'] = $lastResponse['auth_code']; $refundOrder['transaction_id'] = $lastResponse['transaction_id']; diff --git a/tests/Unit/Client/AkbankPosHttpClientTest.php b/tests/Unit/Client/AkbankPosHttpClientTest.php new file mode 100644 index 00000000..19d874c5 --- /dev/null +++ b/tests/Unit/Client/AkbankPosHttpClientTest.php @@ -0,0 +1,409 @@ +account = $this->createMock(AbstractPosAccount::class); + $this->serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + AkbankPosHttpClient::class, + 'https://apipre.akbank.com/api/v1/payment/virtualpos', + $this->serializer, + $this->crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertTrue($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_QUERY_API)); + $this->assertFalse($this->client::supports(EstV3Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider getApiUrlExceptionDataProvider + */ + public function testGetApiUrlException(?string $txType, string $exceptionClass): void + { + $this->expectException($exceptionClass); + $this->client->getApiURL($txType); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $responseContent = 'response-content'; + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + [ + 'name' => 'auth-hash', + 'value' => 'hash123', + ], + ]); + + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->account->expects($this->once()) + ->method('getStoreKey') + ->willReturn('store-key123'); + + $this->crypt->expects($this->once()) + ->method('hashString') + ->with($encodedData->getData(), 'store-key123') + ->willReturn('hash123'); + + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl, + $this->account, + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data']; + $order = ['id' => 123]; + $expectedApiUrl = 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process'; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $responseContent = 'response-content'; + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + [ + 'name' => 'auth-hash', + 'value' => 'hash123', + ], + ]); + + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->account->expects($this->once()) + ->method('getStoreKey') + ->willReturn('store-key123'); + + $this->crypt->expects($this->once()) + ->method('hashString') + ->with($encodedData->getData(), 'store-key123') + ->willReturn('hash123'); + + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = [ + 'message' => 'Error message', + 'code' => 222, + ]; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Error message'); + $this->expectExceptionCode(222); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl, + $this->account, + ); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $responseContent = 'response-content'; + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + [ + 'name' => 'auth-hash', + 'value' => 'hash123', + ], + ]); + + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->account->expects($this->once()) + ->method('getStoreKey') + ->willReturn('store-key123'); + + $this->crypt->expects($this->once()) + ->method('hashString') + ->willReturn('hash123'); + + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + null, + $this->account, + ); + } + + public function testRequestWithoutAccount(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data']; + $order = ['id' => 123]; + $expectedApiUrl = 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process'; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->psrClient->expects($this->never()) + ->method('sendRequest'); + + $this->expectException(InvalidArgumentException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl, + ); + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', + ]; + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', + ], + [ + 'txType' => PosInterface::TX_TYPE_HISTORY, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/portal/report/transaction', + ], + ]; + } + + public static function getApiUrlExceptionDataProvider(): array + { + return [ + [ + 'txType' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + ]; + } +} diff --git a/tests/Unit/Client/EstPosHttpClientTest.php b/tests/Unit/Client/EstPosHttpClientTest.php new file mode 100644 index 00000000..07075405 --- /dev/null +++ b/tests/Unit/Client/EstPosHttpClientTest.php @@ -0,0 +1,283 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + EstPosHttpClient::class, + 'https://entegrasyon.asseco-see.com.tr/fim/api', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + public function testSupports(): void + { + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertTrue($this->client::supports(EstPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertTrue($this->client::supports(EstV3Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + + $responseContent = 'response-content'; + $request = $this->prepareHttpRequest($encodedData->getData(), []); + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + + $request = $this->prepareHttpRequest($encodedData->getData(), []); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), []); + + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + ], + [ + 'txType' => PosInterface::TX_TYPE_HISTORY, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + ]; + } +} diff --git a/tests/Unit/Client/GarantiPosHttpClientTest.php b/tests/Unit/Client/GarantiPosHttpClientTest.php new file mode 100644 index 00000000..9e3e96e5 --- /dev/null +++ b/tests/Unit/Client/GarantiPosHttpClientTest.php @@ -0,0 +1,279 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + GarantiPosHttpClient::class, + 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertTrue($this->client::supports(GarantiPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), []); + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), []); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), []); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ], + [ + 'txType' => PosInterface::TX_TYPE_HISTORY, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ]; + } +} diff --git a/tests/Unit/Client/GenericPosHttpClientStrategyTest.php b/tests/Unit/Client/GenericPosHttpClientStrategyTest.php new file mode 100644 index 00000000..0db9b054 --- /dev/null +++ b/tests/Unit/Client/GenericPosHttpClientStrategyTest.php @@ -0,0 +1,45 @@ +createMock(HttpClientInterface::class); + $client1->method('supportsTx')->willReturn(false); + + $client2 = $this->createMock(HttpClientInterface::class); + $client2->method('supportsTx')->with('pay_auth', 'non_secure')->willReturn(true); + + $strategy = new GenericPosHttpClientStrategy([ + 'payment_api' => $client1, + 'query_api' => $client2, + ]); + + $this->assertSame($client2, $strategy->getClient('pay_auth', 'non_secure')); + } + + public function testGetClientThrowsExceptionIfNotFound(): void + { + $client1 = $this->createMock(HttpClientInterface::class); + $client1->method('supportsTx')->willReturn(false); + + $strategy = new GenericPosHttpClientStrategy([ + 'payment_api' => $client1, + ]); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('No HTTP client configured for transaction type: pay_auth'); + + $strategy->getClient('pay_auth', 'non_secure'); + } +} diff --git a/tests/Unit/Client/HttpClientTestTrait.php b/tests/Unit/Client/HttpClientTestTrait.php new file mode 100644 index 00000000..41d432c3 --- /dev/null +++ b/tests/Unit/Client/HttpClientTestTrait.php @@ -0,0 +1,82 @@ + $headers + * + * @return RequestInterface + */ + private function prepareHttpRequest(string $requestBody, array $headers): RequestInterface + { + $requestStream = $this->createMock(StreamInterface::class); + $request = $this->createMock(RequestInterface::class); + + $this->streamFactory->expects($this->once()) + ->method('createStream') + ->with($requestBody) + ->willReturn($requestStream); + + $request->expects($this->once()) + ->method('withBody') + ->with($requestStream) + ->willReturn($request); + + if (count($headers) === 1) { + $request->expects(self::once()) + ->method('withHeader') + ->with($headers[0]['name'], $headers[0]['value']) + ->willReturn($request); + } else { + $willReturnMap = []; + foreach ($headers as $header) { + $willReturnMap[] = [ + $header['name'], + $header['value'], + $request, + ]; + } + + $request->expects(self::exactly(count($headers))) + ->method('withHeader') + ->willReturnMap($willReturnMap); + } + + return $request; + } + + private function prepareHttpResponse(string $responseContent, ?int $statusCode = null): ResponseInterface + { + $responseMock = $this->createMock(ResponseInterface::class); + $streamMock = $this->createMock(StreamInterface::class); + + if (204 !== $statusCode) { + $streamMock->expects(self::atLeastOnce()) + ->method('getContents') + ->willReturn($responseContent); + $responseMock->expects(self::atLeastOnce()) + ->method('getBody') + ->willReturn($streamMock); + } + + + if (null !== $statusCode) { + $responseMock->expects(self::atLeastOnce()) + ->method('getStatusCode') + ->willReturn($statusCode); + } + + return $responseMock; + } +} diff --git a/tests/Unit/Client/InterPosHttpClientTest.php b/tests/Unit/Client/InterPosHttpClientTest.php new file mode 100644 index 00000000..bee70fa8 --- /dev/null +++ b/tests/Unit/Client/InterPosHttpClientTest.php @@ -0,0 +1,296 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + InterPosHttpClient::class, + 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertTrue($this->client::supports(InterPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_HISTORY, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + ]; + } +} diff --git a/tests/Unit/Client/KuveytPos3DFormHttpClientTest.php b/tests/Unit/Client/KuveytPos3DFormHttpClientTest.php new file mode 100644 index 00000000..0251a83b --- /dev/null +++ b/tests/Unit/Client/KuveytPos3DFormHttpClientTest.php @@ -0,0 +1,227 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + KuveytPos3DFormHttpClient::class, + 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(KuveytPos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(KuveytPos::class, HttpClientInterface::API_NAME_QUERY_API)); + $this->assertFalse($this->client::supports(KuveytPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, PosInterface::MODEL_3D_SECURE)); + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->serializer->expects($this->never()) + ->method('decode'); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($responseContent, $actual); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate', + ]; + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate', + ], + ]; + } +} diff --git a/tests/Unit/Client/KuveytPosHttpClientTest.php b/tests/Unit/Client/KuveytPosHttpClientTest.php new file mode 100644 index 00000000..e0217f98 --- /dev/null +++ b/tests/Unit/Client/KuveytPosHttpClientTest.php @@ -0,0 +1,336 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + KuveytPosHttpClient::class, + 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(KuveytPos::class, HttpClientInterface::API_NAME_QUERY_API)); + $this->assertFalse($this->client::supports(KuveytPos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertTrue($this->client::supports(KuveytPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider getApiUrlDataFailProvider + */ + public function testGetApiUrlUnsupportedTxType(?string $txType, ?string $paymentModel, string $expectedException): void + { + $this->expectException($expectedException); + $this->client->getApiURL($txType, $paymentModel); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public function testRequestApiUrlNotFound(): void + { + $this->psrClient->expects($this->never()) + ->method('sendRequest'); + + $this->expectException(UnsupportedTransactionTypeException::class); + $this->client->request( + PosInterface::TX_TYPE_PAY_POST_AUTH, + PosInterface::MODEL_3D_SECURE, + ['request-data'], + ['id' => 123] + ); + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ]; + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelProvisionGate', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/Non3DPayGate', + ], + ]; + } + + public static function getApiUrlDataFailProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'exception_class' => UnsupportedTransactionTypeException::class, + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'exception_class' => UnsupportedTransactionTypeException::class, + ], + [ + 'txType' => null, + 'paymentModel' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + [ + 'txType' => null, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'exception_class' => \InvalidArgumentException::class, + ], + ]; + } +} diff --git a/tests/Unit/Client/KuveytSoapApiPosHttpClientTest.php b/tests/Unit/Client/KuveytSoapApiPosHttpClientTest.php new file mode 100644 index 00000000..8ea7d94b --- /dev/null +++ b/tests/Unit/Client/KuveytSoapApiPosHttpClientTest.php @@ -0,0 +1,345 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + KuveytSoapApiPosHttpClient::class, + 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(KuveytSoapApiPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertTrue($this->client::supports(KuveytSoapApiPos::class, HttpClientInterface::API_NAME_QUERY_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_NON_SECURE)); + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequestCreatesCorrectSoapRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $requestData = ['foo' => 'bar']; + $order = ['id' => 123]; + $responseContent = 'response-content'; + $encodedData = new \Mews\Pos\Serializer\EncodedData('encoded-content', SerializerInterface::FORMAT_XML); + + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + [ + 'name' => 'SOAPAction', + 'value' => 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/CancelV4', + ], + ]); + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->requestValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($txType) + ->willReturn('CancelV4'); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testCheckFailResponseThrowsExceptionOnEmptyBody(): void + { + $paymentModel = PosInterface::MODEL_NON_SECURE; + $txType = PosInterface::TX_TYPE_CANCEL; + $requestData = ['foo' => 'bar']; + $order = ['id' => 123]; + $responseContent = ''; + $expectedApiUrl = 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic'; + $encodedData = new \Mews\Pos\Serializer\EncodedData('encoded-content', SerializerInterface::FORMAT_XML); + + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + [ + 'name' => 'SOAPAction', + 'value' => 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/CancelV4', + ], + ]); + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->requestValueMapper->expects($this->once()) + ->method('mapTxType') + ->willReturn('CancelV4'); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->never()) + ->method('decode'); + + + $this->expectException(\RuntimeException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl, + ); + } + + /** + * @dataProvider failResponseDataProvider + */ + public function testCheckFailResponseThrowsExceptionOnSoapFault(array $decodedResponse, string $expectedExpMsg): void + { + $paymentModel = PosInterface::MODEL_NON_SECURE; + $txType = PosInterface::TX_TYPE_CANCEL; + $requestData = ['foo' => 'bar']; + $order = ['id' => 123]; + $responseContent = 'response-content'; + $expectedApiUrl = 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic'; + $encodedData = new \Mews\Pos\Serializer\EncodedData('encoded-content', SerializerInterface::FORMAT_XML); + + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + [ + 'name' => 'SOAPAction', + 'value' => 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/CancelV4', + ], + ]); + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->requestValueMapper->expects($this->once()) + ->method('mapTxType') + ->willReturn('CancelV4'); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willReturn($decodedResponse); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage($expectedExpMsg); + $this->expectExceptionCode(400); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl, + ); + } + + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + [ + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + [ + 'txType' => PosInterface::TX_TYPE_STATUS, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + ]; + } + + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ]; + } + + public static function failResponseDataProvider(): array + { + return [ + [ + 'decodedResponse' => [ + 's:Fault' => [ + 'faultstring' => [ + '#' => 'Some SOAP Fault', + ], + ], + ], + 'expectedExpMsg' => 'Some SOAP Fault', + ], + [ + 'decodedResponse' => [ + 's:Fault' => [ + 'some_other_key' => 'bla', + ], + ], + 'expectedExpMsg' => 'Bankaya istek başarısız!', + ], + ]; + } +} diff --git a/tests/Unit/Client/ParamPosHttpClientTest.php b/tests/Unit/Client/ParamPosHttpClientTest.php new file mode 100644 index 00000000..0f4487ea --- /dev/null +++ b/tests/Unit/Client/ParamPosHttpClientTest.php @@ -0,0 +1,335 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + ParamPosHttpClient::class, + 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + $this->serializer, + $this->crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(ParamPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertTrue($this->client::supports(Param3DHostPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + /** + * @dataProvider failResponseDataProvider + */ + public function testRequestBadRequest(array $decodedResponse, string $expectedExpMsg): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data']; + $order = ['id' => 123]; + $expectedApiUrl = 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process'; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage($expectedExpMsg); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + ], + [ + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + ], + [ + 'txType' => PosInterface::TX_TYPE_STATUS, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + ]; + } + + public static function failResponseDataProvider(): array + { + return [ + [ + 'decodedResponse' => [ + 'soap:Fault' => [ + 'faultstring' => 'Error message', + ], + ], + 'expectedExpMsg' => 'Error message', + ], + [ + 'decodedResponse' => [ + 'soap:Fault' => [ + 'some_other_key' => 'bla', + ], + ], + 'expectedExpMsg' => 'Bankaya istek başarısız!', + ], + ]; + } +} diff --git a/tests/Unit/Client/PayFlexCPV4Pos3DFormHttpClientTest.php b/tests/Unit/Client/PayFlexCPV4Pos3DFormHttpClientTest.php new file mode 100644 index 00000000..cb0623d7 --- /dev/null +++ b/tests/Unit/Client/PayFlexCPV4Pos3DFormHttpClientTest.php @@ -0,0 +1,289 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + PayFlexCPV4Pos3DFormHttpClient::class, + 'https://cptest.vakifbank.com.tr/CommonPayment/api/RegisterTransaction', + $this->serializer, + $this->crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PayFlexCPV4Pos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(PayFlexCPV4Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, PosInterface::MODEL_3D_SECURE)); + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + [ + 'name' => 'Accept', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + [ + 'name' => 'Accept', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + [ + 'name' => 'Accept', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/RegisterTransaction', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/RegisterTransaction', + ]; + } +} diff --git a/tests/Unit/Client/PayFlexCPV4PosHttpClientTest.php b/tests/Unit/Client/PayFlexCPV4PosHttpClientTest.php new file mode 100644 index 00000000..834703de --- /dev/null +++ b/tests/Unit/Client/PayFlexCPV4PosHttpClientTest.php @@ -0,0 +1,303 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + PayFlexCPV4PosHttpClient::class, + 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', + $this->serializer, + $this->crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PayFlexCPV4Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(PayFlexCPV4Pos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + [ + 'name' => 'Accept', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + [ + 'name' => 'Accept', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc=1&sa=aa', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + [ + 'name' => 'Accept', + 'value' => 'text/xml', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_HOST, + 'expected' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', + ]; + } +} diff --git a/tests/Unit/Client/PayFlexV4Pos3DFormHttpClientTest.php b/tests/Unit/Client/PayFlexV4Pos3DFormHttpClientTest.php new file mode 100644 index 00000000..9f14c502 --- /dev/null +++ b/tests/Unit/Client/PayFlexV4Pos3DFormHttpClientTest.php @@ -0,0 +1,276 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + PayFlexV4Pos3DFormHttpClient::class, + 'https://3dsecuretest.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspx', + $this->serializer, + $this->crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_QUERY_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + string $encodedRequestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + $encodedRequestData, + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->never()) + ->method('encode'); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['key1' => 'val1']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'key1=val1', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->never()) + ->method('encode'); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['key1' => 'val1']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'key1=val1', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->never()) + ->method('encode'); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, + 'paymentModel' => PosInterface::MODEL_3D_HOST, + 'expected' => 'https://3dsecuretest.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspx', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['key1' => 'val1'], + 'encodedRequestData' => 'key1=val1', + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://3dsecuretest.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspx', + ]; + } +} diff --git a/tests/Unit/Client/PayFlexV4PosHttpClientTest.php b/tests/Unit/Client/PayFlexV4PosHttpClientTest.php new file mode 100644 index 00000000..5a2c52e8 --- /dev/null +++ b/tests/Unit/Client/PayFlexV4PosHttpClientTest.php @@ -0,0 +1,299 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + PayFlexV4PosHttpClient::class, + 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + $this->serializer, + $this->crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_QUERY_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + '', + SerializerInterface::FORMAT_FORM, + ); + + $queryData = 'prmstr=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22%22+%3F%3E'; + $request = $this->prepareHttpRequest($queryData, [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '', + SerializerInterface::FORMAT_FORM, + ); + $queryData = 'prmstr=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22%22+%3F%3E'; + $request = $this->prepareHttpRequest($queryData, [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '', + SerializerInterface::FORMAT_FORM, + ); + $queryData = 'prmstr=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22%22+%3F%3E'; + $request = $this->prepareHttpRequest($queryData, [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_HOST, + 'expected' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + ]; + } +} diff --git a/tests/Unit/Client/PayFlexV4PosSearchApiHttpClientTest.php b/tests/Unit/Client/PayFlexV4PosSearchApiHttpClientTest.php new file mode 100644 index 00000000..153d059e --- /dev/null +++ b/tests/Unit/Client/PayFlexV4PosSearchApiHttpClientTest.php @@ -0,0 +1,284 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + + $this->client = PosHttpClientFactory::create( + PayFlexV4PosSearchApiHttpClient::class, + 'https://sanalpos.vakifbank.com.tr/v4/UIWebService/Search.aspx', + $this->serializer, + $this->crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_QUERY_API)); + $this->assertFalse($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_NON_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + '', + SerializerInterface::FORMAT_FORM, + ); + + $queryData = 'prmstr=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22%22+%3F%3E'; + $request = $this->prepareHttpRequest($queryData, [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '', + SerializerInterface::FORMAT_FORM, + ); + $queryData = 'prmstr=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22%22+%3F%3E'; + $request = $this->prepareHttpRequest($queryData, [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '', + SerializerInterface::FORMAT_FORM, + ); + $queryData = 'prmstr=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22%22+%3F%3E'; + $request = $this->prepareHttpRequest($queryData, [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_STATUS, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://sanalpos.vakifbank.com.tr/v4/UIWebService/Search.aspx', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://sanalpos.vakifbank.com.tr/v4/UIWebService/Search.aspx', + ]; + } +} diff --git a/tests/Unit/Client/PayForPosHttpClientTest.php b/tests/Unit/Client/PayForPosHttpClientTest.php new file mode 100644 index 00000000..01648791 --- /dev/null +++ b/tests/Unit/Client/PayForPosHttpClientTest.php @@ -0,0 +1,290 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + PayForPosHttpClient::class, + 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PayForPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + ], + [ + 'txType' => PosInterface::TX_TYPE_STATUS, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + ]; + } +} diff --git a/tests/Unit/Client/PosNetPosHttpClientTest.php b/tests/Unit/Client/PosNetPosHttpClientTest.php new file mode 100644 index 00000000..af253f5f --- /dev/null +++ b/tests/Unit/Client/PosNetPosHttpClientTest.php @@ -0,0 +1,290 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + PosNetPosHttpClient::class, + 'https://setmpos.ykb.com/PosnetWebService/XML', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PosNet::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'abc', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest('xmldata='.$encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest('xmldata='.$encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'abc', + SerializerInterface::FORMAT_FORM, + ); + $request = $this->prepareHttpRequest('xmldata='.$encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/x-www-form-urlencoded', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://setmpos.ykb.com/PosnetWebService/XML', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://setmpos.ykb.com/PosnetWebService/XML', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://setmpos.ykb.com/PosnetWebService/XML', + ], + [ + 'txType' => PosInterface::TX_TYPE_STATUS, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://setmpos.ykb.com/PosnetWebService/XML', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://setmpos.ykb.com/PosnetWebService/XML', + ]; + } +} diff --git a/tests/Unit/Client/PosNetV1PosHttpClientTest.php b/tests/Unit/Client/PosNetV1PosHttpClientTest.php new file mode 100644 index 00000000..20a999bf --- /dev/null +++ b/tests/Unit/Client/PosNetV1PosHttpClientTest.php @@ -0,0 +1,326 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + PosNetV1PosHttpClient::class, + 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $apiUri, string $expected): void + { + $this->requestValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($txType) + ->willReturn($apiUri); + + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + public function testGetApiUrlException(): void + { + $this->expectException(\InvalidArgumentException::class); + $this->client->getApiURL(); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(PosNetV1Pos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(PosNet::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->requestValueMapper->expects($this->once()) + ->method('mapTxType') + ->with(PosInterface::TX_TYPE_PAY_AUTH) + ->willReturn('Sale'); + + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + public function testSupportsTxWithUnsupportedTx(): void + { + $this->requestValueMapper->expects($this->once()) + ->method('mapTxType') + ->with('unsupported') + ->willThrowException(new UnsupportedTransactionTypeException()); + + $this->assertFalse($this->client->supportsTx('unsupported', PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestApiUrlNotFound(): void + { + $this->psrClient->expects($this->never()) + ->method('sendRequest'); + $this->requestValueMapper->expects(self::once()) + ->method('mapTxType') + ->with(PosInterface::TX_TYPE_PAY_POST_AUTH) + ->willThrowException(new UnsupportedTransactionTypeException()); + + $this->expectException(UnsupportedTransactionTypeException::class); + $this->client->request( + PosInterface::TX_TYPE_PAY_POST_AUTH, + PosInterface::MODEL_3D_SECURE, + ['request-data'], + ['id' => 123] + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'apiUri' => 'Sale', + 'expected' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Sale', + ], + [ + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'apiUri' => 'Reverse', + 'expected' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Reverse', + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Sale', + ]; + } +} diff --git a/tests/Unit/Client/ToslaPosHttpClientTest.php b/tests/Unit/Client/ToslaPosHttpClientTest.php new file mode 100644 index 00000000..b3805e5e --- /dev/null +++ b/tests/Unit/Client/ToslaPosHttpClientTest.php @@ -0,0 +1,435 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + ToslaPosHttpClient::class, + 'https://ent.akodepos.com/api/Payment', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider getApiUrlExceptionDataProvider + */ + public function testGetApiUrlException(?string $txType, ?string $paymentModel, string $exceptionClass): void + { + $this->expectException($exceptionClass); + $this->client->getApiURL($txType, $paymentModel); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(ToslaPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(PosNet::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE)); + } + + public function testSupportsTxWithUnsupportedTx(): void + { + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_HISTORY, PosInterface::MODEL_NON_SECURE)); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestEmptyResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + $expectedApiUrl = 'https://entegrasyon.asseco-see.com.tr/fim/api'; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + ]); + + $responseContent = ''; + $response = $this->prepareHttpResponse($responseContent, 204); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->serializer->expects($this->never()) + ->method('decode'); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl, + ); + + $this->assertSame([], $actual); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_PAY; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_PAY; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + '{"a": "b"}', + SerializerInterface::FORMAT_JSON, + ); + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'application/json', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestApiUrlNotFound(): void + { + $this->psrClient->expects($this->never()) + ->method('sendRequest'); + + $this->expectException(UnsupportedTransactionTypeException::class); + $this->client->request( + PosInterface::TX_TYPE_HISTORY, + PosInterface::MODEL_NON_SECURE, + ['request-data'], + ['id' => 123] + ); + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPayment', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPreAuth', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_HOST, + 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPayment', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_HOST, + 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPreAuth', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://ent.akodepos.com/api/Payment/Payment', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_POST_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://ent.akodepos.com/api/Payment/postAuth', + ], + [ + 'txType' => PosInterface::TX_TYPE_STATUS, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://ent.akodepos.com/api/Payment/inquiry', + ], + [ + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://ent.akodepos.com/api/Payment/void', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://ent.akodepos.com/api/Payment/refund', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://ent.akodepos.com/api/Payment/refund', + ], + [ + 'txType' => PosInterface::TX_TYPE_ORDER_HISTORY, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://ent.akodepos.com/api/Payment/history', + ], + ]; + } + + public static function getApiUrlExceptionDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_HISTORY, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'exception_class' => UnsupportedTransactionTypeException::class, + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'exception_class' => UnsupportedTransactionTypeException::class, + ], + [ + 'txType' => null, + 'paymentModel' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + [ + 'txType' => null, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'exception_class' => \InvalidArgumentException::class, + ], + ]; + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://ent.akodepos.com/api/Payment/threeDPayment', + ]; + } +} diff --git a/tests/Unit/Client/VakifKatilimPos3DFormHttpClientTest.php b/tests/Unit/Client/VakifKatilimPos3DFormHttpClientTest.php new file mode 100644 index 00000000..2320f19b --- /dev/null +++ b/tests/Unit/Client/VakifKatilimPos3DFormHttpClientTest.php @@ -0,0 +1,131 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + VakifKatilimPos3DFormHttpClient::class, + 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(VakifKatilimPos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_GATEWAY_3D_API)); + $this->assertFalse($this->client::supports(VakifKatilimPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, PosInterface::MODEL_3D_SECURE)); + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + } + + public function testRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['foo' => 'bar']; + $order = ['order_id' => '123']; + $url = 'https://test.url'; + + $encodedData = new EncodedData('encoded-content', SerializerInterface::FORMAT_XML); + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->serializer->expects($this->never()) + ->method('decode'); + + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $url) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $result = $this->client->request($txType, $paymentModel, $requestData, $order, $url); + + $this->assertSame($responseContent, $result); + } +} diff --git a/tests/Unit/Client/VakifKatilimPosHttpClientTest.php b/tests/Unit/Client/VakifKatilimPosHttpClientTest.php new file mode 100644 index 00000000..4d459e7d --- /dev/null +++ b/tests/Unit/Client/VakifKatilimPosHttpClientTest.php @@ -0,0 +1,411 @@ +serializer = $this->createMock(SerializerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $crypt = $this->createMock(CryptInterface::class); + $this->requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $this->psrClient = $this->createMock(ClientInterface::class); + $this->requestFactory = $this->createMock(RequestFactoryInterface::class); + $this->streamFactory = $this->createMock(StreamFactoryInterface::class); + + $this->client = PosHttpClientFactory::create( + VakifKatilimPosHttpClient::class, + 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home', + $this->serializer, + $crypt, + $this->requestValueMapper, + $this->logger, + $this->psrClient, + $this->requestFactory, + $this->streamFactory + ); + } + + public function testSupports(): void + { + $this->assertTrue($this->client::supports(VakifKatilimPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + $this->assertFalse($this->client::supports(AkbankPos::class, HttpClientInterface::API_NAME_PAYMENT_API)); + } + + public function testSupportsTx(): void + { + $this->assertTrue($this->client->supportsTx(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE)); + $this->assertFalse($this->client->supportsTx(PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, PosInterface::MODEL_3D_SECURE)); + } + + public function testSupportsTxWithUnsupportedTx(): void + { + $this->assertFalse($this->client->supportsTx('unsupported', PosInterface::MODEL_3D_SECURE)); + } + + /** + * @dataProvider getApiUrlDataProvider + */ + public function testGetApiUrl(string $txType, ?string $orderTxType, string $paymentModel, string $expected): void + { + $actual = $this->client->getApiURL($txType, $paymentModel, $orderTxType); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider getApiUrlDataFailProvider + */ + public function testGetApiUrlUnsupportedTxType( + ?string $txType, + ?string $paymentModel, + ?string $orderTxType, + string $expectedException + ): void { + $this->expectException($expectedException); + $this->client->getApiURL($txType, $paymentModel, $orderTxType); + } + + /** + * @dataProvider requestDataProvider + */ + public function testRequest( + string $txType, + string $paymentModel, + array $requestData, + array $order, + string $expectedApiUrl + ): void { + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 200); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->with('POST', $expectedApiUrl) + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $decodedResponse = ['decoded-response']; + $this->serializer->expects($this->once()) + ->method('decode') + ->with($responseContent, $txType) + ->willReturn($decodedResponse); + + $actual = $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + $expectedApiUrl + ); + + $this->assertSame($decodedResponse, $actual); + } + + public function testRequestBadRequest(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + + + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 500); + + $this->serializer->expects($this->once()) + ->method('encode') + ->with($requestData, $txType) + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->with($request) + ->willReturn($response); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('İstek Başarısız!'); + + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order, + ); + } + + public function testRequestUndecodableResponse(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data' => 'abc']; + $order = ['id' => 123]; + + $encodedData = new EncodedData( + 'data', + SerializerInterface::FORMAT_XML, + ); + + $request = $this->prepareHttpRequest($encodedData->getData(), [ + [ + 'name' => 'Content-Type', + 'value' => 'text/xml; charset=UTF-8', + ], + ]); + $responseContent = 'response-content'; + $response = $this->prepareHttpResponse($responseContent, 400); + + $this->serializer->expects($this->once()) + ->method('encode') + ->willReturn($encodedData); + + $this->requestFactory->expects($this->once()) + ->method('createRequest') + ->willReturn($request); + + $this->psrClient->expects($this->once()) + ->method('sendRequest') + ->willReturn($response); + + $this->serializer->expects($this->once()) + ->method('decode') + ->willThrowException(new NotEncodableValueException()); + + $this->expectException(NotEncodableValueException::class); + $this->client->request( + $txType, + $paymentModel, + $requestData, + $order + ); + } + + public function testRequestApiUrlNotFound(): void + { + $this->psrClient->expects($this->never()) + ->method('sendRequest'); + + $this->expectException(UnsupportedTransactionTypeException::class); + $this->client->request( + PosInterface::TX_TYPE_PAY_PRE_AUTH, + PosInterface::MODEL_3D_SECURE, + ['request-data'], + ['id' => 123] + ); + } + + public static function requestDataProvider(): \Generator + { + yield [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'requestData' => ['request-data'], + 'order' => ['id' => 123], + 'expectedApiUrl' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + ]; + } + + public static function getApiUrlDataProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'orderTxType' => null, + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelProvisionGate', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'orderTxType' => null, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizaten', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'orderTxType' => null, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/Non3DPayGate', + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_POST_AUTH, + 'orderTxType' => null, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizatenClose', + ], + [ + 'txType' => PosInterface::TX_TYPE_STATUS, + 'orderTxType' => null, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SelectOrderByMerchantOrderId', + ], + [ + 'txType' => PosInterface::TX_TYPE_ORDER_HISTORY, + 'orderTxType' => null, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SelectOrder', + ], + [ + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'orderTxType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SaleReversal', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'orderTxType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/DrawBack', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'orderTxType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PartialDrawBack', + ], + [ + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'orderTxType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizationReversal', + ], + [ + 'txType' => PosInterface::TX_TYPE_REFUND, + 'orderTxType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizationDrawBack', + ], + ]; + } + + public static function getApiUrlDataFailProvider(): array + { + return [ + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'orderTxType' => null, + 'exception_class' => UnsupportedTransactionTypeException::class, + ], + [ + 'txType' => null, + 'paymentModel' => null, + 'orderTxType' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + [ + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'paymentModel' => null, + 'orderTxType' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + [ + 'txType' => null, + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'orderTxType' => null, + 'exception_class' => \InvalidArgumentException::class, + ], + [ + 'txType' => 'abc', + 'paymentModel' => PosInterface::MODEL_3D_PAY, + 'orderTxType' => null, + 'exception_class' => UnsupportedTransactionTypeException::class, + ], + [ + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'paymentModel' => PosInterface::MODEL_NON_SECURE, + 'orderTxType' => PosInterface::TX_TYPE_PAY_POST_AUTH, + 'exception_class' => UnsupportedTransactionTypeException::class, + ], + ]; + } +} diff --git a/tests/Unit/Crypt/AkbankPosCryptTest.php b/tests/Unit/Crypt/AkbankPosCryptTest.php index d8ed98f8..5647d06e 100644 --- a/tests/Unit/Crypt/AkbankPosCryptTest.php +++ b/tests/Unit/Crypt/AkbankPosCryptTest.php @@ -11,6 +11,8 @@ use Mews\Pos\Entity\Account\AkbankPosAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\AkbankPosResponseDataMapperTest; use PHPUnit\Framework\TestCase; @@ -42,6 +44,15 @@ protected function setUp(): void $this->crypt = new AkbankPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(AkbankPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + public function testGenerateRandomString(): void { $str = $this->crypt->generateRandomString(); diff --git a/tests/Unit/Crypt/EstPosCryptTest.php b/tests/Unit/Crypt/EstPosCryptTest.php index bc5fad96..7566701b 100644 --- a/tests/Unit/Crypt/EstPosCryptTest.php +++ b/tests/Unit/Crypt/EstPosCryptTest.php @@ -11,6 +11,8 @@ use Mews\Pos\Entity\Account\EstPosAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstPos; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -42,6 +44,15 @@ protected function setUp(): void $this->crypt = new EstPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(EstPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + public function testCreate3DHash(): void { $requestData = [ diff --git a/tests/Unit/Crypt/EstV3PosCryptTest.php b/tests/Unit/Crypt/EstV3PosCryptTest.php index 61e59309..83ccae40 100644 --- a/tests/Unit/Crypt/EstV3PosCryptTest.php +++ b/tests/Unit/Crypt/EstV3PosCryptTest.php @@ -10,6 +10,8 @@ use Mews\Pos\Entity\Account\EstPosAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstPos; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -41,6 +43,15 @@ protected function setUp(): void $this->crypt = new EstV3PosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstPos::class); + $this->assertFalse($supports); + } + /** * @dataProvider threeDHashCheckDataProvider */ diff --git a/tests/Unit/Crypt/GarantiPosCryptTest.php b/tests/Unit/Crypt/GarantiPosCryptTest.php index 210daf10..32a73dcb 100644 --- a/tests/Unit/Crypt/GarantiPosCryptTest.php +++ b/tests/Unit/Crypt/GarantiPosCryptTest.php @@ -10,6 +10,8 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\GarantiPosAccount; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\GarantiPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -44,6 +46,15 @@ protected function setUp(): void $this->crypt = new GarantiPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(GarantiPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + /** * @dataProvider threeDHashCheckDataProvider */ diff --git a/tests/Unit/Crypt/InterPosCryptTest.php b/tests/Unit/Crypt/InterPosCryptTest.php index b2b75593..976dddb6 100644 --- a/tests/Unit/Crypt/InterPosCryptTest.php +++ b/tests/Unit/Crypt/InterPosCryptTest.php @@ -11,6 +11,8 @@ use Mews\Pos\Entity\Account\InterPosAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\InterPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -47,6 +49,15 @@ protected function setUp(): void $this->crypt = new InterPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(InterPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + /** * @dataProvider threeDHashCheckDataProvider */ diff --git a/tests/Unit/Crypt/KuveytPosCryptTest.php b/tests/Unit/Crypt/KuveytPosCryptTest.php index c3ed6966..d67074ea 100644 --- a/tests/Unit/Crypt/KuveytPosCryptTest.php +++ b/tests/Unit/Crypt/KuveytPosCryptTest.php @@ -11,6 +11,8 @@ use Mews\Pos\Entity\Account\KuveytPosAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\KuveytPos; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -40,6 +42,15 @@ protected function setUp(): void $this->crypt = new KuveytPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(KuveytPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + public function testHashString(): void { $actual = $this->crypt->hashString('123'); diff --git a/tests/Unit/Crypt/NullCryptTest.php b/tests/Unit/Crypt/NullCryptTest.php index 3737402d..761848e7 100644 --- a/tests/Unit/Crypt/NullCryptTest.php +++ b/tests/Unit/Crypt/NullCryptTest.php @@ -8,6 +8,8 @@ use Mews\Pos\Crypt\NullCrypt; use Mews\Pos\Entity\Account\AbstractPosAccount; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\KuveytPos; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -31,6 +33,15 @@ protected function setUp(): void $this->crypt = new NullCrypt($this->createMock(LoggerInterface::class)); } + public function testSupports(): void + { + $supports = $this->crypt::supports(KuveytPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertTrue($supports); + } + public function testCreate3DHash(): void { $this->assertSame('', $this->crypt->create3DHash($this->account, [])); diff --git a/tests/Unit/Crypt/ParamPosCryptTest.php b/tests/Unit/Crypt/ParamPosCryptTest.php index ebb95849..bde42ef8 100644 --- a/tests/Unit/Crypt/ParamPosCryptTest.php +++ b/tests/Unit/Crypt/ParamPosCryptTest.php @@ -10,6 +10,9 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\ParamPosAccount; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\Param3DHostPos; +use Mews\Pos\Gateways\ParamPos; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\ParamPosRequestDataMapperTest; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -37,6 +40,17 @@ protected function setUp(): void $this->crypt = new ParamPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(ParamPos::class); + $this->assertTrue($supports); + $supports = $this->crypt::supports(Param3DHostPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + public function testCreate3DHash(): void { $this->expectException(NotImplementedException::class); diff --git a/tests/Unit/Crypt/PayFlexCP4CryptTest.php b/tests/Unit/Crypt/PayFlexCP4CryptTest.php index 8f8ce52c..6b79a60b 100644 --- a/tests/Unit/Crypt/PayFlexCP4CryptTest.php +++ b/tests/Unit/Crypt/PayFlexCP4CryptTest.php @@ -10,6 +10,8 @@ use Mews\Pos\Entity\Account\PayFlexAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\PayFlexCPV4Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -40,6 +42,14 @@ protected function setUp(): void $this->crypt = new PayFlexCPV4Crypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(PayFlexCPV4Pos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } public function testCreate3DHash(): void { diff --git a/tests/Unit/Crypt/PayForPosCryptTest.php b/tests/Unit/Crypt/PayForPosCryptTest.php index e291d16c..d86d678b 100644 --- a/tests/Unit/Crypt/PayForPosCryptTest.php +++ b/tests/Unit/Crypt/PayForPosCryptTest.php @@ -10,6 +10,8 @@ use Mews\Pos\Entity\Account\PayForAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\PayForPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -43,6 +45,14 @@ protected function setUp(): void $this->crypt = new PayForPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(PayForPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } /** * @dataProvider threeDHashCreateDataProvider diff --git a/tests/Unit/Crypt/PosNetCryptTest.php b/tests/Unit/Crypt/PosNetCryptTest.php index 60a7a245..5be9ea2e 100644 --- a/tests/Unit/Crypt/PosNetCryptTest.php +++ b/tests/Unit/Crypt/PosNetCryptTest.php @@ -11,6 +11,8 @@ use Mews\Pos\Entity\Account\PosNetAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\PosNet; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -42,6 +44,15 @@ protected function setUp(): void $this->crypt = new PosNetCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(PosNet::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + public function testCreate3DHashException(): void { $this->expectException(NotImplementedException::class); diff --git a/tests/Unit/Crypt/PosNetV1PosCryptTest.php b/tests/Unit/Crypt/PosNetV1PosCryptTest.php index f8a8b17d..5468b7ef 100644 --- a/tests/Unit/Crypt/PosNetV1PosCryptTest.php +++ b/tests/Unit/Crypt/PosNetV1PosCryptTest.php @@ -10,6 +10,8 @@ use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PosNetAccount; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\PosNetV1Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -41,6 +43,15 @@ protected function setUp(): void $this->crypt = new PosNetV1PosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(PosNetV1Pos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + /** * @dataProvider hashFromParamsDataProvider */ diff --git a/tests/Unit/Crypt/ToslaPosCryptTest.php b/tests/Unit/Crypt/ToslaPosCryptTest.php index 4f8d6f9e..47e29114 100644 --- a/tests/Unit/Crypt/ToslaPosCryptTest.php +++ b/tests/Unit/Crypt/ToslaPosCryptTest.php @@ -11,6 +11,8 @@ use Mews\Pos\Entity\Account\ToslaPosAccount; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\AccountFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\ToslaPos; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -39,6 +41,15 @@ protected function setUp(): void $this->crypt = new ToslaPosCrypt($logger); } + public function testSupports(): void + { + $supports = $this->crypt::supports(ToslaPos::class); + $this->assertTrue($supports); + + $supports = $this->crypt::supports(EstV3Pos::class); + $this->assertFalse($supports); + } + public function testCreate3DHash(): void { $this->expectException(NotImplementedException::class); diff --git a/tests/Unit/DataMapper/RequestDataMapper/AkbankPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/AkbankPosRequestDataMapperTest.php index e670108c..f7f24db3 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/AkbankPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/AkbankPosRequestDataMapperTest.php @@ -8,13 +8,15 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\AkbankPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\AkbankPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\AkbankPosRequestValueMapper; use Mews\Pos\Entity\Account\AkbankPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\Before3DFormHashCalculatedEvent; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\EstPos; use Mews\Pos\PosInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\AkbankPosResponseDataMapperTest; use PHPUnit\Framework\MockObject\MockObject; @@ -42,6 +44,10 @@ class AkbankPosRequestDataMapperTest extends TestCase private EventDispatcherInterface $dispatcher; + private AkbankPosRequestValueFormatter $valueFormatter; + + private AkbankPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -52,14 +58,12 @@ protected function setUp(): void '2023090417500272654BD9A49CF07574', '2023090417500284633D137A249DBBEB', '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f', - PosInterface::LANG_TR, ); $this->subMerchantAccount = AccountFactory::createAkbankPosAccount( 'akbank-pos', '2023090417500272654BD9A49CF07574', '2023090417500284633D137A249DBBEB', '3230323330393034313735303032363031353172675f357637355f3273387373745f7233725f73323333383737335f323272383774767276327672323531355f', - PosInterface::LANG_TR, 'sub-merchant-id' ); @@ -73,71 +77,27 @@ protected function setUp(): void 'fail_url' => 'http:://localhost/fail', ]; - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - - $this->requestDataMapper = new AkbankPosRequestDataMapper($this->dispatcher, $this->crypt); - } - - /** - * @testWith ["pay", "3d", "3000"] - * ["pre", "3d", "3004"] - * ["pre", "regular", "1004"] - */ - public function testMapTxType(string $txType, string $paymentModel, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType, $paymentModel); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["1"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new AkbankPosRequestValueFormatter(); + $this->valueMapper = new AkbankPosRequestValueMapper(); + + $this->requestDataMapper = new AkbankPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); } - /** - * @testWith ["pre", null] - */ - public function testMapTxTypeInvArgException(string $txType, ?string $paymentModel): void + public function testSupports(): void { - $this->expectException(\InvalidArgumentException::class); - $this->requestDataMapper->mapTxType($txType, $paymentModel); - } + $result = $this->requestDataMapper::supports(AkbankPos::class); + $this->assertTrue($result); - - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame(949, $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame(978, $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } - - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", 1] - * ["1", 1] - * ["2", 2] - * [2, 2] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstPos::class); + $this->assertFalse($result); } /** @@ -190,7 +150,7 @@ public function testGet3DFormDataSubMerchant(): void 'merchantSafeId' => '2023090417500272654BD9A49CF07574', 'terminalSafeId' => '2023090417500284633D137A249DBBEB', 'orderId' => '2020110828BC', - 'lang' => 'TR', + 'lang' => 'EN', 'amount' => '1.10', 'currencyCode' => '949', 'installCount' => '1', @@ -982,7 +942,7 @@ public static function threeDFormDataProvider(): array 'merchantSafeId' => '2023090417500272654BD9A49CF07574', 'terminalSafeId' => '2023090417500284633D137A249DBBEB', 'orderId' => '2020110828BC', - 'lang' => 'TR', + 'lang' => 'EN', 'amount' => '10.00', 'currencyCode' => '949', 'installCount' => '1', @@ -1016,7 +976,7 @@ public static function threeDFormDataProvider(): array 'merchantSafeId' => '2023090417500272654BD9A49CF07574', 'terminalSafeId' => '2023090417500284633D137A249DBBEB', 'orderId' => '2020110828BC', - 'lang' => 'TR', + 'lang' => 'EN', 'amount' => '1.10', 'currencyCode' => '949', 'installCount' => '1', @@ -1053,7 +1013,7 @@ public static function threeDFormDataProvider(): array 'merchantSafeId' => '2023090417500272654BD9A49CF07574', 'terminalSafeId' => '2023090417500284633D137A249DBBEB', 'orderId' => '2020110828BC', - 'lang' => 'TR', + 'lang' => 'EN', 'amount' => '1.10', 'currencyCode' => '949', 'installCount' => '1', @@ -1090,7 +1050,7 @@ public static function threeDFormDataProvider(): array 'merchantSafeId' => '2023090417500272654BD9A49CF07574', 'terminalSafeId' => '2023090417500284633D137A249DBBEB', 'orderId' => '2020110828BC', - 'lang' => 'TR', + 'lang' => 'EN', 'amount' => '1000.00', 'currencyCode' => '949', 'installCount' => '1', diff --git a/tests/Unit/DataMapper/RequestDataMapper/EstPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/EstPosRequestDataMapperTest.php index 6bb4d6ee..2f1a4ff4 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/EstPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/EstPosRequestDataMapperTest.php @@ -8,14 +8,16 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\EstPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\EstPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\EstPosRequestValueMapper; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\EstPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\Before3DFormHashCalculatedEvent; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; use Mews\Pos\Gateways\EstPos; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -39,6 +41,10 @@ class EstPosRequestDataMapperTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private EventDispatcherInterface $dispatcher; + private EstPosRequestValueFormatter $valueFormatter; + + private EstPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -52,10 +58,18 @@ protected function setUp(): void 'TRPS0200' ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - - $this->requestDataMapper = new EstPosRequestDataMapper($this->dispatcher, $this->crypt); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new EstPosRequestValueFormatter(); + $this->valueMapper = new EstPosRequestValueMapper(); + + $this->requestDataMapper = new EstPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); $this->card = CreditCardFactory::create( '5555444433332222', '22', @@ -65,66 +79,13 @@ protected function setUp(): void ); } - /** - * @testWith ["MONTH", "M"] - * ["M", "M"] - */ - public function testMapRecurringFrequency(string $frequency, string $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapRecurringFrequency'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$frequency])); - } - - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } - - /** - * @testWith ["pay", "Auth"] - * ["pre", "PreAuth"] - */ - public function testMapTxType(string $txType, string $expected): void + public function testSupports(): void { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } + $result = $this->requestDataMapper::supports(EstPos::class); + $this->assertTrue($result); - /** - * @testWith ["Auth"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", ""] - * ["1", ""] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -555,7 +516,7 @@ public static function postAuthRequestDataProvider(): array 'ClientId' => '700655000200', 'Type' => 'PostAuth', 'OrderId' => '2020110828BC', - 'Total' => 1.0, + 'Total' => '1', ], ], 'with_pre_auth_amount' => [ @@ -570,9 +531,9 @@ public static function postAuthRequestDataProvider(): array 'ClientId' => '700655000200', 'Type' => 'PostAuth', 'OrderId' => '2020110828BC', - 'Total' => 1.1, + 'Total' => '1.1', 'Extra' => [ - 'PREAMT' => 1.0, + 'PREAMT' => '1', ], ], ], diff --git a/tests/Unit/DataMapper/RequestDataMapper/EstV3PosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/EstV3PosRequestDataMapperTest.php index af2903bc..3b5e6614 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/EstV3PosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/EstV3PosRequestDataMapperTest.php @@ -8,11 +8,14 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\EstV3PosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\EstPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\EstPosRequestValueMapper; use Mews\Pos\Entity\Account\EstPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\Before3DFormHashCalculatedEvent; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstPos; use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; @@ -21,6 +24,7 @@ /** * @covers \Mews\Pos\DataMapper\RequestDataMapper\EstV3PosRequestDataMapper + * @covers \Mews\Pos\DataMapper\RequestDataMapper\AbstractRequestDataMapper */ class EstV3PosRequestDataMapperTest extends TestCase { @@ -36,6 +40,10 @@ class EstV3PosRequestDataMapperTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private EventDispatcherInterface $dispatcher; + private EstPosRequestValueFormatter $valueFormatter; + + private EstPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -49,11 +57,29 @@ protected function setUp(): void '123456' ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new EstPosRequestValueFormatter(); + $this->valueMapper = new EstPosRequestValueMapper(); + + $this->requestDataMapper = new EstV3PosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); + + $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet', CreditCardInterface::CARD_TYPE_VISA); + } + + public function testSupports(): void + { + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertTrue($result); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new EstV3PosRequestDataMapper($this->dispatcher, $this->crypt); - $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet', CreditCardInterface::CARD_TYPE_VISA); + $result = $this->requestDataMapper::supports(EstPos::class); + $this->assertFalse($result); } /** diff --git a/tests/Unit/DataMapper/RequestDataMapper/GarantiPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/GarantiPosRequestDataMapperTest.php index 8282dc6d..f033780e 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/GarantiPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/GarantiPosRequestDataMapperTest.php @@ -8,12 +8,14 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\GarantiPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\GarantiPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\GarantiPosRequestValueMapper; use Mews\Pos\Entity\Account\GarantiPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\Before3DFormHashCalculatedEvent; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\Gateways\GarantiPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; @@ -38,6 +40,10 @@ class GarantiPosRequestDataMapperTest extends TestCase /** @var CryptInterface & MockObject */ private CryptInterface $crypt; + private GarantiPosRequestValueFormatter $valueFormatter; + + private GarantiPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -54,75 +60,31 @@ protected function setUp(): void '123qweASD/' ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new GarantiPosRequestDataMapper($this->dispatcher, $this->crypt); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new GarantiPosRequestValueFormatter(); + $this->valueMapper = new GarantiPosRequestValueMapper(); + + $this->requestDataMapper = new GarantiPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); + $this->requestDataMapper->setTestMode(true); $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet'); } - /** - * @testWith ["pay", "sales"] - * ["pre", "preauth"] - */ - public function testMapTxType(string $txType, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["sales"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testFormatAmount(): void + public function testSupports(): void { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame(100000, $method->invokeArgs($this->requestDataMapper, [1000])); - $this->assertSame(100000, $method->invokeArgs($this->requestDataMapper, [1000.00])); - $this->assertSame(100001, $method->invokeArgs($this->requestDataMapper, [1000.01])); - } + $result = $this->requestDataMapper::supports(GarantiPos::class); + $this->assertTrue($result); - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } - - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", ""] - * ["1", ""] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** diff --git a/tests/Unit/DataMapper/RequestDataMapper/InterPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/InterPosRequestDataMapperTest.php index ec1dc359..d717a7e3 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/InterPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/InterPosRequestDataMapperTest.php @@ -8,12 +8,14 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\InterPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\InterPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\InterPosRequestValueMapper; use Mews\Pos\Entity\Account\InterPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\Before3DFormHashCalculatedEvent; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\Gateways\InterPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; @@ -38,6 +40,10 @@ class InterPosRequestDataMapperTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private EventDispatcherInterface $dispatcher; + private InterPosRequestValueFormatter $valueFormatter; + + private InterPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -56,61 +62,29 @@ protected function setUp(): void $merchantPass ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new InterPosRequestDataMapper($this->dispatcher, $this->crypt); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new InterPosRequestValueFormatter(); + $this->valueMapper = new InterPosRequestValueMapper(); + + $this->requestDataMapper = new InterPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); $this->card = CreditCardFactory::create('5555444433332222', '21', '12', '122', 'ahmet', CreditCardInterface::CARD_TYPE_VISA); } - /** - * @testWith ["pay", "Auth"] - * ["pre", "PreAuth"] - */ - public function testMapTxType(string $txType, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["PreAuth"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testMapCurrency(): void + public function testSupports(): void { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } + $result = $this->requestDataMapper::supports(InterPos::class); + $this->assertTrue($result); - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", ""] - * ["1", ""] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -534,7 +508,7 @@ public static function refundOrderDataProvider(): \Generator 'order' => $order, 'tx_type' => PosInterface::TX_TYPE_REFUND, 'expectedData' => [ - 'Lang' => 'tr', + 'Lang' => 'en', 'MOTO' => '0', 'OrderId' => null, 'PurchAmount' => '123.1', @@ -551,7 +525,7 @@ public static function refundOrderDataProvider(): \Generator 'order' => $order, 'tx_type' => PosInterface::TX_TYPE_REFUND_PARTIAL, 'expectedData' => [ - 'Lang' => 'tr', + 'Lang' => 'en', 'MOTO' => '0', 'OrderId' => null, 'PurchAmount' => '123.1', diff --git a/tests/Unit/DataMapper/RequestDataMapper/KuveytPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/KuveytPosRequestDataMapperTest.php index 007a85a5..6941d1b1 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/KuveytPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/KuveytPosRequestDataMapperTest.php @@ -6,14 +6,16 @@ namespace Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper; -use Generator; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\KuveytPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\KuveytPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\KuveytPosRequestValueMapper; use Mews\Pos\Entity\Account\KuveytPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\KuveytPos; use Mews\Pos\PosInterface; use Mews\Pos\Tests\TestUtil\TestUtilTrait; use PHPUnit\Framework\MockObject\MockObject; @@ -40,6 +42,10 @@ class KuveytPosRequestDataMapperTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private EventDispatcherInterface $dispatcher; + private KuveytPosRequestValueFormatter $valueFormatter; + + private KuveytPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -52,8 +58,6 @@ protected function setUp(): void 'Api123' ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->card = CreditCardFactory::create( '4155650100416111', 25, @@ -63,71 +67,27 @@ protected function setUp(): void CreditCardInterface::CARD_TYPE_VISA ); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new KuveytPosRequestDataMapper($this->dispatcher, $this->crypt); - } - - /** - * @testWith ["pay", "Sale"] - */ - public function testMapTxType(string $txType, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["Sale"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame(0, $method->invokeArgs($this->requestDataMapper, [0])); - $this->assertSame(0, $method->invokeArgs($this->requestDataMapper, [0.0])); - $this->assertSame(1025, $method->invokeArgs($this->requestDataMapper, [10.25])); - $this->assertSame(1000, $method->invokeArgs($this->requestDataMapper, [10.00])); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new KuveytPosRequestValueFormatter(); + $this->valueMapper = new KuveytPosRequestValueMapper(); + + $this->requestDataMapper = new KuveytPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); } - /** - * @return void - */ - public function testMapCurrency(): void + public function testSupports(): void { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('0949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('0978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } + $result = $this->requestDataMapper::supports(KuveytPos::class); + $this->assertTrue($result); - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "0"] - * ["1", "0"] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -156,55 +116,22 @@ public function testCreate3DEnrollmentCheckRequestData(array $order, string $txT $this->assertSame($expectedData, $actualData); } - /** - * @dataProvider createCancelRequestDataProvider - */ - public function testCreateCancelRequestData(array $order, array $expected): void + public function testCreateCancelRequestData(): void { - $this->crypt->expects(self::once()) - ->method('createHash') - ->willReturn('request-hash'); - - $actual = $this->requestDataMapper->createCancelRequestData($this->account, $order); - - self::recursiveKsort($actual); - self::recursiveKsort($expected); - - $this->assertSame($expected, $actual); + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createCancelRequestData($this->account, []); } - /** - * @dataProvider createRefundRequestDataProvider - */ - public function testCreateRefundRequestData(array $order, string $txType, array $expected): void + public function testCreateRefundRequestData(): void { - $this->crypt->expects(self::once()) - ->method('createHash') - ->willReturn('request-hash'); - - $actual = $this->requestDataMapper->createRefundRequestData($this->account, $order, $txType); - - self::recursiveKsort($actual); - self::recursiveKsort($expected); - - $this->assertSame($expected, $actual); + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createRefundRequestData($this->account, [], PosInterface::TX_TYPE_REFUND); } - /** - * @dataProvider createStatusRequestDataProvider - */ - public function testCreateStatusRequestData(array $order, array $expected): void + public function testCreateStatusRequestData(): void { - $this->crypt->expects(self::once()) - ->method('createHash') - ->willReturn('request-hash'); - - $actual = $this->requestDataMapper->createStatusRequestData($this->account, $order); - - self::recursiveKsort($actual); - self::recursiveKsort($expected); - - $this->assertSame($expected, $actual); + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createStatusRequestData($this->account, []); } /** @@ -253,28 +180,18 @@ public function testCreateNonSecurePaymentRequestData(array $order, string $txTy public function testGet3DFormData(): void { - $expected = [ - 'gateway' => 'https://bank-gateway.com', - 'method' => 'POST', - 'inputs' => [ - 'abc' => '123', - ], - ]; - $txType = PosInterface::TX_TYPE_PAY_AUTH; $paymentModel = PosInterface::MODEL_3D_SECURE; - $this->dispatcher->expects(self::never()) - ->method('dispatch'); - $actual = $this->requestDataMapper->create3DFormData( + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + + $this->requestDataMapper->create3DFormData( $this->account, - ['abc' => '123'], + ['id' => '123'], $paymentModel, $txType, 'https://bank-gateway.com', ); - - $this->assertSame($expected, $actual); } public function testCreateNonSecurePostAuthPaymentRequestData(): void @@ -295,240 +212,56 @@ public function testCreateHistoryRequestData(): void $this->requestDataMapper->createHistoryRequestData($this->account, []); } - public function testCreateCustomQueryRequestData(): void + /** + * @dataProvider createCustomQueryRequestDataDataProvider + */ + public function testCreateCustomQueryRequestData(array $requestData, array $expectedData): void { - $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); - $this->requestDataMapper->createCustomQueryRequestData($this->account, []); - } + if (!isset($requestData['HashData'])) { + $this->crypt->expects(self::once()) + ->method('createHash') + ->willReturn($expectedData['HashData']); + } - public static function createCancelRequestDataProvider(): iterable - { - yield [ - 'order' => [ - 'id' => '2023070849CD', - 'remote_order_id' => '114293600', - 'ref_ret_num' => '318923298433', - 'auth_code' => '241839', - 'transaction_id' => '298433', - 'amount' => 1.01, - 'currency' => PosInterface::CURRENCY_TRY, - ], - 'expected' => [ - 'SaleReversal' => [ - 'request' => [ - 'IsFromExternalNetwork' => true, - 'BusinessKey' => 0, - 'ResourceId' => 0, - 'ActionId' => 0, - 'LanguageId' => 0, - 'CustomerId' => '400235', - 'MailOrTelephoneOrder' => true, - 'Amount' => 101, - 'MerchantId' => '80', - 'OrderId' => '114293600', - 'RRN' => '318923298433', - 'Stan' => '298433', - 'ProvisionNumber' => '241839', - 'VPosMessage' => [ - 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, - 'InstallmentMaturityCommisionFlag' => 0, - 'HashData' => 'request-hash', - 'MerchantId' => '80', - 'SubMerchantId' => 0, - 'CustomerId' => '400235', - 'UserName' => 'apiuser', - 'CardType' => 'Visa', - 'BatchID' => 0, - 'TransactionType' => 'SaleReversal', - 'InstallmentCount' => 0, - 'Amount' => 101, - 'DisplayAmount' => 101, - 'CancelAmount' => 101, - 'MerchantOrderId' => '2023070849CD', - 'FECAmount' => 0, - 'CurrencyCode' => '0949', - 'QeryId' => 0, - 'DebtId' => 0, - 'SurchargeAmount' => 0, - 'SGKDebtAmount' => 0, - 'TransactionSecurity' => 1, - ], - ], - ], - ], - ]; + $actual = $this->requestDataMapper->createCustomQueryRequestData($this->account, $requestData); + + \ksort($actual); + \ksort($expectedData); + $this->assertSame($expectedData, $actual); } - public static function createRefundRequestDataProvider(): Generator + public static function createCustomQueryRequestDataDataProvider(): \Generator { - yield [ - 'full_refund' => [ - 'id' => '2023070849CD', - 'remote_order_id' => '114293600', - 'ref_ret_num' => '318923298433', - 'auth_code' => '241839', - 'transaction_id' => '298433', - 'amount' => 1.01, - 'currency' => PosInterface::CURRENCY_TRY, - ], - 'tx_type' => PosInterface::TX_TYPE_REFUND, - 'expected' => [ - 'DrawBack' => [ - 'request' => [ - 'IsFromExternalNetwork' => true, - 'BusinessKey' => 0, - 'ResourceId' => 0, - 'ActionId' => 0, - 'LanguageId' => 0, - 'CustomerId' => '400235', - 'MailOrTelephoneOrder' => true, - 'Amount' => 101, - 'MerchantId' => '80', - 'OrderId' => '114293600', - 'RRN' => '318923298433', - 'Stan' => '298433', - 'ProvisionNumber' => '241839', - 'VPosMessage' => [ - 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, - 'InstallmentMaturityCommisionFlag' => 0, - 'HashData' => 'request-hash', - 'MerchantId' => '80', - 'SubMerchantId' => 0, - 'CustomerId' => '400235', - 'UserName' => 'apiuser', - 'CardType' => 'Visa', - 'BatchID' => 0, - 'TransactionType' => 'DrawBack', - 'InstallmentCount' => 0, - 'Amount' => 101, - 'DisplayAmount' => 0, - 'CancelAmount' => 101, - 'MerchantOrderId' => '2023070849CD', - 'FECAmount' => 0, - 'CurrencyCode' => '0949', - 'QeryId' => 0, - 'DebtId' => 0, - 'SurchargeAmount' => 0, - 'SGKDebtAmount' => 0, - 'TransactionSecurity' => 1, - ], - ], - ], + yield 'without_account_data' => [ + 'request_data' => [ + 'abc' => 'abc', ], - ]; - - yield [ - 'partial_refund' => [ - 'id' => '2023070849CD', - 'remote_order_id' => '114293600', - 'ref_ret_num' => '318923298433', - 'auth_code' => '241839', - 'transaction_id' => '298433', - 'amount' => 9.01, - 'order_amount' => 10.01, - 'currency' => PosInterface::CURRENCY_TRY, - ], - 'tx_type' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'expected' => [ - 'PartialDrawback' => [ - 'request' => [ - 'IsFromExternalNetwork' => true, - 'BusinessKey' => 0, - 'ResourceId' => 0, - 'ActionId' => 0, - 'LanguageId' => 0, - 'CustomerId' => '400235', - 'MailOrTelephoneOrder' => true, - 'Amount' => 901, - 'MerchantId' => '80', - 'OrderId' => '114293600', - 'RRN' => '318923298433', - 'Stan' => '298433', - 'ProvisionNumber' => '241839', - 'VPosMessage' => [ - 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, - 'InstallmentMaturityCommisionFlag' => 0, - 'HashData' => 'request-hash', - 'MerchantId' => '80', - 'SubMerchantId' => 0, - 'CustomerId' => '400235', - 'UserName' => 'apiuser', - 'CardType' => 'Visa', - 'BatchID' => 0, - 'TransactionType' => 'PartialDrawback', - 'InstallmentCount' => 0, - 'Amount' => 901, - 'DisplayAmount' => 0, - 'CancelAmount' => 901, - 'MerchantOrderId' => '2023070849CD', - 'FECAmount' => 0, - 'CurrencyCode' => '0949', - 'QeryId' => 0, - 'DebtId' => 0, - 'SurchargeAmount' => 0, - 'SGKDebtAmount' => 0, - 'TransactionSecurity' => 1, - ], - ], - ], + 'expected' => [ + 'abc' => 'abc', + 'MerchantId' => '80', + 'CustomerId' => '400235', + 'UserName' => 'apiuser', + 'APIVersion' => 'TDV2.0.0', + 'HashData' => 'hasshhh', ], ]; - } - public static function createStatusRequestDataProvider(): iterable - { - $startDate = new \DateTime('2022-07-08T22:44:31'); - $endDate = new \DateTime('2023-07-08T22:44:31'); - yield [ - 'order' => [ - 'id' => '2023070849CD', - 'currency' => PosInterface::CURRENCY_TRY, - 'start_date' => $startDate, - 'end_date' => $endDate, + yield 'with_account_data' => [ + 'request_data' => [ + 'abc' => 'abc', + 'MerchantId' => '802', + 'CustomerId' => '4002352', + 'UserName' => 'apiuser2', + 'APIVersion' => 'TDV1.0.0', + 'HashData' => 'hasshhh22', ], - 'expected' => [ - 'GetMerchantOrderDetail' => [ - 'request' => [ - 'IsFromExternalNetwork' => true, - 'BusinessKey' => 0, - 'ResourceId' => 0, - 'ActionId' => 0, - 'LanguageId' => 0, - 'CustomerId' => '400235', - 'MailOrTelephoneOrder' => true, - 'Amount' => 0, - 'MerchantId' => '80', - 'OrderId' => 0, - 'TransactionType' => 0, - 'VPosMessage' => [ - 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, - 'InstallmentMaturityCommisionFlag' => 0, - 'HashData' => 'request-hash', - 'MerchantId' => '80', - 'SubMerchantId' => 0, - 'CustomerId' => '400235', - 'UserName' => 'apiuser', - 'CardType' => 'Visa', - 'BatchID' => 0, - 'TransactionType' => 'GetMerchantOrderDetail', - 'InstallmentCount' => 0, - 'Amount' => 0, - 'DisplayAmount' => 0, - 'CancelAmount' => 0, - 'MerchantOrderId' => '2023070849CD', - 'FECAmount' => 0, - 'CurrencyCode' => '0949', - 'QeryId' => 0, - 'DebtId' => 0, - 'SurchargeAmount' => 0, - 'SGKDebtAmount' => 0, - 'TransactionSecurity' => 1, - ], - 'MerchantOrderId' => '2023070849CD', - 'StartDate' => '2022-07-08T22:44:31', - 'EndDate' => '2023-07-08T22:44:31', - ], - ], + 'expected' => [ + 'abc' => 'abc', + 'MerchantId' => '802', + 'CustomerId' => '4002352', + 'UserName' => 'apiuser2', + 'APIVersion' => 'TDV1.0.0', + 'HashData' => 'hasshhh22', ], ]; } diff --git a/tests/Unit/DataMapper/RequestDataMapper/KuveytSoapApiPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/KuveytSoapApiPosRequestDataMapperTest.php new file mode 100644 index 00000000..83bcfa25 --- /dev/null +++ b/tests/Unit/DataMapper/RequestDataMapper/KuveytSoapApiPosRequestDataMapperTest.php @@ -0,0 +1,429 @@ +account = AccountFactory::createKuveytPosAccount( + 'kuveytpos', + '80', + 'apiuser', + '400235', + 'Api123' + ); + + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new KuveytPosRequestValueFormatter(); + $this->valueMapper = new KuveytPosRequestValueMapper(); + + $this->requestDataMapper = new KuveytSoapApiPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); + } + + public function testSupports(): void + { + $result = $this->requestDataMapper::supports(KuveytSoapApiPos::class); + $this->assertTrue($result); + + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider createCancelRequestDataProvider + */ + public function testCreateCancelRequestData(array $order, array $expected): void + { + $this->crypt->expects(self::once()) + ->method('createHash') + ->willReturn('request-hash'); + + $actual = $this->requestDataMapper->createCancelRequestData($this->account, $order); + + self::recursiveKsort($actual); + self::recursiveKsort($expected); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider createRefundRequestDataProvider + */ + public function testCreateRefundRequestData(array $order, string $txType, array $expected): void + { + $this->crypt->expects(self::once()) + ->method('createHash') + ->willReturn('request-hash'); + + $actual = $this->requestDataMapper->createRefundRequestData($this->account, $order, $txType); + + self::recursiveKsort($actual); + self::recursiveKsort($expected); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider createStatusRequestDataProvider + */ + public function testCreateStatusRequestData(array $order, array $expected): void + { + $this->crypt->expects(self::once()) + ->method('createHash') + ->willReturn('request-hash'); + + $actual = $this->requestDataMapper->createStatusRequestData($this->account, $order); + + self::recursiveKsort($actual); + self::recursiveKsort($expected); + + $this->assertSame($expected, $actual); + } + + public function testGet3DFormData(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + + $this->requestDataMapper->create3DFormData( + $this->account, + ['id' => '123'], + $paymentModel, + $txType, + 'https://bank-gateway.com', + ); + } + + public function testCreate3DPaymentRequestData(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + + $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + [], + PosInterface::TX_TYPE_PAY_AUTH, + [] + ); + } + + public function testCreateNonSecurePaymentRequestData(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createNonSecurePaymentRequestData( + $this->account, + [], + PosInterface::TX_TYPE_PAY_AUTH, + $this->createMock(CreditCardInterface::class) + ); + } + + public function testCreateNonSecurePostAuthPaymentRequestData(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createNonSecurePostAuthPaymentRequestData($this->account, []); + } + + public function testCreateOrderHistoryRequestData(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createOrderHistoryRequestData($this->account, []); + } + + public function testCreateHistoryRequestData(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createHistoryRequestData($this->account, []); + } + + public function testCreateCustomQueryRequestData(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createCustomQueryRequestData($this->account, []); + } + + + public static function createCancelRequestDataProvider(): \Generator + { + yield [ + 'order' => [ + 'id' => '2023070849CD', + 'remote_order_id' => '114293600', + 'ref_ret_num' => '318923298433', + 'auth_code' => '241839', + 'transaction_id' => '298433', + 'amount' => 1.01, + 'currency' => PosInterface::CURRENCY_TRY, + ], + 'expected' => [ + 'SaleReversal' => [ + 'request' => [ + 'IsFromExternalNetwork' => true, + 'BusinessKey' => 0, + 'ResourceId' => 0, + 'ActionId' => 0, + 'LanguageId' => 0, + 'CustomerId' => '400235', + 'MailOrTelephoneOrder' => true, + 'Amount' => 101, + 'MerchantId' => '80', + 'OrderId' => '114293600', + 'RRN' => '318923298433', + 'Stan' => '298433', + 'ProvisionNumber' => '241839', + 'VPosMessage' => [ + 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, + 'InstallmentMaturityCommisionFlag' => 0, + 'HashData' => 'request-hash', + 'MerchantId' => '80', + 'SubMerchantId' => 0, + 'CustomerId' => '400235', + 'UserName' => 'apiuser', + 'CardType' => 'Visa', + 'BatchID' => 0, + 'TransactionType' => 'SaleReversal', + 'InstallmentCount' => 0, + 'Amount' => 101, + 'DisplayAmount' => 101, + 'CancelAmount' => 101, + 'MerchantOrderId' => '2023070849CD', + 'FECAmount' => 0, + 'CurrencyCode' => '0949', + 'QeryId' => 0, + 'DebtId' => 0, + 'SurchargeAmount' => 0, + 'SGKDebtAmount' => 0, + 'TransactionSecurity' => 1, + ], + ], + ], + ], + ]; + } + + public static function createRefundRequestDataProvider(): Generator + { + yield [ + 'full_refund' => [ + 'id' => '2023070849CD', + 'remote_order_id' => '114293600', + 'ref_ret_num' => '318923298433', + 'auth_code' => '241839', + 'transaction_id' => '298433', + 'amount' => 1.01, + 'currency' => PosInterface::CURRENCY_TRY, + ], + 'tx_type' => PosInterface::TX_TYPE_REFUND, + 'expected' => [ + 'DrawBack' => [ + 'request' => [ + 'IsFromExternalNetwork' => true, + 'BusinessKey' => 0, + 'ResourceId' => 0, + 'ActionId' => 0, + 'LanguageId' => 0, + 'CustomerId' => '400235', + 'MailOrTelephoneOrder' => true, + 'Amount' => 101, + 'MerchantId' => '80', + 'OrderId' => '114293600', + 'RRN' => '318923298433', + 'Stan' => '298433', + 'ProvisionNumber' => '241839', + 'VPosMessage' => [ + 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, + 'InstallmentMaturityCommisionFlag' => 0, + 'HashData' => 'request-hash', + 'MerchantId' => '80', + 'SubMerchantId' => 0, + 'CustomerId' => '400235', + 'UserName' => 'apiuser', + 'CardType' => 'Visa', + 'BatchID' => 0, + 'TransactionType' => 'DrawBack', + 'InstallmentCount' => 0, + 'Amount' => 101, + 'DisplayAmount' => 0, + 'CancelAmount' => 101, + 'MerchantOrderId' => '2023070849CD', + 'FECAmount' => 0, + 'CurrencyCode' => '0949', + 'QeryId' => 0, + 'DebtId' => 0, + 'SurchargeAmount' => 0, + 'SGKDebtAmount' => 0, + 'TransactionSecurity' => 1, + ], + ], + ], + ], + ]; + + yield [ + 'partial_refund' => [ + 'id' => '2023070849CD', + 'remote_order_id' => '114293600', + 'ref_ret_num' => '318923298433', + 'auth_code' => '241839', + 'transaction_id' => '298433', + 'amount' => 9.01, + 'order_amount' => 10.01, + 'currency' => PosInterface::CURRENCY_TRY, + ], + 'tx_type' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'expected' => [ + 'PartialDrawback' => [ + 'request' => [ + 'IsFromExternalNetwork' => true, + 'BusinessKey' => 0, + 'ResourceId' => 0, + 'ActionId' => 0, + 'LanguageId' => 0, + 'CustomerId' => '400235', + 'MailOrTelephoneOrder' => true, + 'Amount' => 901, + 'MerchantId' => '80', + 'OrderId' => '114293600', + 'RRN' => '318923298433', + 'Stan' => '298433', + 'ProvisionNumber' => '241839', + 'VPosMessage' => [ + 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, + 'InstallmentMaturityCommisionFlag' => 0, + 'HashData' => 'request-hash', + 'MerchantId' => '80', + 'SubMerchantId' => 0, + 'CustomerId' => '400235', + 'UserName' => 'apiuser', + 'CardType' => 'Visa', + 'BatchID' => 0, + 'TransactionType' => 'PartialDrawback', + 'InstallmentCount' => 0, + 'Amount' => 901, + 'DisplayAmount' => 0, + 'CancelAmount' => 901, + 'MerchantOrderId' => '2023070849CD', + 'FECAmount' => 0, + 'CurrencyCode' => '0949', + 'QeryId' => 0, + 'DebtId' => 0, + 'SurchargeAmount' => 0, + 'SGKDebtAmount' => 0, + 'TransactionSecurity' => 1, + ], + ], + ], + ], + ]; + } + + public static function createStatusRequestDataProvider(): Generator + { + $startDate = new \DateTime('2022-07-08T22:44:31'); + $endDate = new \DateTime('2023-07-08T22:44:31'); + yield [ + 'order' => [ + 'id' => '2023070849CD', + 'currency' => PosInterface::CURRENCY_TRY, + 'start_date' => $startDate, + 'end_date' => $endDate, + ], + 'expected' => [ + 'GetMerchantOrderDetail' => [ + 'request' => [ + 'IsFromExternalNetwork' => true, + 'BusinessKey' => 0, + 'ResourceId' => 0, + 'ActionId' => 0, + 'LanguageId' => 0, + 'CustomerId' => '400235', + 'MailOrTelephoneOrder' => true, + 'Amount' => 0, + 'MerchantId' => '80', + 'OrderId' => 0, + 'TransactionType' => 0, + 'VPosMessage' => [ + 'APIVersion' => KuveytPosRequestDataMapper::API_VERSION, + 'InstallmentMaturityCommisionFlag' => 0, + 'HashData' => 'request-hash', + 'MerchantId' => '80', + 'SubMerchantId' => 0, + 'CustomerId' => '400235', + 'UserName' => 'apiuser', + 'CardType' => 'Visa', + 'BatchID' => 0, + 'TransactionType' => 'GetMerchantOrderDetail', + 'InstallmentCount' => 0, + 'Amount' => 0, + 'DisplayAmount' => 0, + 'CancelAmount' => 0, + 'MerchantOrderId' => '2023070849CD', + 'FECAmount' => 0, + 'CurrencyCode' => '0949', + 'QeryId' => 0, + 'DebtId' => 0, + 'SurchargeAmount' => 0, + 'SGKDebtAmount' => 0, + 'TransactionSecurity' => 1, + ], + 'MerchantOrderId' => '2023070849CD', + 'StartDate' => '2022-07-08T22:44:31', + 'EndDate' => '2023-07-08T22:44:31', + ], + ], + ], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestDataMapper/Param3DHostPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/Param3DHostPosRequestDataMapperTest.php new file mode 100644 index 00000000..c7be72f6 --- /dev/null +++ b/tests/Unit/DataMapper/RequestDataMapper/Param3DHostPosRequestDataMapperTest.php @@ -0,0 +1,382 @@ +account = AccountFactory::createParamPosAccount( + 'param-pos', + 10738, + 'Test1', + 'Test2', + '0c13d406-873b-403b-9c09-a5766840d98c' + ); + + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new ParamPosRequestValueFormatter(); + $this->valueMapper = new ParamPosRequestValueMapper(); + + $this->requestDataMapper = new Param3DHostPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); + } + + public function testSupports(): void + { + $result = $this->requestDataMapper::supports(Param3DHostPos::class); + $this->assertTrue($result); + + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + public function testCreateNonSecurePostAuthPaymentRequestData(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->requestDataMapper->createNonSecurePostAuthPaymentRequestData($this->account, []); + } + + /** + * @dataProvider paymentRegisterRequestDataProvider + */ + public function testCreate3DEnrollmentCheckRequestData(array $order, string $txType, string $soapAction, array $expected): void + { + $soapBody = $expected['soap:Body']; + $this->crypt->expects(self::once()) + ->method('generateRandomString') + ->willReturn($soapBody[$soapAction]['Islem_ID']); + + $actual = $this->requestDataMapper->create3DEnrollmentCheckRequestData( + $this->account, + $order, + $txType + ); + + ksort($actual); + ksort($expected); + ksort($actual['soap:Body'][$soapAction]); + ksort($expected['soap:Body'][$soapAction]); + $this->assertSame($expected, $actual); + } + + public function testCreateNonSecurePaymentRequestData(): void + { + $this->expectException(NotImplementedException::class); + + $this->requestDataMapper->createNonSecurePaymentRequestData( + $this->account, + [], + PosInterface::TX_TYPE_PAY_AUTH, + $this->createMock(CreditCardInterface::class) + ); + } + + public function testCreateCancelRequestData(): void + { + $this->expectException(NotImplementedException::class); + $this->requestDataMapper->createCancelRequestData($this->account, []); + } + + public function testCreateOrderHistoryRequestData(): void + { + $this->expectException(NotImplementedException::class); + $this->requestDataMapper->createOrderHistoryRequestData($this->account, []); + } + + + /** + * @dataProvider threeDFormDataProvider + */ + public function testGet3DFormData( + array $order, + string $txType, + ?string $gatewayURL, + array $extraData, + $expected + ): void { + $this->crypt->expects(self::never()) + ->method('create3DHash'); + + $this->crypt->expects(self::never()) + ->method('generateRandomString'); + + $this->dispatcher->expects(self::never()) + ->method('dispatch'); + + $actual = $this->requestDataMapper->create3DFormData( + $this->account, + $order, + PosInterface::MODEL_3D_HOST, + $txType, + $gatewayURL, + null, + $extraData + ); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider threeDFormDataProviderFail + */ + public function testGet3DFormDataFail( + array $order, + string $txType, + string $paymentModel, + ?string $gatewayURL, + array $extraData, + string $expectedException + ): void { + $this->crypt->expects(self::never()) + ->method('create3DHash'); + + $this->crypt->expects(self::never()) + ->method('generateRandomString'); + + $this->dispatcher->expects(self::never()) + ->method('dispatch'); + + $this->expectException($expectedException); + + $this->requestDataMapper->create3DFormData( + $this->account, + $order, + $paymentModel, + $txType, + $gatewayURL, + null, + $extraData + ); + } + + public function testCreateStatusRequestData(): void + { + $this->expectException(NotImplementedException::class); + $this->requestDataMapper->createStatusRequestData($this->account, []); + } + + public function testCreateRefundRequestData(): void + { + $this->expectException(NotImplementedException::class); + $this->requestDataMapper->createRefundRequestData($this->account, [], PosInterface::TX_TYPE_REFUND); + } + + public function testCreate3DPaymentRequestData(): void + { + $this->expectException(NotImplementedException::class); + $this->requestDataMapper->create3DPaymentRequestData( + $this->account, + [], + PosInterface::TX_TYPE_PAY_AUTH, + [] + ); + } + + public function testCreateHistoryRequestData(): void + { + $this->expectException(NotImplementedException::class); + $this->requestDataMapper->createHistoryRequestData($this->account, []); + } + + public function testCreateCustomQueryRequestData(): void + { + $this->expectException(NotImplementedException::class); + $this->requestDataMapper->createCustomQueryRequestData($this->account, []); + } + + public static function paymentRegisterRequestDataProvider(): array + { + $order = [ + 'id' => 'order222', + 'amount' => 1000.25, + 'installment' => 0, + 'currency' => PosInterface::CURRENCY_TRY, + 'ip' => '127.0.0.1', + 'success_url' => 'https://domain.com/success', + 'fail_url' => 'https://domain.com/fail', + ]; + + return [ + '3d_host' => [ + 'order' => $order, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'soapAction' => 'TO_Pre_Encrypting_OOS', + 'expected' => [ + 'soap:Body' => [ + 'TO_Pre_Encrypting_OOS' => [ + '@xmlns' => 'https://turkodeme.com.tr/', + 'Borclu_Aciklama' => 'r|', + 'Borclu_AdSoyad' => 'r|', + 'Borclu_GSM' => 'r|', + 'Borclu_Kisi_TC' => '', + 'Borclu_Odeme_Tip' => 'r|Diğer', + 'Borclu_Tutar' => 'r|1000,25', + 'Islem_ID' => 'rand', + 'Return_URL' => 'r|https://domain.com/success', + 'Taksit' => '1', + 'Terminal_ID' => '10738', + ], + ], + 'soap:Header' => [ + 'ServiceSecuritySoapHeader' => [ + '@xmlns' => 'https://turkodeme.com.tr/', + 'CLIENT_CODE' => '10738', + 'CLIENT_USERNAME' => 'Test1', + 'CLIENT_PASSWORD' => 'Test2', + ], + ], + ], + ], + '3d_host_foreign_currency' => [ + 'order' => [ + 'id' => 'order222', + 'amount' => 1000.25, + 'installment' => 0, + 'currency' => PosInterface::CURRENCY_EUR, + 'ip' => '127.0.0.1', + 'success_url' => 'https://domain.com/success', + 'fail_url' => 'https://domain.com/fail', + ], + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'soapAction' => 'TO_Pre_Encrypting_OOS', + 'expected' => [ + 'soap:Body' => [ + 'TO_Pre_Encrypting_OOS' => [ + '@xmlns' => 'https://turkodeme.com.tr/', + 'Borclu_Aciklama' => 'r|', + 'Borclu_AdSoyad' => 'r|', + 'Borclu_GSM' => 'r|', + 'Borclu_Kisi_TC' => '', + 'Borclu_Odeme_Tip' => 'r|Diğer', + 'Borclu_Tutar' => 'r|1000,25', + 'Doviz_Kodu' => '1002', + 'Islem_ID' => 'rand', + 'Return_URL' => 'r|https://domain.com/success', + 'Taksit' => '1', + 'Terminal_ID' => '10738', + ], + ], + 'soap:Header' => [ + 'ServiceSecuritySoapHeader' => [ + '@xmlns' => 'https://turkodeme.com.tr/', + 'CLIENT_CODE' => '10738', + 'CLIENT_USERNAME' => 'Test1', + 'CLIENT_PASSWORD' => 'Test2', + ], + ], + ], + ], + ]; + } + + public static function threeDFormDataProvider(): array + { + return [ + '3d_host_form_data' => [ + 'order' => [], + 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, + 'gateway' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', + 'extra_data' => [ + 'TO_Pre_Encrypting_OOSResponse' => [ + 'TO_Pre_Encrypting_OOSResult' => 'JHnDLmT5yierHIqsHNRU2SR7HLxOpi8o7Eb/oVSiIf35v+Z1uzteqid4wop8SAuykWNFElYyAxGWcIGvTxmhSljuLTcJ3xDMkS3O0jUboNpl5ad6roy/92lDftpV535KmpbxMxStRa+qGT7Tk4BdEIf+Jobr2o1Yl1+ZakWZ+parsTgnodyWl432Hsv2FUNLhuU7H6folMwleaZFPYdFZ+bO1T95opw5pnDWcFkrIuPfAmVRg4cg+al22FQSN/58AXxWBb8jEPrqn+/ojZ+WqncGvw+NB/Mtv9iCDuF+SNQqRig2dRILzWYwcvNxzj/OxcYuNuvO8wYI/iF1kNBBNtaExIunWZyj1tntGeb7UUaDmHD4LmSMUMpgZGugRfUpxm8WL/EE+PnUkLXE7SOG3g==', + ], + ], + 'expected' => [ + 'gateway' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', + 'method' => 'GET', + 'inputs' => [ + 's' => 'JHnDLmT5yierHIqsHNRU2SR7HLxOpi8o7Eb/oVSiIf35v+Z1uzteqid4wop8SAuykWNFElYyAxGWcIGvTxmhSljuLTcJ3xDMkS3O0jUboNpl5ad6roy/92lDftpV535KmpbxMxStRa+qGT7Tk4BdEIf+Jobr2o1Yl1+ZakWZ+parsTgnodyWl432Hsv2FUNLhuU7H6folMwleaZFPYdFZ+bO1T95opw5pnDWcFkrIuPfAmVRg4cg+al22FQSN/58AXxWBb8jEPrqn+/ojZ+WqncGvw+NB/Mtv9iCDuF+SNQqRig2dRILzWYwcvNxzj/OxcYuNuvO8wYI/iF1kNBBNtaExIunWZyj1tntGeb7UUaDmHD4LmSMUMpgZGugRfUpxm8WL/EE+PnUkLXE7SOG3g==', + ], + ], + ], + ]; + } + + public static function threeDFormDataProviderFail(): array + { + return [ + '3d_host_form_data' => [ + 'order' => [], + 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, + 'payment_model' => PosInterface::MODEL_3D_HOST, + 'gateway' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', + 'extra_data' => [ + 'TO_Pre_Encrypting_OOSResponse' => [ + 'TO_Pre_Encrypting_OOSResult' => 'SOAP Güvenlik Hatası.192.168.190.2', + ], + ], + 'expected_exception' => \RuntimeException::class, + ], + 'non_3d_host_form_data' => [ + 'order' => [], + 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, + 'payment_model' => PosInterface::MODEL_3D_SECURE, + 'gateway' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', + 'extra_data' => [ + 'TO_Pre_Encrypting_OOSResponse' => [ + 'TO_Pre_Encrypting_OOSResult' => 'SOAP Güvenlik Hatası.192.168.190.2', + ], + ], + 'expected_exception' => \InvalidArgumentException::class, + ], + '3d_host_without_gateway_url' => [ + 'order' => [], + 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, + 'payment_model' => PosInterface::MODEL_3D_HOST, + 'gateway' => null, + 'extra_data' => [ + 'TO_Pre_Encrypting_OOSResponse' => [ + 'TO_Pre_Encrypting_OOSResult' => 'SOAP Güvenlik Hatası.192.168.190.2', + ], + ], + 'expected_exception' => \InvalidArgumentException::class, + ], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestDataMapper/ParamPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/ParamPosRequestDataMapperTest.php index 2fb55120..99629a6b 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/ParamPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/ParamPosRequestDataMapperTest.php @@ -8,12 +8,15 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\ParamPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\ParamPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\ParamPosRequestValueMapper; use Mews\Pos\Entity\Account\ParamPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Exceptions\NotImplementedException; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\ParamPos; use Mews\Pos\PosInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\ParamPosResponseDataMapperTest; use PHPUnit\Framework\MockObject\MockObject; @@ -36,6 +39,10 @@ class ParamPosRequestDataMapperTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private EventDispatcherInterface $dispatcher; + private ParamPosRequestValueFormatter $valueFormatter; + + private ParamPosRequestValueMapper $valueMapper; + private ParamPosRequestDataMapper $requestDataMapper; public static function setUpBeforeClass(): void @@ -55,73 +62,27 @@ protected function setUp(): void '0c13d406-873b-403b-9c09-a5766840d98c' ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new ParamPosRequestDataMapper($this->dispatcher, $this->crypt); - } - - /** - * @testWith ["1"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @testWith ["pre", null] - */ - public function testMapTxTypeInvArgException(string $txType, ?string $paymentModel): void - { - $this->expectException(\InvalidArgumentException::class); - $this->requestDataMapper->mapTxType($txType, $paymentModel); - } - - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('1000', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('1001', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_USD])); - $this->assertSame('1002', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new ParamPosRequestValueFormatter(); + $this->valueMapper = new ParamPosRequestValueMapper(); + + $this->requestDataMapper = new ParamPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); } - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "1"] - * ["1", "1"] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void + public function testSupports(): void { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); - } + $result = $this->requestDataMapper::supports(ParamPos::class); + $this->assertTrue($result); - /** - * @testWith [10.0, "10,00"] - * [1000.0, "1000,00"] - * [1000.5, "1000,50"] - */ - public function testFormatAmount(float $amount, string $formattedAmount): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame($formattedAmount, $method->invokeArgs($this->requestDataMapper, [$amount])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -138,27 +99,25 @@ public function testCreateNonSecurePostAuthPaymentRequestData(array $order, arra */ public function testCreate3DEnrollmentCheckRequestData(array $order, string $paymentModel, string $txType, ?CreditCardInterface $card, string $soapAction, array $expected): void { - $requestDataWithoutHash = $expected; $soapBody = $expected['soap:Body']; $this->crypt->expects(self::once()) ->method('generateRandomString') ->willReturn($soapBody[$soapAction]['Islem_ID']); - if (PosInterface::MODEL_3D_HOST !== $paymentModel) { - unset($requestDataWithoutHash['soap:Body'][$soapAction]['Islem_Hash']); - $this->crypt->expects(self::once()) - ->method('createHash') - ->with($this->account, $this->callback(function (array $actual) use ($requestDataWithoutHash, $soapAction): bool { - $expected = $requestDataWithoutHash['soap:Body']; - ksort($actual[$soapAction]); - ksort($expected[$soapAction]); - $this->assertSame($expected, $actual); - - return true; - })) - ->willReturn($soapBody[$soapAction]['Islem_Hash']); - } + + unset($requestDataWithoutHash['soap:Body'][$soapAction]['Islem_Hash']); + $this->crypt->expects(self::once()) + ->method('createHash') + ->with($this->account, $this->callback(function (array $actual) use ($requestDataWithoutHash, $soapAction): bool { + $expected = $requestDataWithoutHash['soap:Body']; + ksort($actual[$soapAction]); + ksort($expected[$soapAction]); + $this->assertSame($expected, $actual); + + return true; + })) + ->willReturn($soapBody[$soapAction]['Islem_Hash']); $actual = $this->requestDataMapper->create3DEnrollmentCheckRequestData( $this->account, @@ -292,13 +251,13 @@ public function testGet3DFormData( * @dataProvider threeDFormDataProviderFail */ public function testGet3DFormDataFail( - array $order, - string $txType, - string $paymentModel, - bool $withCard, + array $order, + string $txType, + string $paymentModel, + bool $withCard, ?string $gatewayURL, - array $extraData, - string $expectedException + array $extraData, + string $expectedException ): void { $card = $withCard ? self::$card : null; @@ -586,7 +545,7 @@ public static function cancelRequestDataProvider(): array '@xmlns' => 'https://turkpos.com.tr/', 'Durum' => 'IPTAL', 'Siparis_ID' => 'id-12', - 'Tutar' => 10.0, + 'Tutar' => '10.00', ], ], ], @@ -639,7 +598,7 @@ public static function refundRequestDataProvider(): array '@xmlns' => 'https://turkpos.com.tr/', 'Durum' => 'IADE', 'Siparis_ID' => 'id-12', - 'Tutar' => 1.02, + 'Tutar' => '1.02', ], ], ], @@ -662,79 +621,6 @@ public static function paymentRegisterRequestDataProvider(): array $card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet', CreditCardInterface::CARD_TYPE_VISA); return [ - '3d_host' => [ - 'order' => $order, - 'paymentModel' => PosInterface::MODEL_3D_HOST, - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'card' => null, - 'soapAction' => 'TO_Pre_Encrypting_OOS', - 'expected' => [ - 'soap:Body' => [ - 'TO_Pre_Encrypting_OOS' => [ - '@xmlns' => 'https://turkodeme.com.tr/', - 'Borclu_Aciklama' => 'r|', - 'Borclu_AdSoyad' => 'r|', - 'Borclu_GSM' => 'r|', - 'Borclu_Kisi_TC' => '', - 'Borclu_Odeme_Tip' => 'r|Diğer', - 'Borclu_Tutar' => 'r|1000,25', - 'Islem_ID' => 'rand', - 'Return_URL' => 'r|https://domain.com/success', - 'Taksit' => '1', - 'Terminal_ID' => '10738', - ], - ], - 'soap:Header' => [ - 'ServiceSecuritySoapHeader' => [ - '@xmlns' => 'https://turkodeme.com.tr/', - 'CLIENT_CODE' => '10738', - 'CLIENT_USERNAME' => 'Test1', - 'CLIENT_PASSWORD' => 'Test2', - ], - ], - ], - ], - '3d_host_foreign_currency' => [ - 'order' => [ - 'id' => 'order222', - 'amount' => 1000.25, - 'installment' => 0, - 'currency' => PosInterface::CURRENCY_EUR, - 'ip' => '127.0.0.1', - 'success_url' => 'https://domain.com/success', - 'fail_url' => 'https://domain.com/fail', - ], - 'paymentModel' => PosInterface::MODEL_3D_HOST, - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'card' => null, - 'soapAction' => 'TO_Pre_Encrypting_OOS', - 'expected' => [ - 'soap:Body' => [ - 'TO_Pre_Encrypting_OOS' => [ - '@xmlns' => 'https://turkodeme.com.tr/', - 'Borclu_Aciklama' => 'r|', - 'Borclu_AdSoyad' => 'r|', - 'Borclu_GSM' => 'r|', - 'Borclu_Kisi_TC' => '', - 'Borclu_Odeme_Tip' => 'r|Diğer', - 'Borclu_Tutar' => 'r|1000,25', - 'Doviz_Kodu' => '1002', - 'Islem_ID' => 'rand', - 'Return_URL' => 'r|https://domain.com/success', - 'Taksit' => '1', - 'Terminal_ID' => '10738', - ], - ], - 'soap:Header' => [ - 'ServiceSecuritySoapHeader' => [ - '@xmlns' => 'https://turkodeme.com.tr/', - 'CLIENT_CODE' => '10738', - 'CLIENT_USERNAME' => 'Test1', - 'CLIENT_PASSWORD' => 'Test2', - ], - ], - ], - ], [ 'order' => $order, 'paymentModel' => PosInterface::MODEL_3D_SECURE, @@ -964,7 +850,6 @@ public static function paymentRegisterRequestDataProviderException(): array ]; return [ - '3d_secure_without_card' => [ 'order' => $order, 'paymentModel' => PosInterface::MODEL_3D_SECURE, @@ -972,6 +857,13 @@ public static function paymentRegisterRequestDataProviderException(): array 'card' => null, 'expected_exception_class' => \InvalidArgumentException::class, ], + '3d_host' => [ + 'order' => $order, + 'paymentModel' => PosInterface::MODEL_3D_HOST, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'card' => null, + 'expected_exception_class' => \InvalidArgumentException::class, + ], ]; } @@ -1128,25 +1020,6 @@ public static function nonSecurePaymentPostRequestDataProvider(): array public static function threeDFormDataProvider(): array { return [ - '3d_host_form_data' => [ - 'order' => [], - 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, - 'payment_model' => PosInterface::MODEL_3D_HOST, - 'is_with_card' => false, - 'gateway' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', - 'extra_data' => [ - 'TO_Pre_Encrypting_OOSResponse' => [ - 'TO_Pre_Encrypting_OOSResult' => 'JHnDLmT5yierHIqsHNRU2SR7HLxOpi8o7Eb/oVSiIf35v+Z1uzteqid4wop8SAuykWNFElYyAxGWcIGvTxmhSljuLTcJ3xDMkS3O0jUboNpl5ad6roy/92lDftpV535KmpbxMxStRa+qGT7Tk4BdEIf+Jobr2o1Yl1+ZakWZ+parsTgnodyWl432Hsv2FUNLhuU7H6folMwleaZFPYdFZ+bO1T95opw5pnDWcFkrIuPfAmVRg4cg+al22FQSN/58AXxWBb8jEPrqn+/ojZ+WqncGvw+NB/Mtv9iCDuF+SNQqRig2dRILzWYwcvNxzj/OxcYuNuvO8wYI/iF1kNBBNtaExIunWZyj1tntGeb7UUaDmHD4LmSMUMpgZGugRfUpxm8WL/EE+PnUkLXE7SOG3g==', - ], - ], - 'expected' => [ - 'gateway' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', - 'method' => 'GET', - 'inputs' => [ - 's' => 'JHnDLmT5yierHIqsHNRU2SR7HLxOpi8o7Eb/oVSiIf35v+Z1uzteqid4wop8SAuykWNFElYyAxGWcIGvTxmhSljuLTcJ3xDMkS3O0jUboNpl5ad6roy/92lDftpV535KmpbxMxStRa+qGT7Tk4BdEIf+Jobr2o1Yl1+ZakWZ+parsTgnodyWl432Hsv2FUNLhuU7H6folMwleaZFPYdFZ+bO1T95opw5pnDWcFkrIuPfAmVRg4cg+al22FQSN/58AXxWBb8jEPrqn+/ojZ+WqncGvw+NB/Mtv9iCDuF+SNQqRig2dRILzWYwcvNxzj/OxcYuNuvO8wYI/iF1kNBBNtaExIunWZyj1tntGeb7UUaDmHD4LmSMUMpgZGugRfUpxm8WL/EE+PnUkLXE7SOG3g==', - ], - ], - ], '3d_secure_form_data' => [ 'order' => [ 'currency' => PosInterface::CURRENCY_TRY, @@ -1253,7 +1126,7 @@ public static function threeDFormDataProvider(): array ], ], ], - '3d_pay_with_port_in_url' => [ + '3d_pay_with_port_in_url' => [ 'order' => [ 'currency' => PosInterface::CURRENCY_TRY, ], @@ -1299,28 +1172,15 @@ public static function threeDFormDataProviderFail(): array 'TO_Pre_Encrypting_OOSResult' => 'SOAP Güvenlik Hatası.192.168.190.2', ], ], - 'expected_exception' => \RuntimeException::class, - ], - '3d_host_without_gateway_url' => [ - 'order' => [], - 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, - 'payment_model' => PosInterface::MODEL_3D_HOST, - 'is_with_card' => false, - 'gateway' => null, - 'extra_data' => [ - 'TO_Pre_Encrypting_OOSResponse' => [ - 'TO_Pre_Encrypting_OOSResult' => 'SOAP Güvenlik Hatası.192.168.190.2', - ], - ], 'expected_exception' => \InvalidArgumentException::class, ], - '3d_pay_invalid_url' => [ + '3d_pay_invalid_url' => [ 'order' => [], 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, 'payment_model' => PosInterface::MODEL_3D_PAY, 'is_with_card' => false, 'gateway' => null, - 'extra_data' => [ + 'extra_data' => [ 'Pos_OdemeResponse' => [ 'Pos_OdemeResult' => [ 'UCD_URL' => 'SOAP Güvenlik Hatası.192.168.190.2', @@ -1329,13 +1189,13 @@ public static function threeDFormDataProviderFail(): array ], 'expected_exception' => \InvalidArgumentException::class, ], - '3d_pay_no_query_params_in_url' => [ + '3d_pay_no_query_params_in_url' => [ 'order' => [], 'tx_type' => PosInterface::TX_TYPE_PAY_AUTH, 'payment_model' => PosInterface::MODEL_3D_PAY, 'is_with_card' => false, 'gateway' => null, - 'extra_data' => [ + 'extra_data' => [ 'Pos_OdemeResponse' => [ 'Pos_OdemeResult' => [ 'UCD_URL' => 'https://test-pos.param.com.tr/3D_Secure/AkilliKart_3DPay_PFO.aspx', diff --git a/tests/Unit/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapperTest.php index 89b4ae01..ead2d744 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/PayFlexCPV4PosRequestDataMapperTest.php @@ -8,13 +8,16 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PayFlexCPV4PosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\PayFlexCPV4PosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\PayFlexCPV4PosRequestValueMapper; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PayFlexAccount; use Mews\Pos\Entity\Card\CreditCard; use Mews\Pos\Entity\Card\CreditCardInterface; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\PayFlexCPV4Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -36,6 +39,10 @@ class PayFlexCPV4PosRequestDataMapperTest extends TestCase /** @var CryptInterface & MockObject */ private CryptInterface $crypt; + private PayFlexCPV4PosRequestValueFormatter $valueFormatter; + + private PayFlexCPV4PosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -48,70 +55,27 @@ protected function setUp(): void PosInterface::MODEL_3D_SECURE ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new PayFlexCPV4PosRequestDataMapper($this->dispatcher, $this->crypt); - } - - /** - * @testWith ["pay", "Sale"] - * ["pre", "Auth"] - */ - public function testMapTxType(string $txType, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["Sale"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame('1000.00', $method->invokeArgs($this->requestDataMapper, [1000])); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new PayFlexCPV4PosRequestValueFormatter(); + $this->valueMapper = new PayFlexCPV4PosRequestValueMapper(); + + $this->requestDataMapper = new PayFlexCPV4PosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); } - /** - * @return void - */ - public function testMapCurrency(): void + public function testSupports(): void { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } + $result = $this->requestDataMapper::supports(PayFlexCPV4Pos::class); + $this->assertTrue($result); - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "0"] - * ["1", "0"] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -311,7 +275,7 @@ public static function registerDataProvider(): iterable 'AllowNotEnrolledCard' => 'false', 'SuccessUrl' => 'https://domain.com/success', 'FailUrl' => 'https://domain.com/fail_url', - 'RequestLanguage' => 'tr-TR', + 'RequestLanguage' => 'en-US', 'Extract' => '', 'CustomItems' => '', 'BrandNumber' => '100', @@ -343,7 +307,7 @@ public static function registerDataProvider(): iterable 'AllowNotEnrolledCard' => 'false', 'SuccessUrl' => 'https://domain.com/success', 'FailUrl' => 'https://domain.com/fail_url', - 'RequestLanguage' => 'tr-TR', + 'RequestLanguage' => 'en-US', 'Extract' => '', 'CustomItems' => '', 'InstallmentCount' => '2', diff --git a/tests/Unit/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapperTest.php index b9e2b140..ff8deae0 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/PayFlexV4PosRequestDataMapperTest.php @@ -8,13 +8,16 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PayFlexV4PosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\PayFlexV4PosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\PayFlexV4PosRequestValueMapper; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PayFlexAccount; use Mews\Pos\Entity\Card\CreditCard; use Mews\Pos\Entity\Card\CreditCardInterface; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\PayFlexV4Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -36,6 +39,10 @@ class PayFlexV4PosRequestDataMapperTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private EventDispatcherInterface $dispatcher; + private PayFlexV4PosRequestValueFormatter $valueFormatter; + + private PayFlexV4PosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -48,82 +55,27 @@ protected function setUp(): void PosInterface::MODEL_3D_SECURE ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new PayFlexV4PosRequestDataMapper($this->dispatcher, $this->crypt); - } - - /** - * @testWith ["pay", "Sale"] - * ["pre", "Auth"] - */ - public function testMapTxType(string $txType, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["Sale"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame('1000.00', $method->invokeArgs($this->requestDataMapper, [1000])); - } - - /** - * @testWith ["MONTH", "Month"] - * ["Month", "Month"] - */ - public function testMapRecurringFrequency(string $frequency, string $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapRecurringFrequency'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$frequency])); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new PayFlexV4PosRequestValueFormatter(); + $this->valueMapper = new PayFlexV4PosRequestValueMapper(); + + $this->requestDataMapper = new PayFlexV4PosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); } - /** - * @return void - */ - public function testMapCurrency(): void + public function testSupports(): void { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } + $result = $this->requestDataMapper::supports(PayFlexV4Pos::class); + $this->assertTrue($result); - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "0"] - * ["1", "0"] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** diff --git a/tests/Unit/DataMapper/RequestDataMapper/PayForPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/PayForPosRequestDataMapperTest.php index 987d3add..f69931d2 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/PayForPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/PayForPosRequestDataMapperTest.php @@ -8,12 +8,14 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PayForPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\PayForPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\PayForPosRequestValueMapper; use Mews\Pos\Entity\Account\PayForAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\Before3DFormHashCalculatedEvent; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\Gateways\PayForPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; @@ -40,6 +42,10 @@ class PayForPosRequestDataMapperTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private EventDispatcherInterface $dispatcher; + private PayForPosRequestValueFormatter $valueFormatter; + + private PayForPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -51,7 +57,6 @@ protected function setUp(): void 'UcBN0', PosInterface::MODEL_3D_SECURE, '12345678', - PosInterface::LANG_TR, PayForAccount::MBR_ID_FINANSBANK ); @@ -62,65 +67,32 @@ protected function setUp(): void 'UcBN0', PosInterface::MODEL_3D_SECURE, '12345678', - PosInterface::LANG_TR, PayForAccount::MBR_ID_ZIRAAT_KATILIM ); - $this->crypt = $this->createMock(CryptInterface::class); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->valueFormatter = new PayForPosRequestValueFormatter(); + $this->valueMapper = new PayForPosRequestValueMapper(); + + $this->requestDataMapper = new PayForPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); - $this->requestDataMapper = new PayForPosRequestDataMapper($this->dispatcher, $this->crypt); - $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet'); + $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet'); } - /** - * @testWith ["pay", "Auth"] - * ["pre", "PreAuth"] - */ - public function testMapTxType(string $txType, string $expected): void + public function testSupports(): void { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } + $result = $this->requestDataMapper::supports(PayForPos::class); + $this->assertTrue($result); - /** - * @testWith ["PreAuth"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } - - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "0"] - * ["1", "0"] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -383,7 +355,7 @@ public static function createCancelRequestDataDataProvider(): array 'SecureType' => 'NonSecure', 'TxnType' => 'Void', 'Currency' => '949', - 'Lang' => 'tr', + 'Lang' => 'en', ], ], [ @@ -401,7 +373,7 @@ public static function createCancelRequestDataDataProvider(): array 'SecureType' => 'NonSecure', 'TxnType' => 'Void', 'Currency' => '949', - 'Lang' => 'tr', + 'Lang' => 'en', ], ], ]; @@ -417,6 +389,33 @@ public static function nonSecurePaymentRequestDataProvider(): array 'amount' => 100.01, ], 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'expected' => [ + 'MerchantId' => '085300000009704', + 'UserCode' => 'QNB_API_KULLANICI_3DPAY', + 'UserPass' => 'UcBN0', + 'MbrId' => '5', + 'MOTO' => '0', + 'OrderId' => '2020110828BC', + 'SecureType' => 'NonSecure', + 'TxnType' => 'Auth', + 'PurchAmount' => '100.01', + 'Currency' => '949', + 'InstallmentCount' => '0', + 'Lang' => 'en', + 'CardHolderName' => 'ahmet', + 'Pan' => '5555444433332222', + 'Expiry' => '0122', + 'Cvv2' => '123', + ], + ], + 'lang_tr' => [ + 'account' => 'finansbank', + 'order' => [ + 'id' => '2020110828BC', + 'amount' => 100.01, + 'lang' => PosInterface::LANG_TR, + ], + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'expected' => [ 'MerchantId' => '085300000009704', 'UserCode' => 'QNB_API_KULLANICI_3DPAY', @@ -455,7 +454,7 @@ public static function nonSecurePaymentRequestDataProvider(): array 'PurchAmount' => '100.01', 'Currency' => '949', 'InstallmentCount' => '0', - 'Lang' => 'tr', + 'Lang' => 'en', 'CardHolderName' => 'ahmet', 'Pan' => '5555444433332222', 'Expiry' => '0122', @@ -472,7 +471,6 @@ public static function createNonSecurePostAuthPaymentRequestDataDataProvider(): 'amount' => 100.01, 'installment' => 0, 'currency' => PosInterface::CURRENCY_TRY, - 'lang' => PosInterface::LANG_TR, ]; return [ @@ -489,7 +487,7 @@ public static function createNonSecurePostAuthPaymentRequestDataDataProvider(): 'TxnType' => 'PostAuth', 'PurchAmount' => '100.01', 'Currency' => '949', - 'Lang' => 'tr', + 'Lang' => 'en', ], ], [ @@ -505,7 +503,7 @@ public static function createNonSecurePostAuthPaymentRequestDataDataProvider(): 'TxnType' => 'PostAuth', 'PurchAmount' => '100.01', 'Currency' => '949', - 'Lang' => 'tr', + 'Lang' => 'en', ], ], ]; @@ -527,7 +525,7 @@ public static function createStatusRequestDataDataProvider(): array 'MbrId' => '5', 'OrgOrderId' => '2020110828BC', 'SecureType' => 'Inquiry', - 'Lang' => 'tr', + 'Lang' => 'en', 'TxnType' => 'OrderInquiry', ], ], @@ -543,7 +541,7 @@ public static function createStatusRequestDataDataProvider(): array 'MbrId' => '12', 'OrgOrderId' => '2020110828BC', 'SecureType' => 'Inquiry', - 'Lang' => 'tr', + 'Lang' => 'en', 'TxnType' => 'OrderInquiry', ], ], @@ -565,7 +563,7 @@ public static function orderHistoryRequestDataProvider(): array 'MbrId' => '5', 'SecureType' => 'Report', 'TxnType' => 'TxnHistory', - 'Lang' => 'tr', + 'Lang' => 'en', 'OrderId' => '2020110828BC', ], ], @@ -581,7 +579,7 @@ public static function orderHistoryRequestDataProvider(): array 'MbrId' => '12', 'SecureType' => 'Report', 'TxnType' => 'TxnHistory', - 'Lang' => 'tr', + 'Lang' => 'en', 'OrderId' => '2020110828BC', ], ], @@ -603,7 +601,7 @@ public static function historyRequestDataProvider(): array 'MbrId' => '5', 'SecureType' => 'Report', 'TxnType' => 'TxnHistory', - 'Lang' => 'tr', + 'Lang' => 'en', 'ReqDate' => '20220518', ], ], @@ -619,7 +617,7 @@ public static function historyRequestDataProvider(): array 'MbrId' => '12', 'SecureType' => 'Report', 'TxnType' => 'TxnHistory', - 'Lang' => 'tr', + 'Lang' => 'en', 'ReqDate' => '20220518', ], ], @@ -775,7 +773,7 @@ public static function refundRequestDataProvider(): array 'txType' => PosInterface::TX_TYPE_REFUND, 'expected' => [ 'Currency' => '949', - 'Lang' => 'tr', + 'Lang' => 'en', 'MbrId' => '5', 'MerchantId' => '085300000009704', 'OrgOrderId' => '7022b92e-3aa1-44fb-86d4-33658c700c80', @@ -796,7 +794,7 @@ public static function refundRequestDataProvider(): array 'txType' => PosInterface::TX_TYPE_REFUND, 'expected' => [ 'Currency' => '949', - 'Lang' => 'tr', + 'Lang' => 'en', 'MbrId' => '12', 'MerchantId' => '085300000009704', 'OrgOrderId' => '7022b92e-3aa1-44fb-86d4-33658c700c80', @@ -817,7 +815,7 @@ public static function refundRequestDataProvider(): array 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, 'expected' => [ 'Currency' => '949', - 'Lang' => 'tr', + 'Lang' => 'en', 'MbrId' => '5', 'MerchantId' => '085300000009704', 'OrgOrderId' => '7022b92e-3aa1-44fb-86d4-33658c700c80', diff --git a/tests/Unit/DataMapper/RequestDataMapper/PosNetRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/PosNetRequestDataMapperTest.php index 50f9871d..d3f1057f 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/PosNetRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/PosNetRequestDataMapperTest.php @@ -9,11 +9,14 @@ use InvalidArgumentException; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PosNetRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\PosNetRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\PosNetRequestValueMapper; use Mews\Pos\Entity\Account\PosNetAccount; use Mews\Pos\Entity\Card\CreditCardInterface; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\PosNet; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -39,6 +42,10 @@ class PosNetRequestDataMapperTest extends TestCase /** @var CryptInterface & MockObject */ private CryptInterface $crypt; + private PosNetRequestValueFormatter $valueFormatter; + + private PosNetRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -62,102 +69,29 @@ protected function setUp(): void 'lang' => PosInterface::LANG_TR, ]; - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new PosNetRequestDataMapper($this->dispatcher, $this->crypt); - $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet'); - } - - /** - * @testWith ["pay", "Sale"] - * ["pre", "Auth"] - */ - public function testMapTxType(string $txType, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["Auth"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('TL', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('EU', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } - - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame(100000, $method->invokeArgs($this->requestDataMapper, [1000])); - $this->assertSame(100000, $method->invokeArgs($this->requestDataMapper, [1000.00])); - $this->assertSame(100001, $method->invokeArgs($this->requestDataMapper, [1000.01])); - } + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new PosNetRequestValueFormatter(); + $this->valueMapper = new PosNetRequestValueMapper(); + + $this->requestDataMapper = new PosNetRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "00"] - * ["1", "00"] - * ["2", "02"] - * ["12", "12"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet'); } - /** - * @return void - */ - public function testMapOrderIdToPrefixedOrderId(): void + public function testSupports(): void { - $this->assertSame('TDSC00000000000000000010', PosNetRequestDataMapper::mapOrderIdToPrefixedOrderId(10, PosInterface::MODEL_3D_SECURE)); - $this->assertSame('000000000000000000000010', PosNetRequestDataMapper::mapOrderIdToPrefixedOrderId(10, PosInterface::MODEL_3D_PAY)); - $this->assertSame('000000000000000000000010', PosNetRequestDataMapper::mapOrderIdToPrefixedOrderId(10, PosInterface::MODEL_NON_SECURE)); - } + $result = $this->requestDataMapper::supports(PosNet::class); + $this->assertTrue($result); - /** - * @return void - */ - public function testFormatOrderId(): void - { - $this->assertSame('0010', PosNetRequestDataMapper::formatOrderId(10, 4)); - $this->assertSame('12345', PosNetRequestDataMapper::formatOrderId(12345, 5)); - $this->assertSame('123456789012345566fm', PosNetRequestDataMapper::formatOrderId('123456789012345566fm')); - } - - /** - * @return void - */ - public function testFormatOrderIdFail(): void - { - $this->expectException(InvalidArgumentException::class); - PosNetRequestDataMapper::formatOrderId('123456789012345566fml'); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -389,7 +323,7 @@ public static function createCustomQueryRequestDataDataProvider(): \Generator public static function threeDFormDataDataProvider(): array { return [ - [ + 'success1' => [ 'enrollment_check_response' => [ 'approved' => '1', //1:Başarılı 'respCode' => '', @@ -417,7 +351,7 @@ public static function threeDFormDataDataProvider(): array 'digest' => '9998F61E1D0C0FB6EC5203A748124F30', 'merchantReturnURL' => 'https://domain.com/success', 'url' => '', - 'lang' => 'tr', + 'lang' => 'en', ], ], ], diff --git a/tests/Unit/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapperTest.php index 95fcf4f1..75abe40e 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/PosNetV1PosRequestDataMapperTest.php @@ -6,15 +6,16 @@ namespace Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper; -use InvalidArgumentException; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PosNetV1PosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\PosNetV1PosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\PosNetV1PosRequestValueMapper; use Mews\Pos\Entity\Account\PosNetAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\Before3DFormHashCalculatedEvent; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\Gateways\PosNetV1Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; @@ -39,6 +40,10 @@ class PosNetV1PosRequestDataMapperTest extends TestCase /** @var CryptInterface & MockObject */ private CryptInterface $crypt; + private PosNetV1PosRequestValueFormatter $valueFormatter; + + private PosNetV1PosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -52,104 +57,29 @@ protected function setUp(): void '10,10,10,10,10,10,10,10' ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new PosNetV1PosRequestValueFormatter(); + $this->valueMapper = new PosNetV1PosRequestValueMapper(); + + $this->requestDataMapper = new PosNetV1PosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); $this->card = CreditCardFactory::create('5400619360964581', '20', '01', '056', 'ahmet'); - - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new PosNetV1PosRequestDataMapper($this->dispatcher, $this->crypt); - } - - /** - * @testWith ["pay", "Sale"] - * ["pre", "Auth"] - */ - public function testMapTxType(string $txType, string $expected): void - { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } - - /** - * @testWith ["Auth"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('TL', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('EU', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } - - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame(100000, $method->invokeArgs($this->requestDataMapper, [1000])); - $this->assertSame(100000, $method->invokeArgs($this->requestDataMapper, [1000.00])); - $this->assertSame(100001, $method->invokeArgs($this->requestDataMapper, [1000.01])); - } - - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "0"] - * ["1", "0"] - * ["2", "2"] - * ["12", "12"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); - } - - /** - * @return void - */ - public function testMapOrderIdToPrefixedOrderId(): void - { - $this->assertSame('TDS_00000000000000000010', $this->requestDataMapper::mapOrderIdToPrefixedOrderId(10, PosInterface::MODEL_3D_SECURE)); - $this->assertSame('000000000000000000000010', $this->requestDataMapper::mapOrderIdToPrefixedOrderId(10, PosInterface::MODEL_3D_PAY)); - $this->assertSame('000000000000000000000010', $this->requestDataMapper::mapOrderIdToPrefixedOrderId(10, PosInterface::MODEL_NON_SECURE)); } - /** - * @return void - */ - public function testFormatOrderId(): void + public function testSupports(): void { - $this->assertSame('0010', $this->requestDataMapper::formatOrderId(10, 4)); - $this->assertSame('12345', $this->requestDataMapper::formatOrderId(12345, 5)); - $this->assertSame('123456789012345566fm', $this->requestDataMapper::formatOrderId('123456789012345566fm')); - } + $result = $this->requestDataMapper::supports(PosNetV1Pos::class); + $this->assertTrue($result); - /** - * @return void - */ - public function testFormatOrderIdFail(): void - { - $this->expectException(InvalidArgumentException::class); - $this->requestDataMapper::formatOrderId('123456789012345566fml'); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -175,7 +105,7 @@ public function testCreateNonSecurePostAuthPaymentRequestData(array $order, arra */ public function testCreateNonSecurePaymentRequestData(array $order, array $expectedData): void { - $hashCalculationData = $expectedData; + $hashCalculationData = $expectedData; unset($hashCalculationData['MAC']); $this->crypt->expects(self::once()) @@ -193,7 +123,7 @@ public function testCreateNonSecurePaymentRequestData(array $order, array $expec */ public function testCreate3DPaymentRequestData(array $order, string $txType, array $responseData, array $expectedData): void { - $hashCalculationData = $expectedData; + $hashCalculationData = $expectedData; unset($hashCalculationData['MAC']); $this->crypt->expects(self::once()) @@ -220,7 +150,7 @@ public function testCreate3DFormData(array $order, string $txType, string $gatew && $paymentModel === $dispatchedEvent->getPaymentModel() && count($dispatchedEvent->getFormInputs()) > 3)); - $hashCalculationData = $expected['inputs']; + $hashCalculationData = $expected['inputs']; unset($hashCalculationData['Mac']); $this->crypt->expects(self::once()) @@ -245,7 +175,7 @@ public function testCreate3DFormData(array $order, string $txType, string $gatew */ public function testCreateStatusRequestData(array $order, array $expected): void { - $hashCalculationData = $expected; + $hashCalculationData = $expected; unset($hashCalculationData['MAC']); $this->crypt->expects(self::once()) @@ -262,7 +192,7 @@ public function testCreateStatusRequestData(array $order, array $expected): void */ public function testCreateRefundRequestData(array $order, string $txType, array $expected): void { - $hashCalculationData = $expected; + $hashCalculationData = $expected; unset($hashCalculationData['MAC']); $this->crypt->expects(self::once()) @@ -283,7 +213,7 @@ public function testCreateRefundRequestData(array $order, string $txType, array */ public function testCreateCancelRequestData(array $order, array $expected): void { - $hashCalculationData = $expected; + $hashCalculationData = $expected; unset($hashCalculationData['MAC']); $this->crypt->expects(self::once()) @@ -433,7 +363,7 @@ public static function createCustomQueryRequestDataDataProvider(): \Generator */ public static function threeDFormDataTestProvider(): iterable { - $order = [ + $order = [ 'id' => '620093100_024', 'amount' => 1.75, 'installment' => 0, @@ -441,7 +371,7 @@ public static function threeDFormDataTestProvider(): iterable 'success_url' => 'https://domain.com/success', 'lang' => PosInterface::LANG_TR, ]; - $card = CreditCardFactory::create('5400619360964581', '20', '01', '056', 'ahmet'); + $card = CreditCardFactory::create('5400619360964581', '20', '01', '056', 'ahmet'); $gatewayUrl = 'https://epostest.albarakaturk.com.tr/ALBSecurePaymentUI/SecureProcess/SecureVerification.aspx'; yield [ diff --git a/tests/Unit/DataMapper/RequestDataMapper/ToslaPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/ToslaPosRequestDataMapperTest.php index f7838c24..65643534 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/ToslaPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/ToslaPosRequestDataMapperTest.php @@ -8,11 +8,14 @@ use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\ToslaPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\ToslaPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\ToslaPosRequestValueMapper; use Mews\Pos\Entity\Account\ToslaPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\ToslaPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -36,6 +39,10 @@ class ToslaPosRequestDataMapperTest extends TestCase private ToslaPosRequestDataMapper $requestDataMapper; + private ToslaPosRequestValueFormatter $valueFormatter; + + private ToslaPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -47,62 +54,29 @@ protected function setUp(): void 'POS_ENT_Test_001!*!*', ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new ToslaPosRequestValueFormatter(); + $this->valueMapper = new ToslaPosRequestValueMapper(); + + $this->requestDataMapper = new ToslaPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new ToslaPosRequestDataMapper($this->dispatcher, $this->crypt); - $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet', CreditCardInterface::CARD_TYPE_VISA); + $this->card = CreditCardFactory::create('5555444433332222', '22', '01', '123', 'ahmet', CreditCardInterface::CARD_TYPE_VISA); } - /** - * @testWith ["pay", "1"] - * ["pre", "2"] - */ - public function testMapTxType(string $txType, string $expected): void + public function testSupports(): void { - $actual = $this->requestDataMapper->mapTxType($txType); - $this->assertSame($expected, $actual); - } + $result = $this->requestDataMapper::supports(ToslaPos::class); + $this->assertTrue($result); - /** - * @testWith ["1"] - */ - public function testMapTxTypeException(string $txType): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->requestDataMapper->mapTxType($txType); - } - - - /** - * @return void - */ - public function testMapCurrency(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } - - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "0"] - * ["1", "0"] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -332,7 +306,7 @@ public static function createCustomQueryRequestDataDataProvider(): \Generator 'clientId' => '1000000494', 'hash' => '12fsdfdsfsfs', 'rnd' => 'rndsfldfls', - 'timeSpan' => '20241103144302', + 'timeSpan' => new \DateTimeImmutable('2024-11-03 14:43:02'), ], ]; @@ -343,7 +317,6 @@ public static function createCustomQueryRequestDataDataProvider(): \Generator 'clientId' => '1000000494xx', 'hash' => '12fsdfdsfsfsxxx', 'rnd' => 'rndsfldfls', - 'timeSpan' => '20241103144302', ], 'expected' => [ 'apiUser' => 'POS_ENT_Test_001xxx', @@ -351,7 +324,7 @@ public static function createCustomQueryRequestDataDataProvider(): \Generator 'clientId' => '1000000494xx', 'hash' => '12fsdfdsfsfsxxx', 'rnd' => 'rndsfldfls', - 'timeSpan' => '20241103144302', + 'timeSpan' => new \DateTimeImmutable('2024-11-03 14:43:02'), ], ]; } @@ -362,7 +335,7 @@ public static function statusRequestDataProvider(): array [ 'order' => [ 'id' => 'id-12', - 'time_span' => '20231209215355', + 'time_span' => new \DateTimeImmutable('20231209215355'), ], 'expected' => [ 'clientId' => '1000000494', @@ -382,7 +355,7 @@ public static function cancelRequestDataProvider(): array [ 'order' => [ 'id' => 'id-12', - 'time_span' => '20231209215355', + 'time_span' => new \DateTimeImmutable('20231209215355'), ], 'expected' => [ 'clientId' => '1000000494', @@ -403,7 +376,7 @@ public static function refundRequestDataProvider(): array 'order' => [ 'id' => 'id-12', 'amount' => 1.02, - 'time_span' => '20231209215355', + 'time_span' => new \DateTimeImmutable('20231209215355'), ], 'tx_type' => PosInterface::TX_TYPE_REFUND, 'expected' => [ @@ -427,7 +400,7 @@ public static function paymentRegisterRequestDataProvider(): array 'installment' => 0, 'currency' => PosInterface::CURRENCY_TRY, 'success_url' => 'https://domain.com/success', - 'time_span' => '20231209214708', + 'time_span' => new \DateTimeImmutable('20231209214708'), ]; return [ @@ -459,7 +432,7 @@ public static function nonSecurePaymentRequestDataProvider(): array 'installment' => 0, 'currency' => PosInterface::CURRENCY_TRY, 'success_url' => 'https://domain.com/success', - 'time_span' => '20231209214708', + 'time_span' => new \DateTimeImmutable('20231209214708'), ]; return [ @@ -492,7 +465,7 @@ public static function nonSecurePaymentPostRequestDataProvider(): array 'order' => [ 'id' => '2020110828BC', 'amount' => 1.10, - 'time_span' => '20231209213944', + 'time_span' => new \DateTimeImmutable('20231209213944'), ], 'expected' => [ 'clientId' => '1000000494', @@ -513,7 +486,7 @@ public static function orderHistoryRequestDataProvider(): array [ 'order' => [ 'id' => '2020110828BC', - 'time_span' => '20231209215355', + 'time_span' => new \DateTimeImmutable('20231209215355'), 'transaction_date' => new \DateTime('2023-12-09 00:00:00'), ], 'expected' => [ @@ -531,7 +504,7 @@ public static function orderHistoryRequestDataProvider(): array [ 'order' => [ 'id' => '2020110828BC', - 'time_span' => '20231209215355', + 'time_span' => new \DateTimeImmutable('20231209215355'), 'page' => 2, 'page_size' => 5, 'transaction_date' => new \DateTime('2023-12-09 00:00:00'), @@ -577,7 +550,7 @@ public static function threeDFormDataProvider(): array 'payment_model' => PosInterface::MODEL_3D_PAY, 'is_with_card' => true, 'gateway' => 'https://ent.akodepos.com/api/Payment/ProcessCardForm', - 'expected' => [ + 'expected' => [ 'gateway' => 'https://ent.akodepos.com/api/Payment/ProcessCardForm', 'method' => 'POST', 'inputs' => [ diff --git a/tests/Unit/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapperTest.php b/tests/Unit/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapperTest.php index dde156e2..81601e95 100644 --- a/tests/Unit/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapperTest.php +++ b/tests/Unit/DataMapper/RequestDataMapper/VakifKatilimPosRequestDataMapperTest.php @@ -9,10 +9,14 @@ use Generator; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\VakifKatilimPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueFormatter\VakifKatilimPosRequestValueFormatter; +use Mews\Pos\DataMapper\RequestValueMapper\VakifKatilimPosRequestValueMapper; use Mews\Pos\Entity\Account\KuveytPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\VakifKatilimPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -36,6 +40,10 @@ class VakifKatilimPosRequestDataMapperTest extends TestCase /** @var CryptInterface & MockObject */ private CryptInterface $crypt; + private VakifKatilimPosRequestValueFormatter $valueFormatter; + + private VakifKatilimPosRequestValueMapper $valueMapper; + protected function setUp(): void { parent::setUp(); @@ -56,54 +64,27 @@ protected function setUp(): void 'John Doe', ); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->crypt = $this->createMock(CryptInterface::class); - $this->requestDataMapper = new VakifKatilimPosRequestDataMapper($this->dispatcher, $this->crypt); - } - - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame(0, $method->invokeArgs($this->requestDataMapper, [0])); - $this->assertSame(0, $method->invokeArgs($this->requestDataMapper, [0.0])); - $this->assertSame(1025, $method->invokeArgs($this->requestDataMapper, [10.25])); - $this->assertSame(1000, $method->invokeArgs($this->requestDataMapper, [10.00])); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->valueFormatter = new VakifKatilimPosRequestValueFormatter(); + $this->valueMapper = new VakifKatilimPosRequestValueMapper(); + + $this->requestDataMapper = new VakifKatilimPosRequestDataMapper( + $this->valueMapper, + $this->valueFormatter, + $this->dispatcher, + $this->crypt, + PosInterface::LANG_EN + ); } - /** - * @return void - */ - public function testMapCurrency(): void + public function testSupports(): void { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapCurrency'); - $method->setAccessible(true); - $this->assertSame('0949', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_TRY])); - $this->assertSame('0978', $method->invokeArgs($this->requestDataMapper, [PosInterface::CURRENCY_EUR])); - } + $result = $this->requestDataMapper::supports(VakifKatilimPos::class); + $this->assertTrue($result); - /** - * @param string|int|null $installment - * @param string|int $expected - * - * @testWith ["0", "0"] - * ["1", "0"] - * ["2", "2"] - * [2, "2"] - * - * @return void - */ - public function testMapInstallment($installment, $expected): void - { - $class = new \ReflectionObject($this->requestDataMapper); - $method = $class->getMethod('mapInstallment'); - $method->setAccessible(true); - $this->assertSame($expected, $method->invokeArgs($this->requestDataMapper, [$installment])); + $result = $this->requestDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); } /** @@ -116,15 +97,13 @@ public function testGet3DFormData( string $paymentModel, array $expected ): void { - if (PosInterface::MODEL_3D_HOST === $paymentModel) { - $hashCalculationData = $expected['inputs']; - unset($hashCalculationData['HashPassword']); + $hashCalculationData = $expected['inputs']; + unset($hashCalculationData['HashPassword']); - $this->crypt->expects(self::once()) - ->method('hashString') - ->with($this->account->getStoreKey()) - ->willReturn($expected['inputs']['HashPassword']); - } + $this->crypt->expects(self::once()) + ->method('hashString') + ->with($this->account->getStoreKey()) + ->willReturn($expected['inputs']['HashPassword']); $actual = $this->requestDataMapper->create3DFormData( $this->account, @@ -137,6 +116,32 @@ public function testGet3DFormData( $this->assertSame($expected, $actual); } + public function testGet3DFormDataUnsupportedPaymentModel(): void + { + $paymentModel = PosInterface::MODEL_3D_SECURE; + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $gatewayURL = 'https://example.com/3d-gateway'; + $this->crypt->expects(self::never()) + ->method('hashString'); + + $order = [ + 'id' => '123', + 'amount' => 10.0, + 'installment' => 0, + 'currency' => PosInterface::CURRENCY_TRY, + ]; + + $this->expectException(\LogicException::class); + + $this->requestDataMapper->create3DFormData( + $this->account, + $order, + $paymentModel, + $txType, + $gatewayURL, + ); + } + /** * @dataProvider nonSecurePaymentRequestDataDataProvider */ @@ -879,7 +884,7 @@ public static function threeDFormDataProvider(): array 'HashPassword' => 'h58bUB83xQz2/21SUeOemUgkF5U=', 'MerchantId' => '1', 'MerchantOrderId' => 'order222', - 'Amount' => 10025, + 'Amount' => '10025', 'FECCurrencyCode' => '0949', 'OkUrl' => 'https://domain.com/success', 'FailUrl' => 'https://domain.com/fail_url', @@ -887,37 +892,6 @@ public static function threeDFormDataProvider(): array ], ], ], - '3d' => [ - 'order' => [ - 'ResponseCode' => '00', - 'ResponseMessage' => '', - 'ProvisionNumber' => 'prov-123', - 'MerchantOrderId' => 'order-123', - 'OrderId' => 'bank-123', - 'RRN' => 'rrn-123', - 'Stan' => 'stan-123', - 'HashData' => 'hash-123', - 'MD' => 'ktSVkYJHcHSYM1ibA/nM6nObr8WpWdcw34ziyRQRLv06g7UR2r5LrpLeNvwfBwPz', - ], - 'gatewayUrl' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_SECURE, - 'expected' => [ - 'gateway' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', - 'method' => 'POST', - 'inputs' => [ - 'ResponseCode' => '00', - 'ResponseMessage' => '', - 'ProvisionNumber' => 'prov-123', - 'MerchantOrderId' => 'order-123', - 'OrderId' => 'bank-123', - 'RRN' => 'rrn-123', - 'Stan' => 'stan-123', - 'HashData' => 'hash-123', - 'MD' => 'ktSVkYJHcHSYM1ibA/nM6nObr8WpWdcw34ziyRQRLv06g7UR2r5LrpLeNvwfBwPz', - ], - ], - ], ]; } } diff --git a/tests/Unit/DataMapper/RequestValueFormatter/AkbankPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/AkbankPosRequestValueFormatterTest.php new file mode 100644 index 00000000..fe81cdab --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/AkbankPosRequestValueFormatterTest.php @@ -0,0 +1,77 @@ +formatter = new AkbankPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(AkbankPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, 1] + * [1, 1] + * [2, 2] + */ + public function testFormatInstallment(int $installment, int $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, "1.10"] + * @testWith [1.0, "1.00"] + * @testWith [1, "1.00"] + * @testWith [1000.0, "1000.00"] + */ + public function testFormatAmount(float $amount, string $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["expiredDate", "0424"] + * ["expireDate", "0424"] + * ["", "0424"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatDateTime($dateTime); + $this->assertSame('2024-04-14T16:45:30.000', $actual); + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/EstPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/EstPosRequestValueFormatterTest.php new file mode 100644 index 00000000..de052cfd --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/EstPosRequestValueFormatterTest.php @@ -0,0 +1,92 @@ +formatter = new EstPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(EstPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(AkbankPos::class); + $this->assertFalse($result); + } + + + /** + * @testWith [0, ""] + * [1, ""] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, "1.1"] + * [1.0, "1"] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + /** + * @testWith ["Ecom_Payment_Card_ExpDate_Month", "04"] + * ["Ecom_Payment_Card_ExpDate_Year", "24"] + * ["Expires", "04/24"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(NotImplementedException::class); + $this->formatter->formatDateTime($dateTime); + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/GarantiPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/GarantiPosRequestValueFormatterTest.php new file mode 100644 index 00000000..291442a2 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/GarantiPosRequestValueFormatterTest.php @@ -0,0 +1,109 @@ +formatter = new GarantiPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(GarantiPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, ""] + * [1, ""] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, 110] + * [1.0, 100] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + /** + * @testWith ["cardexpiredatemonth", "04"] + * ["cardexpiredateyear", "24"] + * ["ExpireDate", "0424"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatDateTimeDataProvider + */ + public function testFormatDateTime(\DateTimeInterface $dateTime, ?string $fieldName, string $expected): void + { + $actual = $this->formatter->formatDateTime($dateTime, $fieldName); + $this->assertSame($expected, $actual); + } + + public static function formatDateTimeDataProvider(): array + { + return [ + [ + new \DateTime('2024-04-14T16:45:30.000'), + 'StartDate', + '14/04/2024 16:45', + ], + [ + new \DateTime('2024-04-14T16:45:30.000'), + 'EndDate', + '14/04/2024 16:45', + ], + [ + new \DateTime('2024-04-14T16:45:30.000'), + null, + '14/04/2024 16:45', + ], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/InterPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/InterPosRequestValueFormatterTest.php new file mode 100644 index 00000000..3ac01403 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/InterPosRequestValueFormatterTest.php @@ -0,0 +1,75 @@ +formatter = new InterPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(InterPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, ""] + * [1, ""] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, "1.1"] + * [1.0, "1"] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["", "0424"] + * ["Expiry", "0424"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(NotImplementedException::class); + $this->formatter->formatDateTime($dateTime); + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/KuveytPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/KuveytPosRequestValueFormatterTest.php new file mode 100644 index 00000000..66fcc524 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/KuveytPosRequestValueFormatterTest.php @@ -0,0 +1,89 @@ +formatter = new KuveytPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(KuveytPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(KuveytSoapApiPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, "0"] + * [1, "0"] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, 110] + * [1.0, 100] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["CardExpireDateMonth", "04"] + * ["CardExpireDateYear", "24"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatDateTime($dateTime); + $this->assertSame('2024-04-14T16:45:30', $actual); + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/ParamPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/ParamPosRequestValueFormatterTest.php new file mode 100644 index 00000000..41847f6c --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/ParamPosRequestValueFormatterTest.php @@ -0,0 +1,102 @@ +formatter = new ParamPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(ParamPos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(Param3DHostPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, "1"] + * [1, "1"] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatAmountDataProvider + */ + public function testFormatAmount(float $amount, string $txType, $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["KK_SK_Yil", "2024"] + * ["KK_SK_Ay", "04"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatDateTime($dateTime); + $this->assertSame('14.04.2024 16:45:30', $actual); + } + + public static function formatAmountDataProvider(): array + { + return [ + [1.0, PosInterface::TX_TYPE_PAY_AUTH, '1,00'], + [1000.0, PosInterface::TX_TYPE_PAY_AUTH, '1000,00'], + [1.0, PosInterface::TX_TYPE_CANCEL, '1.00'], + [1000.0, PosInterface::TX_TYPE_CANCEL, '1000.00'], + [1.0, PosInterface::TX_TYPE_REFUND, '1.00'], + [1000.0, PosInterface::TX_TYPE_REFUND, '1000.00'], + [1.0, PosInterface::TX_TYPE_REFUND_PARTIAL, '1.00'], + [1000.0, PosInterface::TX_TYPE_REFUND_PARTIAL, '1000.00'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/PayFlexCPV4PosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/PayFlexCPV4PosRequestValueFormatterTest.php new file mode 100644 index 00000000..5b329595 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/PayFlexCPV4PosRequestValueFormatterTest.php @@ -0,0 +1,87 @@ +formatter = new PayFlexCPV4PosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(PayFlexCPV4Pos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, "0"] + * [1, "0"] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1, "1.00"] + * [1.1, "1.10"] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + /** + * @testWith ["ExpireMonth", "04"] + * ["ExpireYear", "24"] + * ["Expiry", "202404"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(NotImplementedException::class); + $this->formatter->formatDateTime($dateTime); + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/PayFlexV4PosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/PayFlexV4PosRequestValueFormatterTest.php new file mode 100644 index 00000000..d2c05cbe --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/PayFlexV4PosRequestValueFormatterTest.php @@ -0,0 +1,86 @@ +formatter = new PayFlexV4PosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(PayFlexV4Pos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + + /** + * @testWith [0, "0"] + * [1, "0"] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1, "1.00"] + * [1.1, "1.10"] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + /** + * @testWith ["ExpiryDate", "2404"] + * ["Expiry", "202404"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatDateTime($dateTime); + $this->assertSame('20240414', $actual); + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/PayForPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/PayForPosRequestValueFormatterTest.php new file mode 100644 index 00000000..c4d85966 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/PayForPosRequestValueFormatterTest.php @@ -0,0 +1,74 @@ +formatter = new PayForPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(PayForPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, "0"] + * [1, "0"] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, "1.1"] + * [1.0, "1"] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["", "0424"] + * ["abc", "0424"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatDateTime($dateTime); + $this->assertSame('20240414', $actual); + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/PosNetRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/PosNetRequestValueFormatterTest.php new file mode 100644 index 00000000..0ec46e33 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/PosNetRequestValueFormatterTest.php @@ -0,0 +1,103 @@ +formatter = new PosNetRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(PosNet::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, "00"] + * [1, "00"] + * [2, "02"] + * [12, "12"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, 110] + * [1.0, 100] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatOrderIdDataProvider + */ + public function testFormatOrderId(string $orderId, ?string $txType, ?string $orderPaymentModel, string $expected): void + { + $actual = $this->formatter->formatOrderId($orderId, $txType, $orderPaymentModel); + $this->assertSame($expected, $actual); + } + + public function testFormatOrderIdFail(): void + { + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatOrderId('1234567890123456789AB'); + } + + /** + * @testWith ["Expiry", "2404"] + * ["", "2404"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(NotImplementedException::class); + $this->formatter->formatDateTime($dateTime); + } + + public static function formatOrderIdDataProvider(): array + { + return [ + ['ABC123', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE, '00000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE, '00000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_3D_SECURE, 'TDSC00000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_NON_SECURE, '000000000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_3D_PAY, '000000000000000000ABC123'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/PosNetV1PosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/PosNetV1PosRequestValueFormatterTest.php new file mode 100644 index 00000000..18b7af6e --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/PosNetV1PosRequestValueFormatterTest.php @@ -0,0 +1,103 @@ +formatter = new PosNetV1PosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(PosNetV1Pos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + + /** + * @testWith [0, "0"] + * [1, "0"] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, 110] + * [1.0, 100] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatOrderIdDataProvider + */ + public function testFormatOrderId(string $orderId, ?string $txType, ?string $orderPaymentModel, string $expected): void + { + $actual = $this->formatter->formatOrderId($orderId, $txType, $orderPaymentModel); + $this->assertSame($expected, $actual); + } + + public function testFormatOrderIdFail(): void + { + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatOrderId('1234567890123456789AB'); + } + + /** + * @testWith ["Expiry", "2404"] + * ["", "2404"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + public function testFormatDateTime(): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(NotImplementedException::class); + $this->formatter->formatDateTime($dateTime); + } + + public static function formatOrderIdDataProvider(): array + { + return [ + ['ABC123', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE, '00000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE, '00000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_3D_SECURE, 'TDS_00000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_NON_SECURE, '000000000000000000ABC123'], + ['ABC123', PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_3D_PAY, '000000000000000000ABC123'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/ToslaPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/ToslaPosRequestValueFormatterTest.php new file mode 100644 index 00000000..3066541b --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/ToslaPosRequestValueFormatterTest.php @@ -0,0 +1,115 @@ +formatter = new ToslaPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(ToslaPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + + /** + * @testWith [0, 0] + * [1, 0] + * [2, 2] + */ + public function testFormatInstallment(int $installment, int $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, 110] + * [1, 100] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["ExpireDate", "04/24"] + * ["expireDate", "0424"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + /** + * @dataProvider formatDateTimeDataProvider + */ + public function testFormatDateTime(?string $fieldName, string $expected): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatDateTime($dateTime, $fieldName); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [null] + * [""] + */ + public function testFormatDateTimeUnsupportedField(?string $fieldName): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatDateTime($dateTime, $fieldName); + } + + public static function formatDateTimeDataProvider(): array + { + return [ + [ + 'timeSpan', + '20240414164530', + ], + [ + 'transactionDate', + '20240414', + ], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueFormatter/VakifKatilimPosRequestValueFormatterTest.php b/tests/Unit/DataMapper/RequestValueFormatter/VakifKatilimPosRequestValueFormatterTest.php new file mode 100644 index 00000000..5b143ecd --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueFormatter/VakifKatilimPosRequestValueFormatterTest.php @@ -0,0 +1,119 @@ +formatter = new VakifKatilimPosRequestValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(VakifKatilimPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @testWith [0, "0"] + * [1, "0"] + * [2, "2"] + */ + public function testFormatInstallment(int $installment, string $expected): void + { + $actual = $this->formatter->formatInstallment($installment); + $this->assertSame($expected, $actual); + } + + /** + * @testWith [1.1, 110] + * [1.0, 100] + */ + public function testFormatAmount(float $amount, $expected): void + { + $actual = $this->formatter->formatAmount($amount); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["CardExpireDateMonth", "04"] + * ["CardExpireDateYear", "24"] + */ + public function testFormatCreditCardExpDate(string $fieldName, string $expected): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $actual = $this->formatter->formatCardExpDate($expDate, $fieldName); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [""] + */ + public function testFormatCreditCardExpDateUnSupportedField(string $fieldName): void + { + $expDate = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatCardExpDate($expDate, $fieldName); + } + + /** + * @dataProvider formatDateTimeDataProvider + */ + public function testFormatDateTime(\DateTimeInterface $dateTime, ?string $fieldName, ?string $txType, string $expected): void + { + $actual = $this->formatter->formatDateTime($dateTime, $fieldName); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["abc"] + * [null] + * [""] + */ + public function testFormatDateTimeUnsupportedField(?string $fieldName): void + { + $dateTime = new \DateTime('2024-04-14T16:45:30.000'); + $this->expectException(\InvalidArgumentException::class); + $this->formatter->formatDateTime($dateTime, $fieldName); + } + + + public static function formatDateTimeDataProvider(): array + { + return [ + [ + new \DateTime('2024-04-14T16:45:30.000'), + 'StartDate', + PosInterface::TX_TYPE_HISTORY, + '2024-04-14', + ], + [ + new \DateTime('2024-04-14T16:45:30.000'), + 'EndDate', + PosInterface::TX_TYPE_HISTORY, + '2024-04-14', + ], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/AkbankPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/AkbankPosRequestValueMapperTest.php new file mode 100644 index 00000000..2442b45a --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/AkbankPosRequestValueMapperTest.php @@ -0,0 +1,149 @@ +valueMapper = new AkbankPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(AkbankPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType, $paymentModel); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider mapTxTypeUnsupportedDataProvider + */ + public function testMapTxTypeException(string $txType, ?string $paymentModel, string $exceptionClass): void + { + $this->expectException($exceptionClass); + $this->valueMapper->mapTxType($txType, $paymentModel); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + /** + * @testWith ["DAY", "D"] + * ["WEEK", "W"] + * ["MONTH", "M"] + * ["YEAR", "Y"] + */ + public function testMapRecurringFrequency(string $frequency, string $expected): void + { + $this->assertSame($expected, $this->valueMapper->mapRecurringFrequency($frequency)); + } + + public function testMapLang(): void + { + $this->assertSame('TR', $this->valueMapper->mapLang(PosInterface::LANG_TR)); + $this->assertSame('EN', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('TR', $this->valueMapper->mapLang('ru')); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame(949, $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame(978, $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(2, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(4, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(8, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(4, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3D'], + [PosInterface::MODEL_3D_PAY, '3D_PAY'], + [PosInterface::MODEL_3D_HOST, '3D_PAY_HOSTING'], + [PosInterface::MODEL_NON_SECURE, 'PAY_HOSTING'], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE, '3000'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE, '3004'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_NON_SECURE, '1004'], + ]; + } + + public static function mapTxTypeUnsupportedDataProvider(): array + { + return [ + ['3000', null, UnsupportedTransactionTypeException::class], + [PosInterface::TX_TYPE_PAY_AUTH, null, \InvalidArgumentException::class], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/EstPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/EstPosRequestValueMapperTest.php new file mode 100644 index 00000000..83287afd --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/EstPosRequestValueMapperTest.php @@ -0,0 +1,145 @@ +valueMapper = new EstPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(EstPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["Auth"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + /** + * @testWith ["DAY", "D"] + * ["WEEK", "W"] + * ["MONTH", "M"] + * ["YEAR", "Y"] + */ + public function testMapRecurringFrequency(string $frequency, string $expected): void + { + $this->assertSame($expected, $this->valueMapper->mapRecurringFrequency($frequency)); + } + + public function testMapLang(): void + { + $this->assertSame('tr', $this->valueMapper->mapLang(PosInterface::LANG_TR)); + $this->assertSame('en', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('tr', $this->valueMapper->mapLang('ru')); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(2, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(4, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(8, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(5, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3d'], + [PosInterface::MODEL_3D_PAY, '3d_pay'], + [PosInterface::MODEL_3D_HOST, '3d_host'], + [PosInterface::MODEL_NON_SECURE, 'regular'], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Auth'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'PreAuth'], + [PosInterface::TX_TYPE_PAY_POST_AUTH, 'PostAuth'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/GarantiPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/GarantiPosRequestValueMapperTest.php new file mode 100644 index 00000000..1f3381a1 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/GarantiPosRequestValueMapperTest.php @@ -0,0 +1,136 @@ +valueMapper = new GarantiPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(GarantiPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["sales"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + /** + * @testWith ["DAY", "D"] + * ["WEEK", "W"] + * ["MONTH", "M"] + */ + public function testMapRecurringFrequency(string $frequency, string $expected): void + { + $this->assertSame($expected, $this->valueMapper->mapRecurringFrequency($frequency)); + } + + public function testMapLang(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapLang(PosInterface::LANG_TR); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(0, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(3, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(9, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(2, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3D'], + [PosInterface::MODEL_3D_PAY, '3D_PAY'], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'sales'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'preauth'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/InterPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/InterPosRequestValueMapperTest.php new file mode 100644 index 00000000..022c5b23 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/InterPosRequestValueMapperTest.php @@ -0,0 +1,154 @@ +valueMapper = new InterPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(InterPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["sales"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->assertSame('tr', $this->valueMapper->mapLang(PosInterface::LANG_TR)); + $this->assertSame('en', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('tr', $this->valueMapper->mapLang('ru')); + } + + public function testMapCurrency(): void + { + $this->assertSame('949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + /** + * @dataProvider mapCardTypeDataProvider + */ + public function testMapCardType(string $cardType, string $expected): void + { + $this->assertSame($expected, $this->valueMapper->mapCardType($cardType)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(2, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(7, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(4, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(4, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3DModel'], + [PosInterface::MODEL_3D_PAY, '3DPay'], + [PosInterface::MODEL_NON_SECURE, 'NonSecure'], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Auth'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'PreAuth'], + ]; + } + + public static function mapCardTypeDataProvider(): array + { + return [ + [ + CreditCardInterface::CARD_TYPE_VISA, + '0', + ], + [ + CreditCardInterface::CARD_TYPE_MASTERCARD, + '1', + ], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/KuveytPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/KuveytPosRequestValueMapperTest.php new file mode 100644 index 00000000..c8e27c12 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/KuveytPosRequestValueMapperTest.php @@ -0,0 +1,153 @@ +valueMapper = new KuveytPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(KuveytPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(KuveytSoapApiPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["Auth"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapLang(PosInterface::LANG_TR); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('0949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('0978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(0, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(3, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(5, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(2, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(3, $this->valueMapper->getCardTypeMappings()); + } + + /** + * @dataProvider mapCardTypeDataProvider + */ + public function testMapCardType(string $cardType, string $expected): void + { + $this->assertSame($expected, $this->valueMapper->mapCardType($cardType)); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3'], + [PosInterface::MODEL_NON_SECURE, '0'], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Sale'], + ]; + } + + public static function mapCardTypeDataProvider(): array + { + return [ + [CreditCardInterface::CARD_TYPE_VISA, 'Visa'], + [CreditCardInterface::CARD_TYPE_MASTERCARD, 'MasterCard'], + [CreditCardInterface::CARD_TYPE_TROY, 'Troy'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/ParamPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/ParamPosRequestValueMapperTest.php new file mode 100644 index 00000000..0b143e47 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/ParamPosRequestValueMapperTest.php @@ -0,0 +1,160 @@ +valueMapper = new ParamPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(ParamPos::class); + $this->assertTrue($result); + $result = $this->valueMapper::supports(Param3DHostPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $paymentModel, ?array $order, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType, $paymentModel, $order); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider mapTxTypeUnsupportedDataProvider + */ + public function testMapTxTypeException(string $txType, ?string $paymentModel, string $exceptionClass): void + { + $this->expectException($exceptionClass); + $this->valueMapper->mapTxType($txType, $paymentModel); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapLang(PosInterface::LANG_TR); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('1000', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('1001', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_USD)); + $this->assertSame('1002', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + $this->assertSame('1003', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_GBP)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(0, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(4, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(8, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(3, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3D'], + [PosInterface::MODEL_3D_PAY, '3D'], + [PosInterface::MODEL_NON_SECURE, 'NS'], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE, ['currency' => PosInterface::CURRENCY_USD], 'TP_Islem_Odeme_WD'], + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE, ['currency' => PosInterface::CURRENCY_USD], 'TP_Islem_Odeme_WD'], + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE, ['currency' => PosInterface::CURRENCY_TRY], 'TP_WMD_UCD'], + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE, null, 'TP_WMD_UCD'], + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE, null, 'TP_WMD_UCD'], + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_PAY, null, 'Pos_Odeme'], + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_HOST, null, 'TO_Pre_Encrypting_OOS'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_NON_SECURE, null, 'TP_Islem_Odeme_OnProv_WMD'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE, null, 'TP_Islem_Odeme_OnProv_WMD'], + [PosInterface::TX_TYPE_PAY_POST_AUTH, PosInterface::MODEL_NON_SECURE, null, 'TP_Islem_Odeme_OnProv_Kapa'], + [PosInterface::TX_TYPE_REFUND, PosInterface::MODEL_NON_SECURE, null, 'TP_Islem_Iptal_Iade_Kismi2'], + [PosInterface::TX_TYPE_REFUND_PARTIAL, PosInterface::MODEL_NON_SECURE, null, 'TP_Islem_Iptal_Iade_Kismi2'], + [PosInterface::TX_TYPE_CANCEL, PosInterface::MODEL_NON_SECURE, null, 'TP_Islem_Iptal_Iade_Kismi2'], + [PosInterface::TX_TYPE_CANCEL, PosInterface::MODEL_3D_SECURE, ['transaction_type' => PosInterface::TX_TYPE_PAY_PRE_AUTH], 'TP_Islem_Iptal_OnProv'], + [PosInterface::TX_TYPE_STATUS, PosInterface::MODEL_NON_SECURE, null, 'TP_Islem_Sorgulama4'], + [PosInterface::TX_TYPE_HISTORY, PosInterface::MODEL_NON_SECURE, null, 'TP_Islem_Izleme'], + ]; + } + + public static function mapTxTypeUnsupportedDataProvider(): array + { + return [ + ['3000', null, UnsupportedTransactionTypeException::class], + [PosInterface::TX_TYPE_PAY_AUTH, null, \InvalidArgumentException::class], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/PayFlexCPV4PosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/PayFlexCPV4PosRequestValueMapperTest.php new file mode 100644 index 00000000..0416bd61 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/PayFlexCPV4PosRequestValueMapperTest.php @@ -0,0 +1,123 @@ +valueMapper = new PayFlexCPV4PosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(PayFlexCPV4Pos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["Auth"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapSecureType(PosInterface::MODEL_3D_SECURE); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->assertSame('tr-TR', $this->valueMapper->mapLang(PosInterface::LANG_TR)); + $this->assertSame('en-US', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('tr-TR', $this->valueMapper->mapLang('ru')); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(2, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(8, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(4, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Sale'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'Auth'], + [PosInterface::TX_TYPE_PAY_POST_AUTH, 'Capture'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/PayFlexV4PosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/PayFlexV4PosRequestValueMapperTest.php new file mode 100644 index 00000000..dff431bf --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/PayFlexV4PosRequestValueMapperTest.php @@ -0,0 +1,128 @@ +valueMapper = new PayFlexV4PosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(PayFlexV4Pos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["Auth"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapSecureType(PosInterface::MODEL_3D_SECURE); + } + + /** + * @testWith ["DAY", "Day"] + * ["MONTH", "Month"] + * ["YEAR", "Year"] + */ + public function testMapRecurringFrequency(string $frequency, string $expected): void + { + $this->assertSame($expected, $this->valueMapper->mapRecurringFrequency($frequency)); + } + + public function testMapLang(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapLang(PosInterface::LANG_TR); + $this->assertSame('en', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('tr', $this->valueMapper->mapLang('ru')); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(0, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(3, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(7, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(4, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Sale'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'Auth'], + [PosInterface::TX_TYPE_PAY_POST_AUTH, 'Capture'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/PayForPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/PayForPosRequestValueMapperTest.php new file mode 100644 index 00000000..cea4f47a --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/PayForPosRequestValueMapperTest.php @@ -0,0 +1,136 @@ +valueMapper = new PayForPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(PayForPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["Auth"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->assertSame('tr', $this->valueMapper->mapLang(PosInterface::LANG_TR)); + $this->assertSame('en', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('tr', $this->valueMapper->mapLang('ru')); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(2, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(8, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(4, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3DModel'], + [PosInterface::MODEL_3D_PAY, '3DPay'], + [PosInterface::MODEL_3D_HOST, '3DHost'], + [PosInterface::MODEL_NON_SECURE, 'NonSecure'], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Auth'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'PreAuth'], + [PosInterface::TX_TYPE_PAY_POST_AUTH, 'PostAuth'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/PosNetRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/PosNetRequestValueMapperTest.php new file mode 100644 index 00000000..7e33c82a --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/PosNetRequestValueMapperTest.php @@ -0,0 +1,123 @@ +valueMapper = new PosNetRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(PosNet::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["Sale"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapSecureType(PosInterface::MODEL_3D_SECURE); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->assertSame('tr', $this->valueMapper->mapLang(PosInterface::LANG_TR)); + $this->assertSame('en', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('tr', $this->valueMapper->mapLang('ru')); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('TL', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('EU', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(2, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(7, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Sale'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'Auth'], + [PosInterface::TX_TYPE_PAY_POST_AUTH, 'Capt'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/PosNetV1PosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/PosNetV1PosRequestValueMapperTest.php new file mode 100644 index 00000000..ae738630 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/PosNetV1PosRequestValueMapperTest.php @@ -0,0 +1,123 @@ +valueMapper = new PosNetV1PosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(PosNetV1Pos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["Sale"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapSecureType(PosInterface::MODEL_3D_SECURE); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->assertSame('tr', $this->valueMapper->mapLang(PosInterface::LANG_TR)); + $this->assertSame('en', $this->valueMapper->mapLang(PosInterface::LANG_EN)); + $this->assertSame('tr', $this->valueMapper->mapLang('ru')); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('TL', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('EU', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(2, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(7, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, 'Sale'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, 'Auth'], + [PosInterface::TX_TYPE_PAY_POST_AUTH, 'Capture'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/ToslaPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/ToslaPosRequestValueMapperTest.php new file mode 100644 index 00000000..5a265f21 --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/ToslaPosRequestValueMapperTest.php @@ -0,0 +1,121 @@ +valueMapper = new ToslaPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(ToslaPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $paymentModel, string $expected): void + { + $actual = $this->valueMapper->mapTxType($txType, $paymentModel); + $this->assertSame($expected, $actual); + } + + /** + * @testWith ["1"] + */ + public function testMapTxTypeException(string $txType): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType($txType); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapSecureType(PosInterface::MODEL_3D_SECURE); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapLang(PosInterface::LANG_TR); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame(949, $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame(978, $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(0, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(6, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public static function mapTxTypeDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE, '1'], + [PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE, '2'], + ]; + } +} diff --git a/tests/Unit/DataMapper/RequestValueMapper/VakifKatilimPosRequestValueMapperTest.php b/tests/Unit/DataMapper/RequestValueMapper/VakifKatilimPosRequestValueMapperTest.php new file mode 100644 index 00000000..d22ddf8e --- /dev/null +++ b/tests/Unit/DataMapper/RequestValueMapper/VakifKatilimPosRequestValueMapperTest.php @@ -0,0 +1,119 @@ +valueMapper = new VakifKatilimPosRequestValueMapper(); + } + + public function testSupports(): void + { + $result = $this->valueMapper::supports(VakifKatilimPos::class); + $this->assertTrue($result); + + $result = $this->valueMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + public function testMapTxType(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_AUTH); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $paymentModel, string $expected): void + { + $mappedSecureType = $this->valueMapper->mapSecureType($paymentModel); + $this->assertSame($expected, $mappedSecureType); + } + + public function testMapRecurringFrequency(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapRecurringFrequency('DAY'); + } + + public function testMapLang(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapLang(PosInterface::LANG_TR); + } + + /** + * @return void + */ + public function testMapCurrency(): void + { + $this->assertSame('0949', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_TRY)); + $this->assertSame('0978', $this->valueMapper->mapCurrency(PosInterface::CURRENCY_EUR)); + } + + public function testGetLangMappings(): void + { + $this->assertCount(0, $this->valueMapper->getLangMappings()); + } + + public function testGetRecurringOrderFrequencyMappings(): void + { + $this->assertCount(0, $this->valueMapper->getRecurringOrderFrequencyMappings()); + } + + public function testGetCurrencyMappings(): void + { + $this->assertCount(6, $this->valueMapper->getCurrencyMappings()); + } + + public function testGetTxTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getTxTypeMappings()); + } + + public function testGetSecureTypeMappings(): void + { + $this->assertCount(2, $this->valueMapper->getSecureTypeMappings()); + } + + public function testGetCardTypeMappings(): void + { + $this->assertCount(0, $this->valueMapper->getCardTypeMappings()); + } + + public function testMapCardType(): void + { + $this->expectException(\LogicException::class); + $this->valueMapper->mapCardType(CreditCardInterface::CARD_TYPE_VISA); + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + [PosInterface::MODEL_3D_SECURE, '3'], + [PosInterface::MODEL_NON_SECURE, '5'], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php index dcda5056..97025a86 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php @@ -6,13 +6,17 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\AkbankPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\AkbankPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; +use Mews\Pos\Factory\RequestValueMapperFactory; +use Mews\Pos\Factory\ResponseValueFormatterFactory; +use Mews\Pos\Factory\ResponseValueMapperFactory; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -26,25 +30,37 @@ class AkbankPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new AkbankPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new AkbankPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + /** * @testWith ["VPS-0000", true] * ["VPS-1073", false] @@ -72,14 +88,19 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['txnCode']) + ->willReturn($expectedData['transaction_type']); + + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -96,19 +117,30 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + if (isset($responseData['txnCode'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['txnCode']) + ->willReturn($expectedData['transaction_type']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $responseData, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->assertSame($expectedData['transaction_time'], $actualData['transaction_time']); + } $this->assertArrayHasKey('all', $actualData); if ([] !== $responseData) { @@ -131,14 +163,22 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $this->responseValueMapper->expects($this->never()) + ->method('mapTxType') + ->with($responseData['txnCode']); + + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->assertSame($expectedData['transaction_time'], $actualData['transaction_time']); + } $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -155,14 +195,22 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $this->responseValueMapper->expects($this->never()) + ->method('mapTxType') + ->with($responseData['txnCode']); + + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->assertSame($expectedData['transaction_time'], $actualData['transaction_time']); + } $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -209,11 +257,20 @@ public function testMapCancelResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(AkbankPos::class); + $responseDataMapper = new AkbankPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(AkbankPos::class), + ResponseValueMapperFactory::createForGateway(AkbankPos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); + if (isset($responseData['txnDetailList'])) { $this->assertCount($actualData['trans_count'], $actualData['transactions']); @@ -311,7 +368,7 @@ public static function paymentDataProvider(): iterable 'payment_model' => 'regular', 'transaction_id' => null, 'transaction_type' => 'pay', - 'transaction_time' => new \DateTimeImmutable('2022-03-01T09:29:23.851'), + 'transaction_time' => new \DateTimeImmutable('2022-03-01T09:29:23'), 'auth_code' => '064716', 'order_id' => 'b9ebfdc5-304f-49c2-8065-a2c7481a5d1f', 'recurring_id' => null, @@ -2711,7 +2768,5 @@ public static function historyDataProvider(): \Generator ], 'expectedTxCount' => 0, ]; - - } } diff --git a/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php index 9b42fa32..1437956a 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php @@ -6,14 +6,20 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\EstPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\EstPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Factory\RequestValueMapperFactory; +use Mews\Pos\Factory\ResponseValueFormatterFactory; +use Mews\Pos\Factory\ResponseValueMapperFactory; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\EstPos; +use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,25 +33,40 @@ class EstPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new EstPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new EstPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(EstPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(EstV3Pos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + /** * @testWith [null, false] * ["", false] @@ -80,9 +101,17 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['Extra']['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueMapper->expects($this->never()) + ->method('mapTxType'); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -99,14 +128,39 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['taksit'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['currency'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['storetype'], $txType) + ->willReturn($expectedData['payment_model']); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($paymentResponse['Extra']['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order, ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -129,9 +183,34 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['taksit'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['currency'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['storetype'], $txType) + ->willReturn($expectedData['payment_model']); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['EXTRA_TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -148,14 +227,34 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['taksit'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['currency'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['storetype'], $txType) + ->willReturn($expectedData['payment_model']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -172,29 +271,119 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + if (ResponseDataMapperInterface::TX_APPROVED === $expectedData['status']) { + $amountMatcher = $this->exactly($responseData['Extra']['CAPTURE_AMT'] ? 2 : 1); + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $responseData): bool { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $responseData['Extra']['ORIG_TRANS_AMT']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $responseData['Extra']['CAPTURE_AMT']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['first_amount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['capture_amount']; + } + + return false; + } + ); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['Extra']['CHARGE_TYPE_CD']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['Extra']['TRANS_STAT']) + ->willReturn($expectedData['order_status']); + + $dateTimeMatcher = $this->atLeastOnce(); + $dates = ['AUTH_DTTM', 'CAPTURE_DTTM', 'VOID_DTTM']; + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use (&$dates, $responseData): bool { + if (isset($responseData['Extra'][$dates[0]])) { + $dateKey = $dates[0]; + $dates = array_slice($dates, 1); + + return $dateTime === $responseData['Extra'][$dateKey]; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['capture_time']; + } + + if ($dateTimeMatcher->getInvocationCount() === 3) { + return $expectedData['cancel_time']; + } + + return false; + } + ); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - if (isset($actualData['recurringOrders'])) { - foreach ($actualData['recurringOrders'] as $key => $actualRecurringOrder) { - $expectedRecurringOrder = $expectedData['recurringOrders'][$key]; - \ksort($expectedData['recurringOrders'][$key]); - \ksort($actualData['recurringOrders'][$key]); - $this->assertEquals($expectedRecurringOrder['transaction_time'], $actualRecurringOrder['transaction_time']); - $this->assertEquals($expectedRecurringOrder['capture_time'], $actualRecurringOrder['capture_time']); - unset($actualData['recurringOrders'][$key]['transaction_time'], $expectedData['recurringOrders'][$key]['transaction_time']); - unset($actualData['recurringOrders'][$key]['capture_time'], $expectedData['recurringOrders'][$key]['capture_time']); - } - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); + $this->assertArrayHasKey('all', $actualData); + $this->assertIsArray($actualData['all']); + $this->assertNotEmpty($actualData['all']); + unset($actualData['all']); + + \ksort($expectedData); + \ksort($actualData); + + $this->assertSame($expectedData, $actualData); + } + + + /** + * Doing integration test because of the iteration, and conditional statements it is difficult to mock values. + * @dataProvider statusRecurringOrderTestDataProvider + */ + public function testMapStatusResponseRecurringOrder(array $responseData, array $expectedData): void + { + $requestValueMapper = RequestValueMapperFactory::createForGateway(EstV3Pos::class); + $responseDataMapper = new EstPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(EstV3Pos::class), + ResponseValueMapperFactory::createForGateway(EstV3Pos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapStatusResponse($responseData); + + foreach ($actualData['recurringOrders'] as $key => $actualRecurringOrder) { + $expectedRecurringOrder = $expectedData['recurringOrders'][$key]; + \ksort($expectedData['recurringOrders'][$key]); + \ksort($actualData['recurringOrders'][$key]); + $this->assertEquals($expectedRecurringOrder['transaction_time'], $actualRecurringOrder['transaction_time']); + $this->assertEquals($expectedRecurringOrder['capture_time'], $actualRecurringOrder['capture_time']); + unset($actualData['recurringOrders'][$key]['transaction_time'], $expectedData['recurringOrders'][$key]['transaction_time']); + unset($actualData['recurringOrders'][$key]['capture_time'], $expectedData['recurringOrders'][$key]['capture_time']); } + $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); $this->assertNotEmpty($actualData['all']); @@ -237,11 +426,19 @@ public function testMapCancelResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryTestDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(EstV3Pos::class); + $responseDataMapper = new EstPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(EstV3Pos::class), + ResponseValueMapperFactory::createForGateway(EstV3Pos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($responseData['Extra']) > 0) { if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -1282,7 +1479,7 @@ public static function threeDHostPaymentDataProvider(): array public static function statusTestDataProvider(): array { return [ - 'success1' => [ + 'success1' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 20221030FAC5', 'ProcReturnCode' => '00', @@ -1338,7 +1535,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'fail1' => [ + 'fail1' => [ 'responseData' => [ 'ErrMsg' => 'No record found for 2022103088D22', 'ProcReturnCode' => '99', @@ -1375,7 +1572,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'pay_order_status' => [ + 'pay_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 2024010354F1', 'ProcReturnCode' => '00', @@ -1431,7 +1628,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'pre_pay_order_status' => [ + 'pre_pay_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 202401032AF3', 'ProcReturnCode' => '00', @@ -1487,7 +1684,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'canceled_order_status' => [ + 'canceled_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 20240103BBF9', 'ProcReturnCode' => '00', @@ -1544,7 +1741,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'refund_order_status' => [ + 'refund_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 20240128C0B7', 'ProcReturnCode' => '00', @@ -1600,6 +1797,12 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], + ]; + } + + public static function statusRecurringOrderTestDataProvider(): array + { + return [ 'recurring_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 22303O8EA19252', diff --git a/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php index 2a649d49..220e178d 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php @@ -6,14 +6,19 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\GarantiPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\GarantiPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Factory\RequestValueMapperFactory; +use Mews\Pos\Factory\ResponseValueFormatterFactory; +use Mews\Pos\Factory\ResponseValueMapperFactory; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\GarantiPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,25 +32,37 @@ class GarantiPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new GarantiPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new GarantiPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(GarantiPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + /** * @testWith [null, false] * ["", false] @@ -80,9 +97,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['Transaction']['ProvDate'] ?? 'now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -99,14 +121,44 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($paymentResponse['Transaction']['ProvDate'] ?? 'now', $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['txntype']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['secure3dsecuritylevel'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['txnamount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['txncurrencycode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['txninstallmentcount'], $txType) + ->willReturn($expectedData['installment_count']); + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -135,14 +187,39 @@ public function testMap3DHostResponseData(): void */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['txntype']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['secure3dsecuritylevel'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['txnamount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['txncurrencycode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['txninstallmentcount'], $txType) + ->willReturn($expectedData['installment_count']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -159,15 +236,81 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['Order']['OrderInqResult']['InstallmentCnt'], $txType) + ->willReturn($expectedData['installment_count']); + + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['Order']['OrderInqResult']['Status']) + ->willReturn($expectedData['order_status']); + + $amountMatcher = $this->atLeastOnce(); + + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $responseData): bool { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $responseData['Order']['OrderInqResult']['AuthAmount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + if ($responseData['Order']['OrderInqResult']['AuthAmount'] > 0) { + return $amount === $responseData['Order']['OrderInqResult']['AuthAmount']; + } + + return $amount === $responseData['Order']['OrderInqResult']['PreAuthAmount']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['capture_amount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['first_amount']; + } + + return false; + } + ); + + $dateTimeMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use ($dateTimeMatcher, $responseData): bool { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $dateTime === ($responseData['Order']['OrderInqResult']['ProvDate'] ?? $responseData['Order']['OrderInqResult']['PreAuthDate']); + } + + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $dateTime === $responseData['Order']['OrderInqResult']['AuthDate']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['capture_time']; + } + + return false; + } + ); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -180,11 +323,19 @@ public function testMapStatusResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryTestDataProvider */ public function testOrderMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(GarantiPos::class); + $responseDataMapper = new GarantiPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(GarantiPos::class), + ResponseValueMapperFactory::createForGateway(GarantiPos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] && null !== $actualData['transactions'][1]['transaction_time'] @@ -219,7 +370,14 @@ public function testOrderMapHistoryResponse(array $responseData, array $expected */ public function testMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(GarantiPos::class); + $responseDataMapper = new GarantiPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(GarantiPos::class), + ResponseValueMapperFactory::createForGateway(GarantiPos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] diff --git a/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php index b81b126d..2251a5d8 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php @@ -6,14 +6,15 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\InterPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\InterPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\InterPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,25 +28,37 @@ class InterPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new InterPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new InterPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(InterPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + /** * @testWith [null, false] * ["", false] @@ -80,9 +93,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TRXDATE'] ?? 'now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $responseData) { @@ -102,19 +120,29 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($paymentResponse['TRXDATE'] ?? $threeDResponseData['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -137,6 +165,23 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); @@ -154,6 +199,24 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); @@ -171,15 +234,22 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['VoidDate'], $txType) + ->willReturn($expectedData['cancel_time']); + } + + if ($responseData['RefundedAmount'] > 0) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['RefundedAmount'], $txType) + ->willReturn($expectedData['refund_amount']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php index 11815bfb..8fddaf8e 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php @@ -6,14 +6,16 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\KuveytPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\KuveytPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\KuveytPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,24 +29,38 @@ class KuveytPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new KuveytPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); + $this->responseDataMapper = new KuveytPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(KuveytPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** * @testWith [null, false] * ["", false] @@ -70,31 +86,37 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi $this->assertSame($expected, $actual); } - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->responseDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame(0.1, $method->invokeArgs($this->responseDataMapper, [10])); - $this->assertSame(1.01, $method->invokeArgs($this->responseDataMapper, [101])); - } - /** * @dataProvider paymentTestDataProvider */ public function testMapPaymentResponse(string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($responseData['VPosMessage'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['VPosMessage']['Amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['VPosMessage']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); + if ([] !== $responseData) { $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -107,63 +129,22 @@ public function testMapPaymentResponse(string $txType, array $responseData, arra $this->assertSame($expectedData, $actualData); } - /** - * @dataProvider refundTestDataProvider - */ - public function testMapRefundResponse(array $responseData, array $expectedData): void + public function testMapRefundResponse(): void { - $actualData = $this->responseDataMapper->mapRefundResponse($responseData); - - $this->assertArrayHasKey('all', $actualData); - $this->assertIsArray($actualData['all']); - $this->assertNotEmpty($actualData['all']); - unset($actualData['all']); - - ksort($actualData); - ksort($expectedData); - $this->assertSame($expectedData, $actualData); + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->mapRefundResponse([]); } - /** - * @dataProvider cancelTestDataProvider - */ - public function testMapCancelResponse(array $responseData, array $expectedData): void + public function testMapCancelResponse(): void { - $actualData = $this->responseDataMapper->mapCancelResponse($responseData); - - $this->assertArrayHasKey('all', $actualData); - $this->assertIsArray($actualData['all']); - $this->assertNotEmpty($actualData['all']); - unset($actualData['all']); - - ksort($actualData); - ksort($expectedData); - $this->assertSame($expectedData, $actualData); + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->mapCancelResponse([]); } - /** - * @dataProvider statusTestDataProvider - */ - public function testMapStatusResponse(array $responseData, array $expectedData): void + public function testMapStatusResponse(): void { - $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); - - $this->assertArrayHasKey('all', $actualData); - $this->assertIsArray($actualData['all']); - $this->assertNotEmpty($actualData['all']); - unset($actualData['all']); - - \ksort($expectedData); - \ksort($actualData); - $this->assertSame($expectedData, $actualData); + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->mapStatusResponse([]); } /** @@ -171,19 +152,76 @@ public function testMapStatusResponse(array $responseData, array $expectedData): */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if (isset($threeDResponseData['VPosMessage']['TransactionType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['VPosMessage']['TransactionType']) + ->willReturn($expectedData['transaction_type']); + } + + if ($threeDResponseData['ResponseCode'] === '00') { + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['VPosMessage']['TransactionSecurity'], $txType) + ->willReturn($expectedData['payment_model']); + + $amountMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $threeDResponseData, $paymentResponse): bool { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $threeDResponseData['VPosMessage']['Amount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $paymentResponse['VPosMessage']['Amount']; + } + + return false; + }), $txType) + ->willReturnCallback( + fn () => $expectedData['amount'] + ); + + $currencyMatcher = $this->atLeastOnce(); + $this->responseValueMapper->expects($currencyMatcher) + ->method('mapCurrency') + ->with($this->callback(function ($amount) use ($currencyMatcher, $threeDResponseData, $paymentResponse): bool { + if ($currencyMatcher->getInvocationCount() === 1) { + return $amount === $threeDResponseData['VPosMessage']['CurrencyCode']; + } + + if ($currencyMatcher->getInvocationCount() === 2) { + return $amount === $paymentResponse['VPosMessage']['CurrencyCode']; + } + + return false; + }), $txType) + ->willReturnCallback( + fn () => $expectedData['currency'] + ); + + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($paymentResponse['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + } + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -896,841 +934,4 @@ public static function threeDPaymentDataProvider(): array ], ]; } - - public static function statusTestDataProvider(): iterable - { - yield 'fail1' => [ - 'responseData' => [ - 'GetMerchantOrderDetailResponse' => [ - 'GetMerchantOrderDetailResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [], - ], - ], - ], - 'expectedData' => [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => null, - 'transaction_id' => null, - 'error_message' => null, - 'ref_ret_num' => null, - 'order_status' => null, - 'transaction_type' => null, - 'masked_number' => null, - 'first_amount' => null, - 'capture_amount' => null, - 'status' => 'declined', - 'error_code' => null, - 'status_detail' => null, - 'capture' => null, - 'capture_time' => null, - 'transaction_time' => null, - 'currency' => null, - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => null, - ], - ]; - yield 'success1' => [ - 'responseData' => [ - 'GetMerchantOrderDetailResponse' => [ - 'GetMerchantOrderDetailResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [ - 'OrderContract' => [ - 'IsSelected' => false, - 'IsSelectable' => true, - 'OrderId' => 114_293_600, - 'MerchantOrderId' => '2023070849CD', - 'MerchantId' => 496, - 'CardHolderName' => 'John Doe', - 'CardType' => 'MasterCard', - 'CardNumber' => '518896******2544', - 'OrderDate' => '2023-07-08T23:45:15.797', - 'OrderStatus' => 1, - 'LastOrderStatus' => 1, - 'OrderType' => 1, - 'TransactionStatus' => 1, - 'FirstAmount' => '1.01', - 'CancelAmount' => '0.00', - 'DrawbackAmount' => '0.00', - 'ClosedAmount' => '0.00', - 'FEC' => '0949', - 'VPSEntryMode' => 'ECOM', - 'InstallmentCount' => 0, - 'TransactionSecurity' => 3, - 'ResponseCode' => '00', - 'ResponseExplain' => 'İşlem gerçekleştirildi.', - 'EndOfDayStatus' => 2, - 'TransactionSide' => 'Auto', - 'CardHolderIPAddress' => '', - 'MerchantIPAddress' => '92.38.180.58', - 'MerchantUserName' => 'apitest', - 'ProvNumber' => '241839', - 'BatchId' => 491, - 'CardExpireDate' => '2506', - 'PosTerminalId' => 'VP008759', - 'Explain' => '', - 'Explain2' => '', - 'Explain3' => '', - 'RRN' => '318923298433', - 'Stan' => '298433', - 'UserName' => 'vposuser', - 'HostName' => 'STD8BOATEST2', - 'SystemDate' => '2023-07-08T23:45:15.8', - 'UpdateUserName' => 'vposuser', - 'UpdateHostName' => 'STD8BOATEST2', - 'UpdateSystemDate' => '2023-07-08T23:45:35.283', - 'EndOfDayDate' => null, - 'HostIP' => '172.20.8.85', - 'FECAmount' => '0', - 'IdentityTaxNumber' => '', - 'QueryId' => '0', - 'DebtId' => '0', - 'DebtorName' => '', - 'Period' => '', - 'SurchargeAmount' => '0', - 'SGKDebtAmount' => '0', - 'DeferringCount' => null, - ], - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => '2023070849CD', - 'auth_code' => '241839', - 'proc_return_code' => '00', - 'transaction_id' => '298433', - 'ref_ret_num' => '318923298433', - 'order_status' => 'PAYMENT_COMPLETED', - 'transaction_type' => null, - 'masked_number' => '518896******2544', - 'first_amount' => 1.01, - 'capture_amount' => 1.01, - 'status' => 'approved', - 'error_code' => null, - 'error_message' => null, - 'status_detail' => null, - 'capture' => true, - 'remote_order_id' => '114293600', - 'currency' => PosInterface::CURRENCY_TRY, - 'capture_time' => new \DateTimeImmutable('2023-07-08T23:45:35.283'), - 'transaction_time' => new \DateTimeImmutable('2023-07-08T23:45:15.797'), - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 0, - ], - ]; - yield 'tdv2_fail_hash_error' => [ - 'responseData' => [ - 'GetMerchantOrderDetailResponse' => [ - 'GetMerchantOrderDetailResult' => [ - 'Results' => [ - 'Result' => [ - 'ErrorMessage' => 'Şifrelenen veriler (Hashdata) uyuşmamaktadır.', - 'ErrorCode' => 'HashDataError', - 'IsFriendly' => true, - 'Severity' => 'BusinessError', - ], - ], - 'Success' => false, - 'Value' => [ - ], - ], - ], - ], - 'expectedData' => [ - 'auth_code' => null, - 'capture' => null, - 'capture_amount' => null, - 'currency' => null, - 'error_code' => 'HashDataError', - 'error_message' => 'Şifrelenen veriler (Hashdata) uyuşmamaktadır.', - 'first_amount' => null, - 'installment_count' => null, - 'masked_number' => null, - 'order_id' => null, - 'order_status' => null, - 'proc_return_code' => null, - 'ref_ret_num' => null, - 'refund_amount' => null, - 'status' => 'declined', - 'status_detail' => null, - 'transaction_id' => null, - 'transaction_type' => null, - 'transaction_time' => null, - 'capture_time' => null, - 'refund_time' => null, - 'cancel_time' => null, - ], - ]; - yield 'tdv2_success_tx_pay' => [ - 'responseData' => [ - 'GetMerchantOrderDetailResponse' => [ - 'GetMerchantOrderDetailResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [ - 'OrderContract' => [ - 'IsSelected' => false, - 'IsSelectable' => true, - 'OrderId' => 155768281, - 'MerchantOrderId' => '20240424C7A5', - 'MerchantId' => 496, - 'CardHolderName' => 'John Doe', - 'CardType' => 'MasterCard', - 'CardNumber' => '518896******2544', - 'OrderDate' => '2024-04-24T16:03:42.07', - 'OrderStatus' => 1, - 'LastOrderStatus' => 1, - 'OrderType' => 1, - 'TransactionStatus' => 1, - 'FirstAmount' => '10.01', - 'CancelAmount' => '0.00', - 'DrawbackAmount' => '0.00', - 'ClosedAmount' => '0.00', - 'FEC' => '0949', - 'VPSEntryMode' => 'ECOM', - 'InstallmentCount' => 0, - 'TransactionSecurity' => 3, - 'ResponseCode' => '00', - 'ResponseExplain' => 'İşlem gerçekleştirildi.', - 'EndOfDayStatus' => 1, - 'TransactionSide' => 'Auto', - 'CardHolderIPAddress' => '', - 'MerchantIPAddress' => '45.130.202.59', - 'MerchantUserName' => 'apitest', - 'ProvNumber' => '050990', - 'BatchId' => 545, - 'CardExpireDate' => '2506', - 'PosTerminalId' => 'VP008759', - 'Explain' => '', - 'Explain2' => '', - 'Explain3' => '', - 'RRN' => '411516539768', - 'Stan' => '539768', - 'UserName' => 'vposuser', - 'HostName' => 'STD8BOATEST1', - 'SystemDate' => '2024-04-24T16:03:42.077', - 'UpdateUserName' => 'vposuser', - 'UpdateHostName' => 'STD8BOATEST2', - 'UpdateSystemDate' => '2024-04-24T16:04:12.373', - 'EndOfDayDate' => null, - 'HostIP' => '172.20.8.84', - 'FECAmount' => '0', - 'IdentityTaxNumber' => '', - 'QueryId' => '0', - 'DebtId' => '0', - 'DebtorName' => '', - 'Period' => '', - 'SurchargeAmount' => '0', - 'SGKDebtAmount' => '0', - 'DeferringCount' => null, - ], - ], - ], - ], - ], - 'expectedData' => [ - 'auth_code' => '050990', - 'capture' => true, - 'capture_amount' => 10.01, - 'currency' => 'TRY', - 'error_code' => null, - 'error_message' => null, - 'first_amount' => 10.01, - 'installment_count' => 0, - 'masked_number' => '518896******2544', - 'order_id' => '20240424C7A5', - 'order_status' => 'PAYMENT_COMPLETED', - 'proc_return_code' => '00', - 'ref_ret_num' => '411516539768', - 'refund_amount' => null, - 'remote_order_id' => '155768281', - 'status' => 'approved', - 'status_detail' => null, - 'transaction_id' => '539768', - 'transaction_type' => null, - 'transaction_time' => new \DateTimeImmutable('2024-04-24T16:03:42.07'), - 'capture_time' => new \DateTimeImmutable('2024-04-24T16:04:12.373'), - 'refund_time' => null, - 'cancel_time' => null, - ], - ]; - yield 'tdv2_success_tx_pay_then_cancel' => [ - 'responseData' => [ - 'GetMerchantOrderDetailResponse' => [ - 'GetMerchantOrderDetailResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [ - 'OrderContract' => [ - 'IsSelected' => false, - 'IsSelectable' => true, - 'OrderId' => 155768281, - 'MerchantOrderId' => '20240424C7A5', - 'MerchantId' => 496, - 'CardHolderName' => 'John Doe', - 'CardType' => 'MasterCard', - 'CardNumber' => '518896******2544', - 'OrderDate' => '2024-04-24T16:03:42.07', - 'OrderStatus' => 1, - 'LastOrderStatus' => 6, - 'OrderType' => 1, - 'TransactionStatus' => 1, - 'FirstAmount' => '10.01', - 'CancelAmount' => '10.01', - 'DrawbackAmount' => '0.00', - 'ClosedAmount' => '0.00', - 'FEC' => '0949', - 'VPSEntryMode' => 'ECOM', - 'InstallmentCount' => 0, - 'TransactionSecurity' => 3, - 'ResponseCode' => '00', - 'ResponseExplain' => 'İşlem gerçekleştirildi.', - 'EndOfDayStatus' => 1, - 'TransactionSide' => 'Auto', - 'CardHolderIPAddress' => '', - 'MerchantIPAddress' => '45.130.202.59', - 'MerchantUserName' => 'apitest', - 'ProvNumber' => '050990', - 'BatchId' => 545, - 'CardExpireDate' => '2506', - 'PosTerminalId' => 'VP008759', - 'Explain' => '', - 'Explain2' => '', - 'Explain3' => '', - 'RRN' => '411516539768', - 'Stan' => '539768', - 'UserName' => 'vposuser', - 'HostName' => 'STD8BOATEST1', - 'SystemDate' => '2024-04-24T16:03:42.077', - 'UpdateUserName' => 'webgate', - 'UpdateHostName' => 'STD8BOATEST1', - 'UpdateSystemDate' => '2024-04-24T16:09:27.067', - 'EndOfDayDate' => null, - 'HostIP' => '172.20.8.84', - 'FECAmount' => '0', - 'IdentityTaxNumber' => '', - 'QueryId' => '0', - 'DebtId' => '0', - 'DebtorName' => '', - 'Period' => '', - 'SurchargeAmount' => '0', - 'SGKDebtAmount' => '0', - 'DeferringCount' => null, - ], - ], - ], - ], - ], - 'expectedData' => [ - 'auth_code' => '050990', - 'capture' => null, - 'capture_amount' => null, - 'currency' => 'TRY', - 'error_code' => null, - 'error_message' => null, - 'first_amount' => 10.01, - 'installment_count' => 0, - 'masked_number' => '518896******2544', - 'order_id' => '20240424C7A5', - 'order_status' => 'CANCELED', - 'proc_return_code' => '00', - 'ref_ret_num' => '411516539768', - 'refund_amount' => null, - 'remote_order_id' => '155768281', - 'status' => 'approved', - 'status_detail' => null, - 'transaction_id' => '539768', - 'transaction_type' => null, - 'transaction_time' => new \DateTimeImmutable('2024-04-24T16:03:42.07'), - 'capture_time' => null, - 'refund_time' => null, - 'cancel_time' => new \DateTimeImmutable('2024-04-24T16:09:27.067'), - ], - ]; - yield 'tdv2_success_tx_pay_then_refund' => [ - 'responseData' => [ - 'GetMerchantOrderDetailResponse' => [ - 'GetMerchantOrderDetailResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [ - 'OrderContract' => [ - 'IsSelected' => false, - 'IsSelectable' => true, - 'OrderId' => 155768298, - 'MerchantOrderId' => '202404240DEE', - 'MerchantId' => 496, - 'CardHolderName' => 'John Doe', - 'CardType' => 'MasterCard', - 'CardNumber' => '518896******2544', - 'OrderDate' => '2024-04-24T16:33:44.01', - 'OrderStatus' => 1, - 'LastOrderStatus' => 4, - 'OrderType' => 1, - 'TransactionStatus' => 1, - 'FirstAmount' => '10.01', - 'CancelAmount' => '0.00', - 'DrawbackAmount' => '10.01', - 'ClosedAmount' => '0.00', - 'FEC' => '0949', - 'VPSEntryMode' => 'ECOM', - 'InstallmentCount' => 0, - 'TransactionSecurity' => 1, - 'ResponseCode' => '00', - 'ResponseExplain' => 'İşlem gerçekleştirildi.', - 'EndOfDayStatus' => 2, - 'TransactionSide' => 'Auto', - 'CardHolderIPAddress' => '', - 'MerchantIPAddress' => '45.130.202.55', - 'MerchantUserName' => 'apitest', - 'ProvNumber' => '051004', - 'BatchId' => 545, - 'CardExpireDate' => '2506', - 'PosTerminalId' => 'VP008759', - 'Explain' => '', - 'Explain2' => '', - 'Explain3' => '', - 'RRN' => '411516539788', - 'Stan' => '539788', - 'UserName' => 'vposuser', - 'HostName' => 'STD8BOATEST2', - 'SystemDate' => '2024-04-24T16:33:44.02', - 'UpdateUserName' => 'webgate', - 'UpdateHostName' => 'STD8BOATEST2', - 'UpdateSystemDate' => '2024-04-26T10:59:49.443', - 'EndOfDayDate' => '2024-04-24T17:08:46.15', - 'HostIP' => '172.20.8.85', - 'FECAmount' => '0', - 'IdentityTaxNumber' => '', - 'QueryId' => '0', - 'DebtId' => '0', - 'DebtorName' => '', - 'Period' => '', - 'SurchargeAmount' => '0', - 'SGKDebtAmount' => '0', - 'DeferringCount' => null, - ], - ], - ], - ], - ], - 'expectedData' => [ - 'auth_code' => '051004', - 'capture' => null, - 'capture_amount' => null, - 'currency' => 'TRY', - 'error_code' => null, - 'error_message' => null, - 'first_amount' => 10.01, - 'installment_count' => 0, - 'masked_number' => '518896******2544', - 'order_id' => '202404240DEE', - 'order_status' => 'FULLY_REFUNDED', - 'proc_return_code' => '00', - 'ref_ret_num' => '411516539788', - 'refund_amount' => null, - 'remote_order_id' => '155768298', - 'status' => 'approved', - 'status_detail' => null, - 'transaction_id' => '539788', - 'transaction_type' => null, - 'transaction_time' => new \DateTimeImmutable('2024-04-24T16:33:44.01'), - 'capture_time' => null, - 'refund_time' => new \DateTimeImmutable('2024-04-26T10:59:49.443'), - 'cancel_time' => null, - ], - ]; - } - - public static function cancelTestDataProvider(): iterable - { - yield 'success1' => [ - 'responseData' => [ - 'SaleReversalResponse' => [ - 'SaleReversalResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [ - 'IsEnrolled' => false, - 'IsVirtual' => false, - 'ProvisionNumber' => '241839', - 'RRN' => '318923298433', - 'Stan' => '298433', - 'ResponseCode' => '00', - 'ResponseMessage' => 'OTORİZASYON VERİLDİ', - 'OrderId' => '114293600', - 'TransactionTime' => '2023-07-08T23:45:15.797', - 'MerchantOrderId' => '2023070849CD', - 'CurrencyCode' => '0949', - 'MerchantId' => null, - 'BusinessKey' => '202208456498416947', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => '2023070849CD', - 'auth_code' => '241839', - 'proc_return_code' => '00', - 'transaction_id' => '298433', - 'currency' => PosInterface::CURRENCY_TRY, - 'error_message' => null, - 'ref_ret_num' => '318923298433', - 'status' => 'approved', - 'error_code' => null, - 'status_detail' => null, - 'remote_order_id' => '114293600', - ], - ]; - yield 'fail1' => [ - 'responseData' => [ - 'SaleReversalResponse' => [ - 'SaleReversalResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [ - 'IsEnrolled' => false, - 'IsVirtual' => false, - 'OrderId' => 0, - 'TransactionTime' => '0001-01-01T00:00:00', - 'MerchantId' => null, - 'BusinessKey' => '202307089999000000009015473', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => null, - 'transaction_id' => null, - 'currency' => null, - 'error_message' => null, - 'ref_ret_num' => null, - 'status' => 'declined', - 'error_code' => null, - 'status_detail' => null, - ], - ]; - yield 'fail_already_cancelled' => [ - 'responseData' => [ - 'SaleReversalResponse' => [ - 'SaleReversalResult' => [ - 'Results' => [ - 'Result' => [ - 0 => [ - 'ErrorMessage' => 'İşlem daha önce iptal edilmiştir.', - 'ErrorCode' => '21', - 'IsFriendly' => null, - 'Severity' => 'Error', - ], - 1 => [ - 'ErrorMessage' => 'İşleminizi şu an gerçekleştiremiyoruz, lütfen daha sonra tekrar deneyiniz.', - 'ErrorCode' => 'IntegrationFatalException', - 'IsFriendly' => null, - 'Severity' => 'Error', - ], - ], - ], - 'Success' => null, - 'Value' => [ - 'IsEnrolled' => null, - 'IsVirtual' => null, - 'ResponseCode' => 'DbLayerError', - 'OrderId' => 0, - 'TransactionTime' => '0001-01-01T00:00:00', - 'MerchantId' => null, - 'BusinessKey' => '0', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => 'DbLayerError', - 'transaction_id' => null, - 'currency' => null, - 'error_message' => 'İşlem daha önce iptal edilmiştir.', - 'ref_ret_num' => null, - 'status' => 'declined', - 'error_code' => '21', - 'status_detail' => null, - ], - ]; - yield 'tdv2_fail_already_cancelled' => [ - 'responseData' => [ - 'SaleReversalResponse' => [ - 'SaleReversalResult' => [ - 'Results' => [ - 'Result' => [ - 'ErrorMessage' => 'İşlem daha önce iptal edilmiştir.', - 'ErrorCode' => '21', - 'IsFriendly' => true, - 'Severity' => 'BusinessError', - ], - ], - 'Success' => false, - 'Value' => [ - 'IsEnrolled' => false, - 'IsVirtual' => false, - 'ResponseCode' => 'DbLayerError', - 'OrderId' => 0, - 'TransactionTime' => '0001-01-01T00:00:00', - 'MerchantId' => null, - 'BusinessKey' => '0', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => 'DbLayerError', - 'transaction_id' => null, - 'currency' => null, - 'error_message' => 'İşlem daha önce iptal edilmiştir.', - 'ref_ret_num' => null, - 'status' => 'declined', - 'error_code' => '21', - 'status_detail' => null, - ], - ]; - } - - public static function refundTestDataProvider(): iterable - { - yield 'fail1' => [ - 'responseData' => [ - 'PartialDrawbackResponse' => [ - 'PartialDrawbackResult' => [ - 'Results' => [], - 'Success' => null, - 'Value' => [ - 'IsEnrolled' => null, - 'IsVirtual' => null, - 'RRN' => '319013298460', - 'Stan' => '298460', - 'ResponseCode' => '28', - 'ResponseMessage' => 'İptal Edilen İşlem İade Yapılamaz', - 'OrderId' => 114_293_625, - 'TransactionTime' => '2023-07-09T13:38:00.9396957', - 'MerchantOrderId' => '202307093C2D', - 'CurrencyCode' => '0949', - 'MerchantId' => null, - 'BusinessKey' => '202307099999000000003235752', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => '202307093C2D', - 'auth_code' => null, - 'proc_return_code' => '28', - 'transaction_id' => '298460', - 'currency' => null, - 'error_message' => 'İptal Edilen İşlem İade Yapılamaz', - 'ref_ret_num' => '319013298460', - 'status' => 'declined', - 'error_code' => '28', - 'status_detail' => null, - 'remote_order_id' => '114293625', - ], - ]; - - yield 'fail2' => [ - 'responseData' => [ - 'PartialDrawbackResponse' => [ - 'PartialDrawbackResult' => [ - 'Results' => [], - 'Success' => null, - 'Value' => [ - 'IsEnrolled' => null, - 'IsVirtual' => null, - 'OrderId' => 0, - 'TransactionTime' => '0001-01-01T00:00:00', - 'MerchantId' => null, - 'BusinessKey' => '202307099999000000003252739', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => null, - 'transaction_id' => null, - 'currency' => null, - 'error_message' => null, - 'ref_ret_num' => null, - 'status' => 'declined', - 'error_code' => null, - 'status_detail' => null, - ], - ]; - yield 'tdv2_fail_partial_refund_not_allowed' => [ - 'responseData' => [ - 'PartialDrawbackResponse' => [ - 'PartialDrawbackResult' => [ - 'Results' => [ - 'Result' => [ - 'ErrorMessage' => 'Kısmi iade işlemi, satışla aynı gün içerisindeyse tutarın tamamı için yapılamaz. Tutarın tamamı için iptal işlemi yapabilirsiniz.', - 'IsFriendly' => true, - 'Severity' => 'BusinessError', - ], - ], - 'Success' => false, - 'Value' => [ - 'IsEnrolled' => false, - 'IsVirtual' => false, - 'ResponseCode' => 'DbLayerError', - 'OrderId' => 0, - 'TransactionTime' => '0001-01-01T00:00:00', - 'MerchantId' => null, - 'BusinessKey' => '0', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => null, - 'auth_code' => null, - 'proc_return_code' => 'DbLayerError', - 'transaction_id' => null, - 'currency' => null, - 'ref_ret_num' => null, - 'status' => 'declined', - 'error_code' => 'DbLayerError', - 'error_message' => 'Kısmi iade işlemi, satışla aynı gün içerisindeyse tutarın tamamı için yapılamaz. Tutarın tamamı için iptal işlemi yapabilirsiniz.', - 'status_detail' => null, - ], - ]; - - yield 'success1' => [ - 'responseData' => [ - 'PartialDrawbackResponse' => [ - 'PartialDrawbackResult' => [ - 'Results' => [], - 'Success' => null, - 'Value' => [ - 'IsEnrolled' => null, - 'IsVirtual' => null, - 'ProvisionNumber' => '241859', - 'RRN' => '319014298463', - 'Stan' => '298463', - 'ResponseCode' => '00', - 'ResponseMessage' => 'OTORİZASYON VERİLDİ', - 'OrderId' => 114_293_626, - 'TransactionTime' => '2023-07-09T14:07:41.9306297', - 'MerchantOrderId' => '202307091285', - 'CurrencyCode' => '0949', - 'MerchantId' => null, - 'BusinessKey' => '202307099999000000003252996', - ], - ], - ], - ], - 'expectedData' => [ - 'order_id' => '202307091285', - 'auth_code' => '241859', - 'proc_return_code' => '00', - 'transaction_id' => '298463', - 'currency' => PosInterface::CURRENCY_TRY, - 'error_message' => null, - 'ref_ret_num' => '319014298463', - 'status' => 'approved', - 'error_code' => null, - 'status_detail' => null, - 'remote_order_id' => '114293626', - ], - ]; - - yield 'tdv2_success_full_refund' => [ - 'responseData' => [ - 'DrawBackResponse' => [ - 'DrawBackResult' => [ - 'Results' => [], - 'Success' => true, - 'Value' => [ - 'IsEnrolled' => false, - 'IsVirtual' => false, - 'ProvisionNumber' => '050823', - 'RRN' => '411415539590', - 'Stan' => '539590', - 'ResponseCode' => '00', - 'ResponseMessage' => 'OTORİZASYON VERİLDİ', - 'OrderId' => 155767855, - 'TransactionTime' => '2024-04-23T15:19:15.7471578', - 'MerchantOrderId' => '202404229EAC', - 'CurrencyCode' => '0949', - 'MerchantId' => null, - 'BusinessKey' => '202404239999000000013631520', - ], - ], - ], - ], - 'expectedData' => [ - 'auth_code' => '050823', - 'currency' => 'TRY', - 'error_code' => null, - 'error_message' => null, - 'order_id' => '202404229EAC', - 'proc_return_code' => '00', - 'ref_ret_num' => '411415539590', - 'remote_order_id' => '155767855', - 'status' => 'approved', - 'status_detail' => null, - 'transaction_id' => '539590', - ], - ]; - yield 'tdv2_success1' => [ - 'responseData' => [ - 'PartialDrawbackResponse' => [ - 'PartialDrawbackResult' => [ - 'Results' => [ - - ], - 'Success' => true, - 'Value' => [ - 'IsEnrolled' => false, - 'IsVirtual' => false, - 'ProvisionNumber' => '050569', - 'RRN' => '411220539231', - 'Stan' => '539231', - 'ResponseCode' => '00', - 'ResponseMessage' => 'OTORİZASYON VERİLDİ', - 'OrderId' => 155767811, - 'TransactionTime' => '2024-04-21T20:09:21.3829986', - 'MerchantOrderId' => '202404218A62', - 'CurrencyCode' => '0949', - 'MerchantId' => null, - 'BusinessKey' => '202404219999000000009542260', - ], - ], - ], - ], - 'expectedData' => [ - 'auth_code' => '050569', - 'currency' => 'TRY', - 'error_code' => null, - 'error_message' => null, - 'order_id' => '202404218A62', - 'proc_return_code' => '00', - 'ref_ret_num' => '411220539231', - 'remote_order_id' => '155767811', - 'status' => 'approved', - 'status_detail' => null, - 'transaction_id' => '539231', - ], - ]; - } } diff --git a/tests/Unit/DataMapper/ResponseDataMapper/KuveytSoapApiPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/KuveytSoapApiPosResponseDataMapperTest.php new file mode 100644 index 00000000..95615fe7 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseDataMapper/KuveytSoapApiPosResponseDataMapperTest.php @@ -0,0 +1,1091 @@ +logger = $this->createMock(LoggerInterface::class); + + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); + + $this->responseDataMapper = new KuveytSoapApiPosResponseDataMapper( + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger + ); + } + + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(KuveytSoapApiPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + + /** + * @testWith [null, false] + * ["", false] + * ["HashDataError", false] + * ["00", true] + * + */ + public function testIs3dAuthSuccess(?string $mdStatus, bool $expected): void + { + $actual = $this->responseDataMapper->is3dAuthSuccess($mdStatus); + $this->assertSame($expected, $actual); + } + + + /** + * @testWith [[], null] + * [{"ResponseCode": "00"}, "00"] + * + */ + public function testExtractMdStatus(array $responseData, ?string $expected): void + { + $actual = $this->responseDataMapper->extractMdStatus($responseData); + $this->assertSame($expected, $actual); + } + + public function testMapPaymentResponse(): void + { + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->mapPaymentResponse( + [], + PosInterface::TX_TYPE_PAY_AUTH, + [] + ); + } + + /** + * @dataProvider refundTestDataProvider + */ + public function testMapRefundResponse(array $responseData, array $expectedData): void + { + $txType = PosInterface::TX_TYPE_REFUND; + $drawbackResult = $responseData['PartialDrawbackResponse']['PartialDrawbackResult'] ?? $responseData['DrawBackResponse']['DrawBackResult']; + + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($drawbackResult['Value']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + + $actualData = $this->responseDataMapper->mapRefundResponse($responseData); + + $this->assertArrayHasKey('all', $actualData); + $this->assertIsArray($actualData['all']); + $this->assertNotEmpty($actualData['all']); + unset($actualData['all']); + + ksort($actualData); + ksort($expectedData); + $this->assertSame($expectedData, $actualData); + } + + /** + * @dataProvider cancelTestDataProvider + */ + public function testMapCancelResponse(array $responseData, array $expectedData): void + { + $txType = PosInterface::TX_TYPE_CANCEL; + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['SaleReversalResponse']['SaleReversalResult']['Value']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + + $actualData = $this->responseDataMapper->mapCancelResponse($responseData); + + $this->assertArrayHasKey('all', $actualData); + $this->assertIsArray($actualData['all']); + $this->assertNotEmpty($actualData['all']); + unset($actualData['all']); + + ksort($actualData); + ksort($expectedData); + $this->assertSame($expectedData, $actualData); + } + + /** + * @dataProvider statusTestDataProvider + */ + public function testMapStatusResponse(array $responseData, array $expectedData): void + { + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $txType = PosInterface::TX_TYPE_STATUS; + $orderContract = $responseData['GetMerchantOrderDetailResponse']['GetMerchantOrderDetailResult']['Value']['OrderContract']; + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($orderContract['LastOrderStatus']) + ->willReturn($expectedData['order_status']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($orderContract['FEC'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($orderContract['FirstAmount'], $txType) + ->willReturn($expectedData['first_amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($orderContract['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $dateTimeMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use ($dateTimeMatcher, $orderContract): bool { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $dateTime === $orderContract['OrderDate']; + } + + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $dateTime === $orderContract['UpdateSystemDate']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['capture_time'] ?? $expectedData['cancel_time'] ?? $expectedData['refund_time']; + } + + return false; + } + ); + } + + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); + + $this->assertArrayHasKey('all', $actualData); + $this->assertIsArray($actualData['all']); + $this->assertNotEmpty($actualData['all']); + unset($actualData['all']); + + \ksort($expectedData); + \ksort($actualData); + $this->assertSame($expectedData, $actualData); + } + + public function testMap3DPaymentData(): void + { + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->map3DPaymentData( + [], + [], + PosInterface::TX_TYPE_PAY_AUTH, + [] + ); + } + + public function testMap3DPayResponseData(): void + { + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->map3DPayResponseData([], PosInterface::TX_TYPE_PAY_AUTH, []); + } + + public function testMap3DHostResponseData(): void + { + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->map3DHostResponseData([], PosInterface::TX_TYPE_PAY_AUTH, []); + } + + public function testMapHistoryResponse(): void + { + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->mapHistoryResponse([]); + } + + public function testMapOrderHistoryResponse(): void + { + $this->expectException(NotImplementedException::class); + $this->responseDataMapper->mapOrderHistoryResponse([]); + } + + public static function statusTestDataProvider(): \Generator + { + yield 'fail1' => [ + 'responseData' => [ + 'GetMerchantOrderDetailResponse' => [ + 'GetMerchantOrderDetailResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [], + ], + ], + ], + 'expectedData' => [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => null, + 'transaction_id' => null, + 'error_message' => null, + 'ref_ret_num' => null, + 'order_status' => null, + 'transaction_type' => null, + 'masked_number' => null, + 'first_amount' => null, + 'capture_amount' => null, + 'status' => 'declined', + 'error_code' => null, + 'status_detail' => null, + 'capture' => null, + 'capture_time' => null, + 'transaction_time' => null, + 'currency' => null, + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => null, + ], + ]; + yield 'success1' => [ + 'responseData' => [ + 'GetMerchantOrderDetailResponse' => [ + 'GetMerchantOrderDetailResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [ + 'OrderContract' => [ + 'IsSelected' => false, + 'IsSelectable' => true, + 'OrderId' => 114_293_600, + 'MerchantOrderId' => '2023070849CD', + 'MerchantId' => 496, + 'CardHolderName' => 'John Doe', + 'CardType' => 'MasterCard', + 'CardNumber' => '518896******2544', + 'OrderDate' => '2023-07-08T23:45:15.797', + 'OrderStatus' => 1, + 'LastOrderStatus' => 1, + 'OrderType' => 1, + 'TransactionStatus' => 1, + 'FirstAmount' => '1.01', + 'CancelAmount' => '0.00', + 'DrawbackAmount' => '0.00', + 'ClosedAmount' => '0.00', + 'FEC' => '0949', + 'VPSEntryMode' => 'ECOM', + 'InstallmentCount' => 0, + 'TransactionSecurity' => 3, + 'ResponseCode' => '00', + 'ResponseExplain' => 'İşlem gerçekleştirildi.', + 'EndOfDayStatus' => 2, + 'TransactionSide' => 'Auto', + 'CardHolderIPAddress' => '', + 'MerchantIPAddress' => '92.38.180.58', + 'MerchantUserName' => 'apitest', + 'ProvNumber' => '241839', + 'BatchId' => 491, + 'CardExpireDate' => '2506', + 'PosTerminalId' => 'VP008759', + 'Explain' => '', + 'Explain2' => '', + 'Explain3' => '', + 'RRN' => '318923298433', + 'Stan' => '298433', + 'UserName' => 'vposuser', + 'HostName' => 'STD8BOATEST2', + 'SystemDate' => '2023-07-08T23:45:15.8', + 'UpdateUserName' => 'vposuser', + 'UpdateHostName' => 'STD8BOATEST2', + 'UpdateSystemDate' => '2023-07-08T23:45:35.283', + 'EndOfDayDate' => null, + 'HostIP' => '172.20.8.85', + 'FECAmount' => '0', + 'IdentityTaxNumber' => '', + 'QueryId' => '0', + 'DebtId' => '0', + 'DebtorName' => '', + 'Period' => '', + 'SurchargeAmount' => '0', + 'SGKDebtAmount' => '0', + 'DeferringCount' => null, + ], + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => '2023070849CD', + 'auth_code' => '241839', + 'proc_return_code' => '00', + 'transaction_id' => '298433', + 'ref_ret_num' => '318923298433', + 'order_status' => 'PAYMENT_COMPLETED', + 'transaction_type' => null, + 'masked_number' => '518896******2544', + 'first_amount' => 1.01, + 'capture_amount' => 1.01, + 'status' => 'approved', + 'error_code' => null, + 'error_message' => null, + 'status_detail' => null, + 'capture' => true, + 'remote_order_id' => '114293600', + 'currency' => PosInterface::CURRENCY_TRY, + 'capture_time' => new \DateTimeImmutable('2023-07-08T23:45:35.283'), + 'transaction_time' => new \DateTimeImmutable('2023-07-08T23:45:15.797'), + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 0, + ], + ]; + yield 'tdv2_fail_hash_error' => [ + 'responseData' => [ + 'GetMerchantOrderDetailResponse' => [ + 'GetMerchantOrderDetailResult' => [ + 'Results' => [ + 'Result' => [ + 'ErrorMessage' => 'Şifrelenen veriler (Hashdata) uyuşmamaktadır.', + 'ErrorCode' => 'HashDataError', + 'IsFriendly' => true, + 'Severity' => 'BusinessError', + ], + ], + 'Success' => false, + 'Value' => [ + ], + ], + ], + ], + 'expectedData' => [ + 'auth_code' => null, + 'capture' => null, + 'capture_amount' => null, + 'currency' => null, + 'error_code' => 'HashDataError', + 'error_message' => 'Şifrelenen veriler (Hashdata) uyuşmamaktadır.', + 'first_amount' => null, + 'installment_count' => null, + 'masked_number' => null, + 'order_id' => null, + 'order_status' => null, + 'proc_return_code' => null, + 'ref_ret_num' => null, + 'refund_amount' => null, + 'status' => 'declined', + 'status_detail' => null, + 'transaction_id' => null, + 'transaction_type' => null, + 'transaction_time' => null, + 'capture_time' => null, + 'refund_time' => null, + 'cancel_time' => null, + ], + ]; + yield 'tdv2_success_tx_pay' => [ + 'responseData' => [ + 'GetMerchantOrderDetailResponse' => [ + 'GetMerchantOrderDetailResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [ + 'OrderContract' => [ + 'IsSelected' => false, + 'IsSelectable' => true, + 'OrderId' => 155768281, + 'MerchantOrderId' => '20240424C7A5', + 'MerchantId' => 496, + 'CardHolderName' => 'John Doe', + 'CardType' => 'MasterCard', + 'CardNumber' => '518896******2544', + 'OrderDate' => '2024-04-24T16:03:42.07', + 'OrderStatus' => 1, + 'LastOrderStatus' => 1, + 'OrderType' => 1, + 'TransactionStatus' => 1, + 'FirstAmount' => '10.01', + 'CancelAmount' => '0.00', + 'DrawbackAmount' => '0.00', + 'ClosedAmount' => '0.00', + 'FEC' => '0949', + 'VPSEntryMode' => 'ECOM', + 'InstallmentCount' => 0, + 'TransactionSecurity' => 3, + 'ResponseCode' => '00', + 'ResponseExplain' => 'İşlem gerçekleştirildi.', + 'EndOfDayStatus' => 1, + 'TransactionSide' => 'Auto', + 'CardHolderIPAddress' => '', + 'MerchantIPAddress' => '45.130.202.59', + 'MerchantUserName' => 'apitest', + 'ProvNumber' => '050990', + 'BatchId' => 545, + 'CardExpireDate' => '2506', + 'PosTerminalId' => 'VP008759', + 'Explain' => '', + 'Explain2' => '', + 'Explain3' => '', + 'RRN' => '411516539768', + 'Stan' => '539768', + 'UserName' => 'vposuser', + 'HostName' => 'STD8BOATEST1', + 'SystemDate' => '2024-04-24T16:03:42.077', + 'UpdateUserName' => 'vposuser', + 'UpdateHostName' => 'STD8BOATEST2', + 'UpdateSystemDate' => '2024-04-24T16:04:12.373', + 'EndOfDayDate' => null, + 'HostIP' => '172.20.8.84', + 'FECAmount' => '0', + 'IdentityTaxNumber' => '', + 'QueryId' => '0', + 'DebtId' => '0', + 'DebtorName' => '', + 'Period' => '', + 'SurchargeAmount' => '0', + 'SGKDebtAmount' => '0', + 'DeferringCount' => null, + ], + ], + ], + ], + ], + 'expectedData' => [ + 'auth_code' => '050990', + 'capture' => true, + 'capture_amount' => 10.01, + 'currency' => 'TRY', + 'error_code' => null, + 'error_message' => null, + 'first_amount' => 10.01, + 'installment_count' => 0, + 'masked_number' => '518896******2544', + 'order_id' => '20240424C7A5', + 'order_status' => 'PAYMENT_COMPLETED', + 'proc_return_code' => '00', + 'ref_ret_num' => '411516539768', + 'refund_amount' => null, + 'remote_order_id' => '155768281', + 'status' => 'approved', + 'status_detail' => null, + 'transaction_id' => '539768', + 'transaction_type' => null, + 'transaction_time' => new \DateTimeImmutable('2024-04-24T16:03:42.07'), + 'capture_time' => new \DateTimeImmutable('2024-04-24T16:04:12.373'), + 'refund_time' => null, + 'cancel_time' => null, + ], + ]; + yield 'tdv2_success_tx_pay_then_cancel' => [ + 'responseData' => [ + 'GetMerchantOrderDetailResponse' => [ + 'GetMerchantOrderDetailResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [ + 'OrderContract' => [ + 'IsSelected' => false, + 'IsSelectable' => true, + 'OrderId' => 155768281, + 'MerchantOrderId' => '20240424C7A5', + 'MerchantId' => 496, + 'CardHolderName' => 'John Doe', + 'CardType' => 'MasterCard', + 'CardNumber' => '518896******2544', + 'OrderDate' => '2024-04-24T16:03:42.07', + 'OrderStatus' => 1, + 'LastOrderStatus' => 6, + 'OrderType' => 1, + 'TransactionStatus' => 1, + 'FirstAmount' => '10.01', + 'CancelAmount' => '10.01', + 'DrawbackAmount' => '0.00', + 'ClosedAmount' => '0.00', + 'FEC' => '0949', + 'VPSEntryMode' => 'ECOM', + 'InstallmentCount' => 0, + 'TransactionSecurity' => 3, + 'ResponseCode' => '00', + 'ResponseExplain' => 'İşlem gerçekleştirildi.', + 'EndOfDayStatus' => 1, + 'TransactionSide' => 'Auto', + 'CardHolderIPAddress' => '', + 'MerchantIPAddress' => '45.130.202.59', + 'MerchantUserName' => 'apitest', + 'ProvNumber' => '050990', + 'BatchId' => 545, + 'CardExpireDate' => '2506', + 'PosTerminalId' => 'VP008759', + 'Explain' => '', + 'Explain2' => '', + 'Explain3' => '', + 'RRN' => '411516539768', + 'Stan' => '539768', + 'UserName' => 'vposuser', + 'HostName' => 'STD8BOATEST1', + 'SystemDate' => '2024-04-24T16:03:42.077', + 'UpdateUserName' => 'webgate', + 'UpdateHostName' => 'STD8BOATEST1', + 'UpdateSystemDate' => '2024-04-24T16:09:27.067', + 'EndOfDayDate' => null, + 'HostIP' => '172.20.8.84', + 'FECAmount' => '0', + 'IdentityTaxNumber' => '', + 'QueryId' => '0', + 'DebtId' => '0', + 'DebtorName' => '', + 'Period' => '', + 'SurchargeAmount' => '0', + 'SGKDebtAmount' => '0', + 'DeferringCount' => null, + ], + ], + ], + ], + ], + 'expectedData' => [ + 'auth_code' => '050990', + 'capture' => null, + 'capture_amount' => null, + 'currency' => 'TRY', + 'error_code' => null, + 'error_message' => null, + 'first_amount' => 10.01, + 'installment_count' => 0, + 'masked_number' => '518896******2544', + 'order_id' => '20240424C7A5', + 'order_status' => 'CANCELED', + 'proc_return_code' => '00', + 'ref_ret_num' => '411516539768', + 'refund_amount' => null, + 'remote_order_id' => '155768281', + 'status' => 'approved', + 'status_detail' => null, + 'transaction_id' => '539768', + 'transaction_type' => null, + 'transaction_time' => new \DateTimeImmutable('2024-04-24T16:03:42.07'), + 'capture_time' => null, + 'refund_time' => null, + 'cancel_time' => new \DateTimeImmutable('2024-04-24T16:09:27.067'), + ], + ]; + yield 'tdv2_success_tx_pay_then_refund' => [ + 'responseData' => [ + 'GetMerchantOrderDetailResponse' => [ + 'GetMerchantOrderDetailResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [ + 'OrderContract' => [ + 'IsSelected' => false, + 'IsSelectable' => true, + 'OrderId' => 155768298, + 'MerchantOrderId' => '202404240DEE', + 'MerchantId' => 496, + 'CardHolderName' => 'John Doe', + 'CardType' => 'MasterCard', + 'CardNumber' => '518896******2544', + 'OrderDate' => '2024-04-24T16:33:44.01', + 'OrderStatus' => 1, + 'LastOrderStatus' => 4, + 'OrderType' => 1, + 'TransactionStatus' => 1, + 'FirstAmount' => '10.01', + 'CancelAmount' => '0.00', + 'DrawbackAmount' => '10.01', + 'ClosedAmount' => '0.00', + 'FEC' => '0949', + 'VPSEntryMode' => 'ECOM', + 'InstallmentCount' => 0, + 'TransactionSecurity' => 1, + 'ResponseCode' => '00', + 'ResponseExplain' => 'İşlem gerçekleştirildi.', + 'EndOfDayStatus' => 2, + 'TransactionSide' => 'Auto', + 'CardHolderIPAddress' => '', + 'MerchantIPAddress' => '45.130.202.55', + 'MerchantUserName' => 'apitest', + 'ProvNumber' => '051004', + 'BatchId' => 545, + 'CardExpireDate' => '2506', + 'PosTerminalId' => 'VP008759', + 'Explain' => '', + 'Explain2' => '', + 'Explain3' => '', + 'RRN' => '411516539788', + 'Stan' => '539788', + 'UserName' => 'vposuser', + 'HostName' => 'STD8BOATEST2', + 'SystemDate' => '2024-04-24T16:33:44.02', + 'UpdateUserName' => 'webgate', + 'UpdateHostName' => 'STD8BOATEST2', + 'UpdateSystemDate' => '2024-04-26T10:59:49.443', + 'EndOfDayDate' => '2024-04-24T17:08:46.15', + 'HostIP' => '172.20.8.85', + 'FECAmount' => '0', + 'IdentityTaxNumber' => '', + 'QueryId' => '0', + 'DebtId' => '0', + 'DebtorName' => '', + 'Period' => '', + 'SurchargeAmount' => '0', + 'SGKDebtAmount' => '0', + 'DeferringCount' => null, + ], + ], + ], + ], + ], + 'expectedData' => [ + 'auth_code' => '051004', + 'capture' => null, + 'capture_amount' => null, + 'currency' => 'TRY', + 'error_code' => null, + 'error_message' => null, + 'first_amount' => 10.01, + 'installment_count' => 0, + 'masked_number' => '518896******2544', + 'order_id' => '202404240DEE', + 'order_status' => 'FULLY_REFUNDED', + 'proc_return_code' => '00', + 'ref_ret_num' => '411516539788', + 'refund_amount' => null, + 'remote_order_id' => '155768298', + 'status' => 'approved', + 'status_detail' => null, + 'transaction_id' => '539788', + 'transaction_type' => null, + 'transaction_time' => new \DateTimeImmutable('2024-04-24T16:33:44.01'), + 'capture_time' => null, + 'refund_time' => new \DateTimeImmutable('2024-04-26T10:59:49.443'), + 'cancel_time' => null, + ], + ]; + } + + public static function cancelTestDataProvider(): \Generator + { + yield 'success1' => [ + 'responseData' => [ + 'SaleReversalResponse' => [ + 'SaleReversalResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [ + 'IsEnrolled' => false, + 'IsVirtual' => false, + 'ProvisionNumber' => '241839', + 'RRN' => '318923298433', + 'Stan' => '298433', + 'ResponseCode' => '00', + 'ResponseMessage' => 'OTORİZASYON VERİLDİ', + 'OrderId' => '114293600', + 'TransactionTime' => '2023-07-08T23:45:15.797', + 'MerchantOrderId' => '2023070849CD', + 'CurrencyCode' => '0949', + 'MerchantId' => null, + 'BusinessKey' => '202208456498416947', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => '2023070849CD', + 'auth_code' => '241839', + 'proc_return_code' => '00', + 'transaction_id' => '298433', + 'currency' => PosInterface::CURRENCY_TRY, + 'error_message' => null, + 'ref_ret_num' => '318923298433', + 'status' => 'approved', + 'error_code' => null, + 'status_detail' => null, + 'remote_order_id' => '114293600', + ], + ]; + yield 'fail1' => [ + 'responseData' => [ + 'SaleReversalResponse' => [ + 'SaleReversalResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [ + 'IsEnrolled' => false, + 'IsVirtual' => false, + 'OrderId' => 0, + 'TransactionTime' => '0001-01-01T00:00:00', + 'MerchantId' => null, + 'BusinessKey' => '202307089999000000009015473', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => null, + 'transaction_id' => null, + 'currency' => null, + 'error_message' => null, + 'ref_ret_num' => null, + 'status' => 'declined', + 'error_code' => null, + 'status_detail' => null, + ], + ]; + yield 'fail_already_cancelled' => [ + 'responseData' => [ + 'SaleReversalResponse' => [ + 'SaleReversalResult' => [ + 'Results' => [ + 'Result' => [ + 0 => [ + 'ErrorMessage' => 'İşlem daha önce iptal edilmiştir.', + 'ErrorCode' => '21', + 'IsFriendly' => null, + 'Severity' => 'Error', + ], + 1 => [ + 'ErrorMessage' => 'İşleminizi şu an gerçekleştiremiyoruz, lütfen daha sonra tekrar deneyiniz.', + 'ErrorCode' => 'IntegrationFatalException', + 'IsFriendly' => null, + 'Severity' => 'Error', + ], + ], + ], + 'Success' => null, + 'Value' => [ + 'IsEnrolled' => null, + 'IsVirtual' => null, + 'ResponseCode' => 'DbLayerError', + 'OrderId' => 0, + 'TransactionTime' => '0001-01-01T00:00:00', + 'MerchantId' => null, + 'BusinessKey' => '0', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => 'DbLayerError', + 'transaction_id' => null, + 'currency' => null, + 'error_message' => 'İşlem daha önce iptal edilmiştir.', + 'ref_ret_num' => null, + 'status' => 'declined', + 'error_code' => '21', + 'status_detail' => null, + ], + ]; + yield 'tdv2_fail_already_cancelled' => [ + 'responseData' => [ + 'SaleReversalResponse' => [ + 'SaleReversalResult' => [ + 'Results' => [ + 'Result' => [ + 'ErrorMessage' => 'İşlem daha önce iptal edilmiştir.', + 'ErrorCode' => '21', + 'IsFriendly' => true, + 'Severity' => 'BusinessError', + ], + ], + 'Success' => false, + 'Value' => [ + 'IsEnrolled' => false, + 'IsVirtual' => false, + 'ResponseCode' => 'DbLayerError', + 'OrderId' => 0, + 'TransactionTime' => '0001-01-01T00:00:00', + 'MerchantId' => null, + 'BusinessKey' => '0', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => 'DbLayerError', + 'transaction_id' => null, + 'currency' => null, + 'error_message' => 'İşlem daha önce iptal edilmiştir.', + 'ref_ret_num' => null, + 'status' => 'declined', + 'error_code' => '21', + 'status_detail' => null, + ], + ]; + } + + public static function refundTestDataProvider(): \Generator + { + yield 'fail1' => [ + 'responseData' => [ + 'PartialDrawbackResponse' => [ + 'PartialDrawbackResult' => [ + 'Results' => [], + 'Success' => null, + 'Value' => [ + 'IsEnrolled' => null, + 'IsVirtual' => null, + 'RRN' => '319013298460', + 'Stan' => '298460', + 'ResponseCode' => '28', + 'ResponseMessage' => 'İptal Edilen İşlem İade Yapılamaz', + 'OrderId' => 114_293_625, + 'TransactionTime' => '2023-07-09T13:38:00.9396957', + 'MerchantOrderId' => '202307093C2D', + 'CurrencyCode' => '0949', + 'MerchantId' => null, + 'BusinessKey' => '202307099999000000003235752', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => '202307093C2D', + 'auth_code' => null, + 'proc_return_code' => '28', + 'transaction_id' => '298460', + 'currency' => null, + 'error_message' => 'İptal Edilen İşlem İade Yapılamaz', + 'ref_ret_num' => '319013298460', + 'status' => 'declined', + 'error_code' => '28', + 'status_detail' => null, + 'remote_order_id' => '114293625', + ], + ]; + + yield 'fail2' => [ + 'responseData' => [ + 'PartialDrawbackResponse' => [ + 'PartialDrawbackResult' => [ + 'Results' => [], + 'Success' => null, + 'Value' => [ + 'IsEnrolled' => null, + 'IsVirtual' => null, + 'OrderId' => 0, + 'TransactionTime' => '0001-01-01T00:00:00', + 'MerchantId' => null, + 'BusinessKey' => '202307099999000000003252739', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => null, + 'transaction_id' => null, + 'currency' => null, + 'error_message' => null, + 'ref_ret_num' => null, + 'status' => 'declined', + 'error_code' => null, + 'status_detail' => null, + ], + ]; + yield 'tdv2_fail_partial_refund_not_allowed' => [ + 'responseData' => [ + 'PartialDrawbackResponse' => [ + 'PartialDrawbackResult' => [ + 'Results' => [ + 'Result' => [ + 'ErrorMessage' => 'Kısmi iade işlemi, satışla aynı gün içerisindeyse tutarın tamamı için yapılamaz. Tutarın tamamı için iptal işlemi yapabilirsiniz.', + 'IsFriendly' => true, + 'Severity' => 'BusinessError', + ], + ], + 'Success' => false, + 'Value' => [ + 'IsEnrolled' => false, + 'IsVirtual' => false, + 'ResponseCode' => 'DbLayerError', + 'OrderId' => 0, + 'TransactionTime' => '0001-01-01T00:00:00', + 'MerchantId' => null, + 'BusinessKey' => '0', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => null, + 'auth_code' => null, + 'proc_return_code' => 'DbLayerError', + 'transaction_id' => null, + 'currency' => null, + 'ref_ret_num' => null, + 'status' => 'declined', + 'error_code' => 'DbLayerError', + 'error_message' => 'Kısmi iade işlemi, satışla aynı gün içerisindeyse tutarın tamamı için yapılamaz. Tutarın tamamı için iptal işlemi yapabilirsiniz.', + 'status_detail' => null, + ], + ]; + + yield 'success1' => [ + 'responseData' => [ + 'PartialDrawbackResponse' => [ + 'PartialDrawbackResult' => [ + 'Results' => [], + 'Success' => null, + 'Value' => [ + 'IsEnrolled' => null, + 'IsVirtual' => null, + 'ProvisionNumber' => '241859', + 'RRN' => '319014298463', + 'Stan' => '298463', + 'ResponseCode' => '00', + 'ResponseMessage' => 'OTORİZASYON VERİLDİ', + 'OrderId' => 114_293_626, + 'TransactionTime' => '2023-07-09T14:07:41.9306297', + 'MerchantOrderId' => '202307091285', + 'CurrencyCode' => '0949', + 'MerchantId' => null, + 'BusinessKey' => '202307099999000000003252996', + ], + ], + ], + ], + 'expectedData' => [ + 'order_id' => '202307091285', + 'auth_code' => '241859', + 'proc_return_code' => '00', + 'transaction_id' => '298463', + 'currency' => PosInterface::CURRENCY_TRY, + 'error_message' => null, + 'ref_ret_num' => '319014298463', + 'status' => 'approved', + 'error_code' => null, + 'status_detail' => null, + 'remote_order_id' => '114293626', + ], + ]; + + yield 'tdv2_success_full_refund' => [ + 'responseData' => [ + 'DrawBackResponse' => [ + 'DrawBackResult' => [ + 'Results' => [], + 'Success' => true, + 'Value' => [ + 'IsEnrolled' => false, + 'IsVirtual' => false, + 'ProvisionNumber' => '050823', + 'RRN' => '411415539590', + 'Stan' => '539590', + 'ResponseCode' => '00', + 'ResponseMessage' => 'OTORİZASYON VERİLDİ', + 'OrderId' => 155767855, + 'TransactionTime' => '2024-04-23T15:19:15.7471578', + 'MerchantOrderId' => '202404229EAC', + 'CurrencyCode' => '0949', + 'MerchantId' => null, + 'BusinessKey' => '202404239999000000013631520', + ], + ], + ], + ], + 'expectedData' => [ + 'auth_code' => '050823', + 'currency' => 'TRY', + 'error_code' => null, + 'error_message' => null, + 'order_id' => '202404229EAC', + 'proc_return_code' => '00', + 'ref_ret_num' => '411415539590', + 'remote_order_id' => '155767855', + 'status' => 'approved', + 'status_detail' => null, + 'transaction_id' => '539590', + ], + ]; + yield 'tdv2_success1' => [ + 'responseData' => [ + 'PartialDrawbackResponse' => [ + 'PartialDrawbackResult' => [ + 'Results' => [ + + ], + 'Success' => true, + 'Value' => [ + 'IsEnrolled' => false, + 'IsVirtual' => false, + 'ProvisionNumber' => '050569', + 'RRN' => '411220539231', + 'Stan' => '539231', + 'ResponseCode' => '00', + 'ResponseMessage' => 'OTORİZASYON VERİLDİ', + 'OrderId' => 155767811, + 'TransactionTime' => '2024-04-21T20:09:21.3829986', + 'MerchantOrderId' => '202404218A62', + 'CurrencyCode' => '0949', + 'MerchantId' => null, + 'BusinessKey' => '202404219999000000009542260', + ], + ], + ], + ], + 'expectedData' => [ + 'auth_code' => '050569', + 'currency' => 'TRY', + 'error_code' => null, + 'error_message' => null, + 'order_id' => '202404218A62', + 'proc_return_code' => '00', + 'ref_ret_num' => '411220539231', + 'remote_order_id' => '155767811', + 'status' => 'approved', + 'status_detail' => null, + 'transaction_id' => '539231', + ], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseDataMapper/ParamPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/ParamPosResponseDataMapperTest.php index a56f66e9..c3628170 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/ParamPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/ParamPosResponseDataMapperTest.php @@ -6,14 +6,16 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\ParamPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ParamPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ParamPosResponseValueFormatter; +use Mews\Pos\DataMapper\ResponseValueMapper\ParamPosResponseValueMapper; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\Param3DHostPos; +use Mews\Pos\Gateways\ParamPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -24,6 +26,10 @@ class ParamPosResponseDataMapperTest extends TestCase { private ParamPosResponseDataMapper $responseDataMapper; + private ParamPosResponseValueFormatter $responseValueFormatter; + + private ParamPosResponseValueMapper $responseValueMapper; + /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; @@ -33,19 +39,27 @@ protected function setUp(): void $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new ParamPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = new ParamPosResponseValueFormatter(); + $this->responseValueMapper = new ParamPosResponseValueMapper([], [], []); $this->responseDataMapper = new ParamPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(ParamPos::class); + $this->assertTrue($result); + $result = $this->responseDataMapper::supports(Param3DHostPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + /** * @testWith [null, false] * ["", false] diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php index a3783a4e..d3ea1030 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php @@ -7,14 +7,16 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Generator; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\PayFlexCPV4PosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayFlexCPV4PosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\PayFlexCPV4Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -28,24 +30,38 @@ class PayFlexCPV4PosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new PayFlexCPV4PosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); + $this->responseDataMapper = new PayFlexCPV4PosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(PayFlexCPV4Pos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** * @testWith [null, true] * ["", true] @@ -75,9 +91,36 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMap3DPayResponseData(array $order, string $txType, array $bankResponse, array $expectedData): void { + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($bankResponse['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($bankResponse['HostDate'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($bankResponse['Amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($bankResponse['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($bankResponse['AmountCode'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->map3DPayResponseData($bankResponse, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -95,9 +138,36 @@ public function testMap3DPayResponseData(array $order, string $txType, array $ba public function testMap3DHostResponseData(array $order, string $txType, array $bankResponse, array $expectedData): void { $expectedData['payment_model'] = PosInterface::MODEL_3D_HOST; + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($bankResponse['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($bankResponse['HostDate'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($bankResponse['Amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($bankResponse['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($bankResponse['AmountCode'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->map3DHostResponseData($bankResponse, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php index bcacc69b..782e29cb 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php @@ -6,14 +6,15 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\PayFlexV4PosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayFlexV4PosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\PayFlexV4Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,24 +28,38 @@ class PayFlexV4PosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new PayFlexV4PosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class) - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); + $this->responseDataMapper = new PayFlexV4PosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(PayFlexV4Pos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** * @testWith [null, false] * ["", false] @@ -76,14 +91,55 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if (isset($paymentResponse['TLAmount'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($paymentResponse['TLAmount'], $txType) + ->willReturn($expectedData['amount']); + } + + if (isset($paymentResponse['TransactionType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($paymentResponse['TransactionType']) + ->willReturn($expectedData['transaction_type']); + } + + if (isset($paymentResponse['ThreeDSecureType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($paymentResponse['ThreeDSecureType']) + ->willReturn($expectedData['payment_model']); + } + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with( + strlen($paymentResponse['HostDate']) === 10 + ? date('Y').$paymentResponse['HostDate'] + : $paymentResponse['HostDate'], + $txType + ) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($paymentResponse['CurrencyCode'] ?? $threeDResponseData['PurchCurrency'], $txType) + ->willReturn($expectedData['currency']); + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -106,9 +162,47 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMapPaymentResponse(string $txType, array $responseData, array $expectedData): void { + if (isset($responseData['TLAmount'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['TLAmount'], $txType) + ->willReturn($expectedData['amount']); + } + + if (isset($responseData['TransactionType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TransactionType']) + ->willReturn($expectedData['transaction_type']); + } + + if (isset($responseData['ThreeDSecureType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['ThreeDSecureType']) + ->willReturn($expectedData['payment_model']); + } + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with( + strlen($responseData['HostDate']) === 10 + ? date('Y').$responseData['HostDate'] + : $responseData['HostDate'], + $txType + ) + ->willReturn($expectedData['transaction_time']); + } + + if (isset($responseData['CurrencyCode'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -155,6 +249,25 @@ public function testMapRefundResponse(array $paymentResponse, array $expectedDat */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $txResultInfo = $responseData['TransactionSearchResultInfo']['TransactionSearchResultInfo']; + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($txResultInfo['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($txResultInfo['AmountCode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($txResultInfo['CurrencyAmount'] ?? $txResultInfo['Amount'], $txType) + ->willReturn($expectedData['first_amount']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); $this->assertArrayHasKey('all', $actualData); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php index af505144..dfb99da2 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php @@ -6,13 +6,17 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\PayForPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayForPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; +use Mews\Pos\Factory\RequestValueMapperFactory; +use Mews\Pos\Factory\ResponseValueFormatterFactory; +use Mews\Pos\Factory\ResponseValueMapperFactory; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\PayForPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -26,23 +30,38 @@ class PayForPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); + $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new PayForPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); + $this->responseDataMapper = new PayForPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(PayForPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** * @testWith [null, false] * ["", false] @@ -77,15 +96,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -102,14 +120,44 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['SecureType'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($threeDResponseData['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -132,9 +180,39 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['SecureType'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -151,9 +229,39 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['SecureType'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -170,15 +278,58 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['first_amount']); + + $dateTimeMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use ($dateTimeMatcher, $responseData): bool { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $dateTime === $responseData['InsertDatetime']; + } + + if ($responseData['VoidDate'] > 0) { + return $dateTime === $responseData['VoidDate'].'T'.$responseData['VoidTime']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['cancel_time']; + } + + return false; + } + ); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -191,11 +342,18 @@ public function testMapStatusResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryTestDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(PayForPos::class); + $responseDataMapper = new PayForPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(PayForPos::class), + ResponseValueMapperFactory::createForGateway(PayForPos::class, $requestValueMapper), + $this->logger + ); + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -231,7 +389,13 @@ public function testMapOrderHistoryResponse(array $responseData, array $expected */ public function testMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(PayForPos::class); + $responseDataMapper = new PayForPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(PayForPos::class), + ResponseValueMapperFactory::createForGateway(PayForPos::class, $requestValueMapper), + $this->logger + ); + $actualData = $responseDataMapper->mapHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -1487,914 +1651,924 @@ public static function threeDHostPaymentDataProvider(): array } - public static function statusTestDataProvider(): array + public static function statusTestDataProvider(): iterable { - return [ - 'success1' => [ - 'responseData' => [ - 'RequestGuid' => '1000000081265961', - 'InsertDatetime' => '31.10.2022 23:13:21', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202210312A24', - 'RequestIp' => '89.244.149.137', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'Auth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'tr', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S90370', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4320', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '26786247', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20221031', - 'SysDate' => '20221031', - 'F11' => '101605', - 'F37' => '230423101605', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '16', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '5', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '89.244.149.137', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'false', - 'IsRefunded' => 'false', - 'TrxDate' => '31.10.2022 23:13', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S90370', - 'order_id' => '202210312A24', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'PAYMENT_COMPLETED', - 'transaction_type' => 'pay', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => true, - 'capture_time' => new \DateTimeImmutable('31.10.2022 23:13:21'), - 'capture_amount' => 1.01, - 'first_amount' => 1.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('31.10.2022 23:13:21'), - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 0, - ], + $success1CaptureTime = new \DateTimeImmutable('31.10.2022 23:13:21'); + + yield 'success1' => [ + 'responseData' => [ + 'RequestGuid' => '1000000081265961', + 'InsertDatetime' => '31.10.2022 23:13:21', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202210312A24', + 'RequestIp' => '89.244.149.137', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'Auth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'tr', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S90370', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4320', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '26786247', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20221031', + 'SysDate' => '20221031', + 'F11' => '101605', + 'F37' => '230423101605', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '16', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '5', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '89.244.149.137', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'false', + 'IsRefunded' => 'false', + 'TrxDate' => '31.10.2022 23:13', + 'ReturnMessage' => 'Onaylandı', ], - 'success_pre_pay' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094948181', - 'InsertDatetime' => '19.01.2024 22:07:49', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202401191C51', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '2.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PreAuth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '3', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S18386', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '99712092', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '27445', - 'F37' => '401922027445', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '16', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '2', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'false', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 22:07', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S18386', - 'order_id' => '202401191C51', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => null, - 'transaction_type' => 'pre', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => false, - 'capture_time' => null, - 'capture_amount' => null, - 'first_amount' => 2.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 22:07:49'), - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 3, - ], + 'expectedData' => [ + 'auth_code' => 'S90370', + 'order_id' => '202210312A24', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'PAYMENT_COMPLETED', + 'transaction_type' => 'pay', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => true, + 'capture_time' => $success1CaptureTime, + 'capture_amount' => 1.01, + 'first_amount' => 1.01, + 'transaction_id' => null, + 'transaction_time' => $success1CaptureTime, + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 0, ], - 'success_pre_pay_and_post_pay' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094938529', - 'InsertDatetime' => '19.01.2024 22:13:39', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '2024011926F1', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '2.03', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PostAuth', - 'OrgOrderId' => '2024011926F1', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '3', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => '', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S89375', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '99712640', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '27995', - 'F37' => '401922027995', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '16', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '3', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '27994', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'CardAcceptorName' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'false', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 22:13', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S89375', - 'order_id' => '2024011926F1', - 'org_order_id' => '2024011926F1', - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'PAYMENT_COMPLETED', - 'transaction_type' => 'post', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => true, - 'capture_time' => new \DateTimeImmutable('19.01.2024 22:13:39'), - 'capture_amount' => 2.03, - 'first_amount' => 2.03, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 22:13:39'), - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 3, - ], + ]; + + yield 'success_pre_pay' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094948181', + 'InsertDatetime' => '19.01.2024 22:07:49', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202401191C51', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '2.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PreAuth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '3', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S18386', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '99712092', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '27445', + 'F37' => '401922027445', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '16', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '2', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'false', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 22:07', + 'ReturnMessage' => 'Onaylandı', ], - 'success_pay_then_cancel' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094947969', - 'InsertDatetime' => '19.01.2024 21:34:05', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202401194815', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'Auth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'V', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S29682', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '20240119', - 'CardMask' => '415565******6111', - 'ReqId' => '99709025', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '24380', - 'F37' => '401921024380', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '15', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '2', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '213405', - 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'true', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 21:34', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S29682', - 'order_id' => '202401194815', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'CANCELED', - 'transaction_type' => 'pay', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => true, - 'capture_time' => new \DateTimeImmutable('19.01.2024 21:34:05'), - 'capture_amount' => 1.01, - 'first_amount' => 1.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 21:34:05'), - 'cancel_time' => new \DateTimeImmutable('20240119T213405'), - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 0, - ], + 'expectedData' => [ + 'auth_code' => 'S18386', + 'order_id' => '202401191C51', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => null, + 'transaction_type' => 'pre', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => false, + 'capture_time' => null, + 'capture_amount' => null, + 'first_amount' => 2.01, + 'transaction_id' => null, + 'transaction_time' => new \DateTimeImmutable('19.01.2024 22:07:49'), + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 3, ], - 'success_pre_pay_then_cancel' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094947988', - 'InsertDatetime' => '19.01.2024 21:47:43', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202401197C78', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PreAuth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '3', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'V', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S54087', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '20240119', - 'CardMask' => '415565******6111', - 'ReqId' => '99710256', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '25609', - 'F37' => '401921025609', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '15', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '2', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '214744', - 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'true', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 21:47', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S54087', - 'order_id' => '202401197C78', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'CANCELED', - 'transaction_type' => 'pre', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => false, - 'capture_time' => null, - 'capture_amount' => null, - 'first_amount' => 1.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 21:47:43'), - 'cancel_time' => new \DateTimeImmutable('20240119T214744'), - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 3, - ], + ]; + + $successPrePayAndPostDateTime = new \DateTimeImmutable('19.01.2024 22:13:39'); + yield 'success_pre_pay_and_post_pay' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094938529', + 'InsertDatetime' => '19.01.2024 22:13:39', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '2024011926F1', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '2.03', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PostAuth', + 'OrgOrderId' => '2024011926F1', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '3', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => '', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S89375', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '99712640', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '27995', + 'F37' => '401922027995', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '16', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '3', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '27994', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'CardAcceptorName' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'false', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 22:13', + 'ReturnMessage' => 'Onaylandı', ], - 'fail_order_not_found' => [ - 'responseData' => [ - 'RequestGuid' => '0', - 'InsertDatetime' => '1.01.0001 00:00:00', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202210312A242', - 'RequestIp' => '89.244.149.137', - 'RequestStat' => '1,10', - 'SecureType' => 'Inquiry', - 'PurchAmount' => '', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'OrderInquiry', - 'OrgOrderId' => '202210312A242', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => '', - 'Lang' => 'tr', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => '', - 'IrcDet' => 'Seçili İşlem Bulunamadı!', - 'IrcCode' => '99961', - 'Version' => '', - 'TxnStatus' => 'P', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Seçili İşlem Bulunamadı!', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => '', - 'AuthCode' => '', - 'HostRefNum' => '', - 'ProcReturnCode' => 'V013', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4320', - 'VoidDate' => '', - 'CardMask' => '', - 'ReqId' => '26786448', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '0', - 'SysDate' => '0', - 'F11' => '101906', - 'F37' => '', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '0', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '0', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'True', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '89.244.149.137', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'SESSION_SYSTEM_USER' => '0', - ], - 'expectedData' => [ - 'auth_code' => null, - 'order_id' => '202210312A242', - 'org_order_id' => '202210312A242', - 'proc_return_code' => 'V013', - 'error_message' => 'Seçili İşlem Bulunamadı!', - 'ref_ret_num' => null, - 'order_status' => null, - 'transaction_type' => 'status', - 'masked_number' => null, - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'declined', - 'status_detail' => 'reject', - 'transaction_time' => null, - 'transaction_id' => null, - 'capture_time' => null, - 'capture' => null, - 'capture_amount' => null, - 'error_code' => null, - 'first_amount' => null, - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 0, - ], + 'expectedData' => [ + 'auth_code' => 'S89375', + 'order_id' => '2024011926F1', + 'org_order_id' => '2024011926F1', + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'PAYMENT_COMPLETED', + 'transaction_type' => 'post', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => true, + 'capture_time' => $successPrePayAndPostDateTime, + 'capture_amount' => 2.03, + 'first_amount' => 2.03, + 'transaction_id' => null, + 'transaction_time' => $successPrePayAndPostDateTime, + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 3, + ], + ]; + + $successPayThenCancelDateTime = new \DateTimeImmutable('19.01.2024 21:34:05'); + $successPayThenCancelCancelDateTime = new \DateTimeImmutable('20240119T213405'); + + yield 'success_pay_then_cancel' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094947969', + 'InsertDatetime' => '19.01.2024 21:34:05', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202401194815', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'Auth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'V', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S29682', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '20240119', + 'CardMask' => '415565******6111', + 'ReqId' => '99709025', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '24380', + 'F37' => '401921024380', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '15', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '2', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '213405', + 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'true', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 21:34', + 'ReturnMessage' => 'Onaylandı', + ], + 'expectedData' => [ + 'auth_code' => 'S29682', + 'order_id' => '202401194815', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'CANCELED', + 'transaction_type' => 'pay', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => true, + 'capture_time' => $successPayThenCancelDateTime, + 'capture_amount' => 1.01, + 'first_amount' => 1.01, + 'transaction_id' => null, + 'transaction_time' => $successPayThenCancelDateTime, + 'cancel_time' => $successPayThenCancelCancelDateTime, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 0, + ], + ]; + + yield 'success_pre_pay_then_cancel' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094947988', + 'InsertDatetime' => '19.01.2024 21:47:43', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202401197C78', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PreAuth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '3', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'V', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S54087', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '20240119', + 'CardMask' => '415565******6111', + 'ReqId' => '99710256', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '25609', + 'F37' => '401921025609', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '15', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '2', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '214744', + 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'true', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 21:47', + 'ReturnMessage' => 'Onaylandı', + ], + 'expectedData' => [ + 'auth_code' => 'S54087', + 'order_id' => '202401197C78', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'CANCELED', + 'transaction_type' => 'pre', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => false, + 'capture_time' => null, + 'capture_amount' => null, + 'first_amount' => 1.01, + 'transaction_id' => null, + 'transaction_time' => new \DateTimeImmutable('19.01.2024 21:47:43'), + 'cancel_time' => new \DateTimeImmutable('20240119T214744'), + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 3, + ], + ]; + + + yield 'fail_order_not_found' => [ + 'responseData' => [ + 'RequestGuid' => '0', + 'InsertDatetime' => '1.01.0001 00:00:00', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202210312A242', + 'RequestIp' => '89.244.149.137', + 'RequestStat' => '1,10', + 'SecureType' => 'Inquiry', + 'PurchAmount' => '', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'OrderInquiry', + 'OrgOrderId' => '202210312A242', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => '', + 'Lang' => 'tr', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => '', + 'IrcDet' => 'Seçili İşlem Bulunamadı!', + 'IrcCode' => '99961', + 'Version' => '', + 'TxnStatus' => 'P', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Seçili İşlem Bulunamadı!', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => '', + 'AuthCode' => '', + 'HostRefNum' => '', + 'ProcReturnCode' => 'V013', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4320', + 'VoidDate' => '', + 'CardMask' => '', + 'ReqId' => '26786448', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '0', + 'SysDate' => '0', + 'F11' => '101906', + 'F37' => '', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '0', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '0', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'True', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '89.244.149.137', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'SESSION_SYSTEM_USER' => '0', + ], + 'expectedData' => [ + 'auth_code' => null, + 'order_id' => '202210312A242', + 'org_order_id' => '202210312A242', + 'proc_return_code' => 'V013', + 'error_message' => 'Seçili İşlem Bulunamadı!', + 'ref_ret_num' => null, + 'order_status' => null, + 'transaction_type' => 'status', + 'masked_number' => null, + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'declined', + 'status_detail' => 'reject', + 'transaction_time' => null, + 'transaction_id' => null, + 'capture_time' => null, + 'capture' => null, + 'capture_amount' => null, + 'error_code' => null, + 'first_amount' => null, + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 0, ], ]; } diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php index 6f69d882..138b8bb6 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php @@ -6,14 +6,15 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\PosNetRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PosNetResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\PosNet; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,23 +28,38 @@ class PosNetResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); + $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new PosNetRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); + $this->responseDataMapper = new PosNetResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(PosNet::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** * @testWith [null, false] * ["", false] @@ -77,20 +93,22 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); $this->assertNotEmpty($actualData['all']); unset($actualData['all']); + \ksort($actualData); + \ksort($expectedData); $this->assertSame($expectedData, $actualData); } @@ -99,19 +117,31 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if (isset($threeDResponseData['oosResolveMerchantDataResponse'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['oosResolveMerchantDataResponse']['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['oosResolveMerchantDataResponse']['currency'], $txType) + ->willReturn($expectedData['currency']); + } + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -134,15 +164,30 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + if (isset($responseData['transactions']['transaction'])) { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['transactions']['transaction']['amount'], $txType) + ->willReturn($expectedData['first_amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['transactions']['transaction']['currencyCode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['transactions']['transaction']['tranDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['transactions']['transaction']['state']) + ->willReturn($expectedData['transaction_type']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -159,6 +204,13 @@ public function testMapStatusResponse(array $responseData, array $expectedData): */ public function testMapRefundResponse(array $responseData, array $expectedData): void { + if (isset($responseData['state'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['state']) + ->willReturn($expectedData['transaction_type']); + } + $actualData = $this->responseDataMapper->mapRefundResponse($responseData); $this->assertArrayHasKey('all', $actualData); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php index 00d75f23..78efd91c 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php @@ -6,14 +6,15 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\PosNetV1PosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PosNetV1PosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\PosNetV1Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,25 +28,38 @@ class PosNetV1PosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); - $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new PosNetV1PosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); + $this->responseDataMapper = new PosNetV1PosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(PosNetV1Pos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** * @testWith [null, false] * ["", false] @@ -79,14 +93,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -103,19 +117,43 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['TranType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['Amount'], $txType) + ->willReturn($expectedData['amount']); + + if (isset($threeDResponseData['CurrencyCode'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($paymentResponse['InstallmentData']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); if ([] !== $paymentResponse) { $this->assertArrayHasKey('all', $actualData); @@ -138,16 +176,45 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMapStatusResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapStatusResponse($responseData); + $rawTx = null; + if (isset($responseData['TransactionData'])) { + foreach ($responseData['TransactionData'] as $item) { + if ('1' === $item['TransactionStatus']) { + $rawTx = $item; + break; + } + } + } + + if (null !== $rawTx) { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($rawTx['Amount'], $txType) + ->willReturn($expectedData['first_amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($rawTx['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($rawTx['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($rawTx['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($expectedData['transaction_type']) + ->willReturn($expectedData['order_status']); + } - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -357,7 +424,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '20230622A1C9', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '450634', 'TranType' => 'Sale', @@ -403,7 +470,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '80603153823', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '540061', 'TranType' => 'Sale', @@ -523,7 +590,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '80603153823', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '540061', 'TranType' => 'Sale', @@ -574,7 +641,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '202306226A90', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '450634', 'TranType' => 'Sale', @@ -631,6 +698,8 @@ public static function threeDPaymentDataProvider(): \Generator public static function mapStatusResponseDataProvider(): iterable { + $txTime = new \DateTimeImmutable('2019-11-0813:58:37.909'); + yield 'success_refunded' => [ 'response' => [ 'ServiceResponseData' => [ @@ -673,7 +742,7 @@ public static function mapStatusResponseDataProvider(): iterable 'status_detail' => null, 'error_code' => null, 'error_message' => null, - 'transaction_time' => new \DateTimeImmutable('2019-11-0813:58:37.909'), + 'transaction_time' => $txTime, 'capture_time' => null, 'capture' => null, 'capture_amount' => null, @@ -683,7 +752,7 @@ public static function mapStatusResponseDataProvider(): iterable 'masked_number' => '540061******4581', 'cancel_time' => null, 'refund_amount' => null, - 'refund_time' => new \DateTimeImmutable('2019-11-0813:58:37.909'), + 'refund_time' => $txTime, 'installment_count' => null, ], ]; diff --git a/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php index 15feba7d..f3983ebb 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php @@ -6,14 +6,18 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\ToslaPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ToslaPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Factory\RequestValueMapperFactory; +use Mews\Pos\Factory\ResponseValueFormatterFactory; +use Mews\Pos\Factory\ResponseValueMapperFactory; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\ToslaPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,25 +31,38 @@ class ToslaPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new ToslaPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new ToslaPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatter, + $this->responseValueMapper, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(ToslaPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** * @testWith [null, false] * ["", false] @@ -79,14 +96,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -104,14 +121,19 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['RequestStatus']) + ->willReturn($expectedData['tx_status']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -128,14 +150,19 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['RequestStatus']) + ->willReturn($expectedData['tx_status']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -152,19 +179,60 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - if (isset($responseData['CreateDate'])) { - $this->assertSame($actualData['transaction_time']->format('YmdHis'), $responseData['CreateDate']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); + $txType = PosInterface::TX_TYPE_STATUS; + + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['RequestStatus']) + ->willReturn($expectedData['order_status']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + if ($responseData['Currency'] > 0) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + $amountMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $responseData): bool { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $responseData['Amount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $responseData['RefundedAmount']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['first_amount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['refund_amount']; + } + + return false; + } + ); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['CreateDate'], $txType) + ->willReturn($expectedData['transaction_time']); } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); + $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); $this->assertNotEmpty($actualData['all']); @@ -206,11 +274,18 @@ public function testMapCancelResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(ToslaPos::class); + $responseDataMapper = new ToslaPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(ToslaPos::class), + ResponseValueMapperFactory::createForGateway(ToslaPos::class, $requestValueMapper), + $this->logger + ); + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (isset($responseData['Transactions'])) { $this->assertCount($actualData['trans_count'], $actualData['transactions']); if (count($actualData['transactions']) > 1 diff --git a/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php index 47ebbeb7..7f0ed1af 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php @@ -6,14 +6,18 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; -use Mews\Pos\Crypt\CryptInterface; -use Mews\Pos\DataMapper\RequestDataMapper\VakifKatilimPosRequestDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\VakifKatilimPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; +use Mews\Pos\Factory\RequestValueMapperFactory; +use Mews\Pos\Factory\ResponseValueFormatterFactory; +use Mews\Pos\Factory\ResponseValueMapperFactory; +use Mews\Pos\Gateways\AkbankPos; +use Mews\Pos\Gateways\VakifKatilimPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -27,23 +31,41 @@ class VakifKatilimPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatterMock; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapperMock; + + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); + $this->logger = $this->createMock(LoggerInterface::class); - $requestDataMapper = new VakifKatilimPosRequestDataMapper( - $this->createMock(EventDispatcherInterface::class), - $this->createMock(CryptInterface::class), - ); + $this->responseValueFormatterMock = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapperMock = $this->createMock(ResponseValueMapperInterface::class); + $requestValueMapper = RequestValueMapperFactory::createForGateway(VakifKatilimPos::class); + $this->responseValueMapper = ResponseValueMapperFactory::createForGateway(VakifKatilimPos::class, $requestValueMapper); + $this->responseDataMapper = new VakifKatilimPosResponseDataMapper( - $requestDataMapper->getCurrencyMappings(), - $requestDataMapper->getTxTypeMappings(), - $requestDataMapper->getSecureTypeMappings(), - $this->logger, + $this->responseValueFormatterMock, + $this->responseValueMapperMock, + $this->logger ); } + public function testSupports(): void + { + $result = $this->responseDataMapper::supports(VakifKatilimPos::class); + $this->assertTrue($result); + + $result = $this->responseDataMapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + /** * @testWith [null, false] * ["", false] @@ -69,31 +91,41 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi $this->assertSame($expected, $actual); } - /** - * @return void - */ - public function testFormatAmount(): void - { - $class = new \ReflectionObject($this->responseDataMapper); - $method = $class->getMethod('formatAmount'); - $method->setAccessible(true); - $this->assertSame(0.1, $method->invokeArgs($this->responseDataMapper, [10])); - $this->assertSame(1.01, $method->invokeArgs($this->responseDataMapper, [101])); - } - /** * @dataProvider paymentTestDataProvider */ public function testMapPaymentResponse(string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($this->responseDataMapper::TX_APPROVED === $expectedData['status']) { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatAmount') + ->with($responseData['VPosMessage']['Amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapperMock->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['VPosMessage']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + + if (isset($expectedData['transaction_time'])) { + $txTimeWith = 'now'; + if ('0001-01-01T00:00:00' !== $responseData['TransactionTime'] && '00010101T00:00:00' !== $responseData['TransactionTime']) { + $txTimeWith = $responseData['TransactionTime']; + } + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with($txTimeWith, $txType) + ->willReturn($expectedData['transaction_time']); + } } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -110,19 +142,45 @@ public function testMapPaymentResponse(string $txType, array $responseData, arra */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if ($threeDResponseData['ResponseCode'] === '00') { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatAmount') + ->with($paymentResponse['VPosMessage']['Amount'], $txType) + ->willReturn($expectedData['amount']); + + if (isset($paymentResponse['VPosMessage']['CurrencyCode'])) { + $this->responseValueMapperMock->expects($this->once()) + ->method('mapCurrency') + ->with($paymentResponse['VPosMessage']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatInstallment') + ->with($paymentResponse['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + if (isset($expectedData['transaction_time'])) { + $txTimeWith = 'now'; + if ('0001-01-01T00:00:00' !== $paymentResponse['TransactionTime'] && '00010101T00:00:00' !== $paymentResponse['TransactionTime']) { + $txTimeWith = $paymentResponse['TransactionTime']; + } + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with($txTimeWith, $txType) + ->willReturn($expectedData['transaction_time']); + } + } + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -145,14 +203,14 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -205,15 +263,88 @@ public function testMapCancelResponse(array $responseData, array $expectedData): */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + if ($this->responseDataMapper::TX_APPROVED === $expectedData['status']) { + $amountMatcher = $this->atLeastOnce(); + $orderContract = $responseData['VPosOrderData']['OrderContract']; + $this->responseValueFormatterMock->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $orderContract): bool { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $orderContract['FirstAmount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $orderContract['TranAmount']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['first_amount']; + } + + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['capture_amount']; + } + + return false; + } + ); + + $statusMatcher = $this->atLeastOnce(); + $this->responseValueMapperMock->expects($statusMatcher) + ->method('mapOrderStatus') + ->with($this->callback(function ($amount) use ($statusMatcher, $orderContract): bool { + if ($statusMatcher->getInvocationCount() === 1) { + return $amount === ($orderContract['LastOrderStatus'] + ?? $orderContract['LastOrderStatusDescription']); + } + + if ($statusMatcher->getInvocationCount() === 2) { + return $amount === $orderContract['OrderStatus']; + } + + return false; + })) + ->willReturnCallback( + function () use ($statusMatcher, $expectedData, $orderContract) { + if ($statusMatcher->getInvocationCount() === 1) { + return $expectedData['order_status']; + } + + if ($statusMatcher->getInvocationCount() === 2) { + return $this->responseValueMapper->mapOrderStatus($orderContract['OrderStatus']); + } + + return false; + } + ); + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with($orderContract['OrderDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatInstallment') + ->with($orderContract['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapperMock->expects($this->once()) + ->method('mapSecureType') + ->with($orderContract['TransactionSecurity'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueMapperMock->expects($this->once()) + ->method('mapCurrency') + ->with($orderContract['FEC'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -226,11 +357,17 @@ public function testMapStatusResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider historyTestDataProvider */ public function testMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapHistoryResponse($responseData); + $responseDataMapper = new VakifKatilimPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(VakifKatilimPos::class), + $this->responseValueMapper, + $this->logger + ); + $actualData = $responseDataMapper->mapHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -261,11 +398,20 @@ public function testMapHistoryResponse(array $responseData, array $expectedData) $this->assertSame($expectedData, $actualData); } + /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. + */ public function testMapHistoryResponseWithALotOfTxs(): void { + $responseDataMapper = new VakifKatilimPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(VakifKatilimPos::class), + $this->responseValueMapper, + $this->logger + ); + $responseData = file_get_contents(__DIR__.'/../../test_data/vakifkatilimpos/history/success_history.json'); - $actualData = $this->responseDataMapper->mapHistoryResponse(json_decode($responseData, true)); + $actualData = $responseDataMapper->mapHistoryResponse(json_decode($responseData, true)); $this->assertCount(31, $actualData['transactions']); if (count($actualData['transactions']) <= 1) { @@ -292,7 +438,13 @@ public function testMapHistoryResponseWithALotOfTxs(): void */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $responseDataMapper = new VakifKatilimPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(VakifKatilimPos::class), + $this->responseValueMapper, + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/BasicResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/BasicResponseValueFormatterTest.php new file mode 100644 index 00000000..416cb16a --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/BasicResponseValueFormatterTest.php @@ -0,0 +1,130 @@ +formatter = new BasicResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(AkbankPos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(PayFlexCPV4Pos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(PayFlexV4Pos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(PayForPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatInstallmentProvider + */ + public function testFormatInstallment(?string $installment, string $txType, int $expected): void + { + $actual = $this->formatter->formatInstallment($installment, $txType); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatDateTimeProvider + */ + public function testFormatDateTime(string $dateTime, string $expected): void + { + $actual = $this->formatter->formatDateTime($dateTime, ''); + $this->assertSame($expected, $actual->format('Y-m-d H:i:s')); + } + + public static function formatAmountProvider(): array + { + return [ + ['1.00', PosInterface::TX_TYPE_PAY_AUTH, 1.0], + ['1.00', '', 1.0], + ]; + } + + public static function formatInstallmentProvider(): array + { + return [ + ['1', PosInterface::TX_TYPE_PAY_AUTH, 0], + ['1', '', 0], + ['0', PosInterface::TX_TYPE_PAY_AUTH, 0], + ['0', '', 0], + [null, PosInterface::TX_TYPE_PAY_AUTH, 0], + [null, '', 0], + ]; + } + + public static function formatDateTimeProvider(): array + { + return [ + // AkbankPos txnDateTime, preAuthCloseDate + // KuveytPos OrderDate, UpdateSystemDate + // VakifKatilim OrderDate + ['2024-04-23T16:14:00.264', '2024-04-23 16:14:00'], + + // EstPos AUTH_DTTM, CAPTURE_DTTM, VOID_DTTM + // Garanti ProvDate, PreAuthDate + // PosNet tranDate + ['2022-10-30 12:29:53.773', '2022-10-30 12:29:53'], + + // Garanti LastTrxDate + ['2024-06-03 16:06:29', '2024-06-03 16:06:29'], + + // PosNetV1 TransactionDate => '2019-11-0813:58:37.909' + ['2019-11-0813:58:37.909', '2019-11-08 13:58:37'], + + // Garanti ProvDate + // EstPos TRXDATE, EXTRA_TRXDATE + ['20221101 13:14:19', '2022-11-01 13:14:19'], + + // PayFlexCPV4 HostDate + // ToslaPos CreateDate + ['20230309221037', '2023-03-09 22:10:37'], + + // InterPos TRXDATE, VoidDate + // PayForPos InsertDatetime, TransactionDate + ['09.08.2024 10:40:34', '2024-08-09 10:40:34'], + + // VakifKatilim TransactionTime + ['2019-08-16T10:54:23.81069', '2019-08-16 10:54:23'], + ['2024-07-01T13:15:47.2754872+03:00', '2024-07-01 13:15:47'], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/BoaPosResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/BoaPosResponseValueFormatterTest.php new file mode 100644 index 00000000..a50990d8 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/BoaPosResponseValueFormatterTest.php @@ -0,0 +1,62 @@ +formatter = new BoaPosResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(KuveytPos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(KuveytSoapApiPos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(VakifKatilimPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + public static function formatAmountProvider(): array + { + return [ + ['101', '', 1.01], + ['101', PosInterface::TX_TYPE_PAY_AUTH, 1.01], + ['101', PosInterface::TX_TYPE_STATUS, 101], + ['101', PosInterface::TX_TYPE_HISTORY, 101], + ['101', PosInterface::TX_TYPE_ORDER_HISTORY, 101], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/EstPosResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/EstPosResponseValueFormatterTest.php new file mode 100644 index 00000000..fec81059 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/EstPosResponseValueFormatterTest.php @@ -0,0 +1,63 @@ +formatter = new EstPosResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(EstPos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + public static function formatAmountProvider(): array + { + return [ + ['1.00', PosInterface::TX_TYPE_PAY_AUTH, 1.0], + ['1.00', PosInterface::TX_TYPE_PAY_PRE_AUTH, 1.0], + ['1.00', PosInterface::TX_TYPE_PAY_POST_AUTH, 1.0], + ['1.00', PosInterface::TX_TYPE_CANCEL, 1.0], + ['1.00', PosInterface::TX_TYPE_REFUND, 1.0], + ['1.00', PosInterface::TX_TYPE_REFUND_PARTIAL, 1.0], + ['1.00', '', 1.0], + ['1001', PosInterface::TX_TYPE_STATUS, 10.01], + ['1001', PosInterface::TX_TYPE_ORDER_HISTORY, 10.01], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/GarantiPosResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/GarantiPosResponseValueFormatterTest.php new file mode 100644 index 00000000..297d49b3 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/GarantiPosResponseValueFormatterTest.php @@ -0,0 +1,83 @@ +formatter = new GarantiPosResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(GarantiPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatInstallmentProvider + */ + public function testFormatInstallment(?string $installment, string $txType, int $expected): void + { + $actual = $this->formatter->formatInstallment($installment, $txType); + $this->assertSame($expected, $actual); + } + + public static function formatInstallmentProvider(): array + { + return [ + ['1', PosInterface::TX_TYPE_PAY_AUTH, 0], + ['1', '', 0], + ['0', PosInterface::TX_TYPE_PAY_AUTH, 0], + ['0', '', 0], + [null, PosInterface::TX_TYPE_PAY_AUTH, 0], + [null, '', 0], + ['1', PosInterface::TX_TYPE_HISTORY, 0], + ['Pesin', PosInterface::TX_TYPE_HISTORY, 0], + ]; + } + + public static function formatAmountProvider(): array + { + return [ + ['1001', PosInterface::TX_TYPE_PAY_AUTH, 10.01], + ['1001', PosInterface::TX_TYPE_PAY_PRE_AUTH, 10.01], + ['1001', PosInterface::TX_TYPE_PAY_POST_AUTH, 10.01], + ['1001', PosInterface::TX_TYPE_CANCEL, 10.01], + ['1001', PosInterface::TX_TYPE_REFUND, 10.01], + ['1001', PosInterface::TX_TYPE_REFUND_PARTIAL, 10.01], + ['1001', PosInterface::TX_TYPE_STATUS, 10.01], + ['1001', PosInterface::TX_TYPE_ORDER_HISTORY, 10.01], + ['1001', '', 10.01], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/InterPosResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/InterPosResponseValueFormatterTest.php new file mode 100644 index 00000000..e2fd9124 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/InterPosResponseValueFormatterTest.php @@ -0,0 +1,60 @@ +formatter = new InterPosResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(InterPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + public function testFormatInstallment(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->formatter->formatInstallment("2", PosInterface::TX_TYPE_PAY_AUTH); + } + + public static function formatAmountProvider(): array + { + return [ + ['0', '', 0.0], + ['1.056,2', '', 1056.2], + ['1,01', '', 1.01], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/ParamPosResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/ParamPosResponseValueFormatterTest.php new file mode 100644 index 00000000..6686e6c0 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/ParamPosResponseValueFormatterTest.php @@ -0,0 +1,95 @@ +formatter = new ParamPosResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(ParamPos::class); + $this->assertTrue($result); + $result = $this->formatter::supports(Param3DHostPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider formatInstallmentProvider + */ + public function testFormatInstallment(?string $installment, string $txType, int $expected): void + { + $actual = $this->formatter->formatInstallment($installment, $txType); + $this->assertSame($expected, $actual); + } + + public static function formatAmountProvider(): array + { + return [ + ['1.01', '', 1.01], + ['1.01', PosInterface::TX_TYPE_PAY_AUTH, 1.01], + ['101', PosInterface::TX_TYPE_STATUS, 101], + ]; + } + + public static function formatInstallmentProvider(): array + { + return [ + ['1', PosInterface::TX_TYPE_PAY_AUTH, 0], + ['1', '', 0], + ['0', PosInterface::TX_TYPE_PAY_AUTH, 0], + ['0', '', 0], + [null, PosInterface::TX_TYPE_PAY_AUTH, 0], + [null, '', 0], + ]; + } + + /** + * @dataProvider formatDateTimeProvider + */ + public function testFormatDateTime(string $dateTime, string $expected): void + { + $actual = $this->formatter->formatDateTime($dateTime, ''); + $this->assertSame($expected, $actual->format('Y-m-d H:i:s')); + } + + public static function formatDateTimeProvider(): array + { + return [ + 'TURKPOS_RETVAL_Islem_Tarih' => ['19.01.2025 18:53:48', '2025-01-19 18:53:48'], + 'Tarih' => ['05.01.2025 13:14:32', '2025-01-05 13:14:32'], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/PosNetResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/PosNetResponseValueFormatterTest.php new file mode 100644 index 00000000..2acde320 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/PosNetResponseValueFormatterTest.php @@ -0,0 +1,57 @@ +formatter = new PosNetResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(PosNet::class); + $this->assertTrue($result); + $result = $this->formatter::supports(PosNetV1Pos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + public static function formatAmountProvider(): array + { + return [ + ['101', '', 1.01], + ['10,1', PosInterface::TX_TYPE_STATUS, 10.1], + ['1.056,2', PosInterface::TX_TYPE_STATUS, 1056.2], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueFormatter/ToslaPosResponseValueFormatterTest.php b/tests/Unit/DataMapper/ResponseValueFormatter/ToslaPosResponseValueFormatterTest.php new file mode 100644 index 00000000..ef49d8a2 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueFormatter/ToslaPosResponseValueFormatterTest.php @@ -0,0 +1,58 @@ +formatter = new ToslaPosResponseValueFormatter(); + } + + public function testSupports(): void + { + $result = $this->formatter::supports(ToslaPos::class); + $this->assertTrue($result); + + $result = $this->formatter::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider formatAmountProvider + */ + public function testFormatAmount(string $amount, string $txType, float $expected): void + { + $actual = $this->formatter->formatAmount($amount, $txType); + $this->assertSame($expected, $actual); + } + + public function testFormatInstallment(): void + { + $this->expectException(\Mews\Pos\Exceptions\NotImplementedException::class); + $this->formatter->formatInstallment("2", PosInterface::TX_TYPE_PAY_AUTH); + } + + public static function formatAmountProvider(): array + { + return [ + ['1001', '', 10.01], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/AkbankPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/AkbankPosResponseValueMapperTest.php new file mode 100644 index 00000000..660e8725 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/AkbankPosResponseValueMapperTest.php @@ -0,0 +1,131 @@ +mapper = ResponseValueMapperFactory::createForGateway( + AkbankPos::class, + RequestValueMapperFactory::createForGateway(AkbankPos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(AkbankPos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + /** + * @dataProvider mapOrderStatusDataProvider + */ + public function testMapOrderStatus( + string $orderStatus, + ?string $preAuthStatus, + bool $isRecurringOrder, + string $expected + ): void { + $this->assertSame( + $expected, + $this->mapper->mapOrderStatus($orderStatus, $preAuthStatus, $isRecurringOrder) + ); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(int $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapSecureType('3D', PosInterface::TX_TYPE_PAY_AUTH); + } + + + public static function mapCurrencyDataProvider(): array + { + return [ + [949, PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + [949, '', PosInterface::CURRENCY_TRY], + [840, '', PosInterface::CURRENCY_USD], + [978, '', PosInterface::CURRENCY_EUR], + [826, '', PosInterface::CURRENCY_GBP], + [392, '', PosInterface::CURRENCY_JPY], + [643, '', PosInterface::CURRENCY_RUB], + [1, '', null], + ]; + } + + + public static function mapTxTypeDataProvider(): array + { + return [ + ['1000', PosInterface::TX_TYPE_PAY_AUTH], + ['3000', PosInterface::TX_TYPE_PAY_AUTH], + ['1004', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['3004', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['1005', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['1002', PosInterface::TX_TYPE_REFUND], + ['1003', PosInterface::TX_TYPE_CANCEL], + ['1010', PosInterface::TX_TYPE_ORDER_HISTORY], + ['1009', PosInterface::TX_TYPE_HISTORY], + ]; + } + + public static function mapOrderStatusDataProvider(): array + { + return [ + ['N', null, false, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['N', 'O', false, PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED], + ['N', 'C', false, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['S', null, false, PosInterface::PAYMENT_STATUS_ERROR], + ['V', null, false, PosInterface::PAYMENT_STATUS_CANCELED], + ['R', null, false, PosInterface::PAYMENT_STATUS_FULLY_REFUNDED], + ['Başarılı', null, false, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['Başarısız', null, false, PosInterface::PAYMENT_STATUS_ERROR], + ['İptal', null, false, PosInterface::PAYMENT_STATUS_CANCELED], + ['S', null, true, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['W', null, true, PosInterface::PAYMENT_STATUS_PAYMENT_PENDING], + ['V', null, true, PosInterface::PAYMENT_STATUS_CANCELED], + ['C', null, true, PosInterface::PAYMENT_STATUS_CANCELED], + ['blabla', null, true, 'blabla'], + ['blabla', null, false, 'blabla'], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/BoaPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/BoaPosResponseValueMapperTest.php new file mode 100644 index 00000000..72e8f09c --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/BoaPosResponseValueMapperTest.php @@ -0,0 +1,134 @@ +mapper = ResponseValueMapperFactory::createForGateway( + KuveytPos::class, + RequestValueMapperFactory::createForGateway(KuveytPos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(KuveytPos::class); + $this->assertTrue($result); + $result = $this->mapper::supports(KuveytSoapApiPos::class); + $this->assertTrue($result); + $result = $this->mapper::supports(VakifKatilimPos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + /** + * @dataProvider mapOrderStatusDataProvider + */ + public function testMapOrderStatus( + $orderStatus, + $expected + ): void { + $this->assertSame( + $expected, + $this->mapper->mapOrderStatus($orderStatus) + ); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $secureType, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapSecureType($secureType, $txType)); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['0949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['0949', '', PosInterface::CURRENCY_TRY], + ['TRY', '', null], + ['840', '', PosInterface::CURRENCY_USD], + ['0840', '', PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', null], + ['392', '', null], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + ['Sale', PosInterface::TX_TYPE_PAY_AUTH], + ['SaleReversal', PosInterface::TX_TYPE_CANCEL], + ['GetMerchantOrderDetail', PosInterface::TX_TYPE_STATUS], + ['DrawBack', PosInterface::TX_TYPE_REFUND], + ['PartialDrawback', PosInterface::TX_TYPE_REFUND_PARTIAL], + ['', null], + ]; + } + + public static function mapOrderStatusDataProvider(): array + { + return [ + [1, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + [4, PosInterface::PAYMENT_STATUS_FULLY_REFUNDED], + [5, PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED], + [6, PosInterface::PAYMENT_STATUS_CANCELED], + [2, 2], + ['blabla', 'blabla'], + ]; + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + ['3', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE], + ['0', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE], + ['1', PosInterface::TX_TYPE_PAY_AUTH, null], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/EstPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/EstPosResponseValueMapperTest.php new file mode 100644 index 00000000..2d9d002a --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/EstPosResponseValueMapperTest.php @@ -0,0 +1,138 @@ +mapper = ResponseValueMapperFactory::createForGateway( + EstV3Pos::class, + RequestValueMapperFactory::createForGateway(EstV3Pos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(EstPos::class); + $this->assertTrue($result); + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(AkbankPos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + /** + * @dataProvider mapOrderStatusDataProvider + */ + public function testMapOrderStatus( + string $orderStatus, + string $expected + ): void { + $this->assertSame( + $expected, + $this->mapper->mapOrderStatus($orderStatus) + ); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $secureType, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapSecureType($secureType, $txType)); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['840', '', PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', PosInterface::CURRENCY_GBP], + ['392', '', PosInterface::CURRENCY_JPY], + ['643', '', PosInterface::CURRENCY_RUB], + ['TRY', '', null], + ]; + } + + + public static function mapTxTypeDataProvider(): array + { + return [ + ['S', PosInterface::TX_TYPE_PAY_AUTH], + ['C', PosInterface::TX_TYPE_REFUND], + ['', null], + ]; + } + + public static function mapOrderStatusDataProvider(): array + { + return [ + ['D', PosInterface::PAYMENT_STATUS_ERROR], + ['ERR', PosInterface::PAYMENT_STATUS_ERROR], + ['A', PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['C', PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['S', PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['PN', PosInterface::PAYMENT_STATUS_PAYMENT_PENDING], + ['CNCL', PosInterface::PAYMENT_STATUS_CANCELED], + ['V', PosInterface::PAYMENT_STATUS_CANCELED], + ['blabla', 'blabla'], + ]; + } + + + public static function mapSecureTypeDataProvider(): array + { + return [ + ['3d', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE], + ['3d', PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE], + ['3d', '', PosInterface::MODEL_3D_SECURE], + ['3d_pay', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_PAY], + ['3d_pay', '', PosInterface::MODEL_3D_PAY], + ['3d_pay_hosting', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_PAY_HOSTING], + ['3d_host', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_HOST], + ['regular', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE], + ['regular', PosInterface::TX_TYPE_PAY_POST_AUTH, PosInterface::MODEL_NON_SECURE], + ]; + } + +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/GarantiPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/GarantiPosResponseValueMapperTest.php new file mode 100644 index 00000000..b56a3f43 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/GarantiPosResponseValueMapperTest.php @@ -0,0 +1,150 @@ +mapper = ResponseValueMapperFactory::createForGateway( + GarantiPos::class, + RequestValueMapperFactory::createForGateway(GarantiPos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(GarantiPos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + /** + * @dataProvider mapOrderStatusDataProvider + */ + public function testMapOrderStatus( + string $orderStatus, + ?string $requestTxType, + ?string $txType, + string $expected + ): void { + $this->assertSame( + $expected, + $this->mapper->mapOrderStatus($orderStatus, $requestTxType, $txType) + ); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $secureType, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapSecureType($secureType, $txType)); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['TL', PosInterface::TX_TYPE_HISTORY, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['TRY', '', null], + ['840', '', PosInterface::CURRENCY_USD], + ['USD', PosInterface::TX_TYPE_HISTORY, PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', PosInterface::CURRENCY_GBP], + ['392', '', PosInterface::CURRENCY_JPY], + ['643', '', PosInterface::CURRENCY_RUB], + ]; + } + + + public static function mapTxTypeDataProvider(): array + { + return [ + ['Satis', PosInterface::TX_TYPE_PAY_AUTH], + ['sales', PosInterface::TX_TYPE_PAY_AUTH], + ['On Otorizasyon', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['On Otorizasyon Kapama', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['Iade', PosInterface::TX_TYPE_REFUND], + ['refund', PosInterface::TX_TYPE_REFUND], + ['Iptal', PosInterface::TX_TYPE_CANCEL], + ['void', PosInterface::TX_TYPE_CANCEL], + ['', null], + ]; + } + + public static function mapOrderStatusDataProvider(): array + { + return [ + ['WAITINGPOSTAUTH', PosInterface::TX_TYPE_STATUS, null, PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED], + ['APPROVED', PosInterface::TX_TYPE_STATUS, null, 'APPROVED'], + ['blabla', PosInterface::TX_TYPE_STATUS, null, 'blabla'], + + ['Basarili', PosInterface::TX_TYPE_HISTORY, null, 'Basarili'], + ['blabla', PosInterface::TX_TYPE_HISTORY, null, 'blabla'], + + ['Basarili', PosInterface::TX_TYPE_HISTORY, PosInterface::TX_TYPE_CANCEL, PosInterface::PAYMENT_STATUS_CANCELED], + ['Onaylandi', PosInterface::TX_TYPE_HISTORY, PosInterface::TX_TYPE_CANCEL, PosInterface::PAYMENT_STATUS_CANCELED], + ['Basarili', PosInterface::TX_TYPE_HISTORY, PosInterface::TX_TYPE_REFUND, PosInterface::PAYMENT_STATUS_FULLY_REFUNDED], + ['Basarili', PosInterface::TX_TYPE_HISTORY, PosInterface::TX_TYPE_PAY_AUTH, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['Basarili', PosInterface::TX_TYPE_HISTORY, PosInterface::TX_TYPE_PAY_POST_AUTH, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['Basarili', PosInterface::TX_TYPE_HISTORY, PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::PAYMENT_STATUS_PRE_AUTH_COMPLETED], + ['Basarili', PosInterface::TX_TYPE_HISTORY, '', 'Basarili'], + ['Iptal', PosInterface::TX_TYPE_HISTORY, '', 'Iptal'], + ['', PosInterface::TX_TYPE_HISTORY, '', PosInterface::PAYMENT_STATUS_ERROR], + ['blabla', '', '', 'blabla'], + ]; + } + + + public static function mapSecureTypeDataProvider(): array + { + return [ + ['3D', PosInterface::TX_TYPE_HISTORY, PosInterface::MODEL_3D_SECURE], + ['', PosInterface::TX_TYPE_HISTORY, PosInterface::MODEL_NON_SECURE], + ['abc', PosInterface::TX_TYPE_HISTORY, null], + ['3D', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE], + ['3D', PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE], + ['3D_PAY', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_PAY], + ['3D_PAY', PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_PAY], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/InterPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/InterPosResponseValueMapperTest.php new file mode 100644 index 00000000..e0c4b8d6 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/InterPosResponseValueMapperTest.php @@ -0,0 +1,82 @@ +mapper = ResponseValueMapperFactory::createForGateway( + InterPos::class, + RequestValueMapperFactory::createForGateway(InterPos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(InterPos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + public function testMapTxType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapTxType('Auth'); + } + + public function testMapOrderStatus(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapOrderStatus('S'); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapSecureType('3DModel', PosInterface::TX_TYPE_PAY_AUTH); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['840', '', PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', PosInterface::CURRENCY_GBP], + ['392', '', PosInterface::CURRENCY_JPY], + ['643', '', PosInterface::CURRENCY_RUB], + ['TRY', '', null], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/ParamPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/ParamPosResponseValueMapperTest.php new file mode 100644 index 00000000..75bfbf50 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/ParamPosResponseValueMapperTest.php @@ -0,0 +1,124 @@ +mapper = ResponseValueMapperFactory::createForGateway( + ParamPos::class, + RequestValueMapperFactory::createForGateway(ParamPos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(ParamPos::class); + $this->assertTrue($result); + $result = $this->mapper::supports(Param3DHostPos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + public function testMapTxType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapTxType('Auth'); + } + + /** + * @dataProvider mapOrderStatusDataProvider + */ + public function testMapOrderStatus( + string $orderStatus, + ?string $preAuthStatus, + bool $isRecurringOrder, + string $expected + ): void { + $this->assertSame( + $expected, + $this->mapper->mapOrderStatus($orderStatus) + ); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame( + $expected, + $this->mapper->mapCurrency($currency, $txType) + ); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $secureType, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapSecureType($secureType, $txType)); + } + + + + public static function mapCurrencyDataProvider(): array + { + return [ + ['TL', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['TL', '', PosInterface::CURRENCY_TRY], + ['TRL', '', PosInterface::CURRENCY_TRY], + ['EUR', '', PosInterface::CURRENCY_EUR], + ['USD', '', PosInterface::CURRENCY_USD], + ['949', '', null], + ]; + } + + public static function mapOrderStatusDataProvider(): array + { + return [ + ['SUCCESS', null, false, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + ['FAIL', null, false, PosInterface::PAYMENT_STATUS_ERROR], + ['BANK_FAIL', null, false, PosInterface::PAYMENT_STATUS_ERROR], + ['CANCEL', null, false, PosInterface::PAYMENT_STATUS_CANCELED], + ['REFUND', null, false, PosInterface::PAYMENT_STATUS_FULLY_REFUNDED], + ['PARTIAL_REFUND', null, false, PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED], + ['blabla', null, true, 'blabla'], + ['blabla', null, false, 'blabla'], + ]; + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + ['3D', PosInterface::TX_TYPE_HISTORY, PosInterface::MODEL_3D_SECURE], + ['NONSECURE', PosInterface::TX_TYPE_HISTORY, PosInterface::MODEL_NON_SECURE], + ['abc', PosInterface::TX_TYPE_HISTORY, null], + ['3D', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE], + ['3D', PosInterface::TX_TYPE_PAY_PRE_AUTH, PosInterface::MODEL_3D_SECURE], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/PayFlexCPV4PosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/PayFlexCPV4PosResponseValueMapperTest.php new file mode 100644 index 00000000..5b366a78 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/PayFlexCPV4PosResponseValueMapperTest.php @@ -0,0 +1,98 @@ +mapper = ResponseValueMapperFactory::createForGateway( + PayFlexCPV4Pos::class, + RequestValueMapperFactory::createForGateway(PayFlexCPV4Pos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(PayFlexCPV4Pos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + public function testMapOrderStatus(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapOrderStatus('S'); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapSecureType('3D', PosInterface::TX_TYPE_PAY_AUTH); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['TRY', '', null], + ['840', '', PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', PosInterface::CURRENCY_GBP], + ['392', '', PosInterface::CURRENCY_JPY], + ['643', '', PosInterface::CURRENCY_RUB], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + ['Sale', PosInterface::TX_TYPE_PAY_AUTH], + ['Auth', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['Capture', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['Cancel', PosInterface::TX_TYPE_CANCEL], + ['Refund', PosInterface::TX_TYPE_REFUND], + ['TxnHistory', PosInterface::TX_TYPE_HISTORY], + ['OrderInquiry', PosInterface::TX_TYPE_STATUS], + ['', null], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/PayFlexV4PosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/PayFlexV4PosResponseValueMapperTest.php new file mode 100644 index 00000000..bf291caa --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/PayFlexV4PosResponseValueMapperTest.php @@ -0,0 +1,113 @@ +mapper = ResponseValueMapperFactory::createForGateway( + PayFlexV4Pos::class, + RequestValueMapperFactory::createForGateway(PayFlexV4Pos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(PayFlexV4Pos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + public function testMapOrderStatus(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapOrderStatus('S'); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $secureType, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapSecureType($secureType, $txType)); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['TRY', '', null], + ['840', '', PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', PosInterface::CURRENCY_GBP], + ['392', '', PosInterface::CURRENCY_JPY], + ['643', '', PosInterface::CURRENCY_RUB], + ]; + } + + public static function mapTxTypeDataProvider(): array + { + return [ + ['Sale', PosInterface::TX_TYPE_PAY_AUTH], + ['Auth', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['Capture', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['Cancel', PosInterface::TX_TYPE_CANCEL], + ['Refund', PosInterface::TX_TYPE_REFUND], + ['status', PosInterface::TX_TYPE_STATUS], + ['', null], + ]; + } + + public static function mapSecureTypeDataProvider(): array + { + return [ + ['1', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_NON_SECURE], + ['2', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE], + ['3', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_PAY], + ['1', '', PosInterface::MODEL_NON_SECURE], + ['2', '', PosInterface::MODEL_3D_SECURE], + ['3', '', PosInterface::MODEL_3D_PAY], + ['4', '', null], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/PayForPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/PayForPosResponseValueMapperTest.php new file mode 100644 index 00000000..eb91d712 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/PayForPosResponseValueMapperTest.php @@ -0,0 +1,114 @@ +mapper = ResponseValueMapperFactory::createForGateway( + PayForPos::class, + RequestValueMapperFactory::createForGateway(PayForPos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(PayForPos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + public function testMapOrderStatus(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapOrderStatus('S'); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + /** + * @dataProvider mapSecureTypeDataProvider + */ + public function testMapSecureType(string $secureType, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapSecureType($secureType, $txType)); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['840', '', PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', PosInterface::CURRENCY_GBP], + ['392', '', PosInterface::CURRENCY_JPY], + ['643', '', PosInterface::CURRENCY_RUB], + ['TRY', '', null], + ]; + } + + + public static function mapTxTypeDataProvider(): array + { + return [ + ['Auth', PosInterface::TX_TYPE_PAY_AUTH], + ['PreAuth', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['PostAuth', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['Void', PosInterface::TX_TYPE_CANCEL], + ['Refund', PosInterface::TX_TYPE_REFUND], + ['TxnHistory', PosInterface::TX_TYPE_HISTORY], + ['OrderInquiry', PosInterface::TX_TYPE_STATUS], + ['blabla', null], + ]; + } + + + public static function mapSecureTypeDataProvider(): array + { + return [ + ['3DModel', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_SECURE], + ['3DModel', '', PosInterface::MODEL_3D_SECURE], + ['3DPay', '', PosInterface::MODEL_3D_PAY], + ['3DHost', '', PosInterface::MODEL_3D_HOST], + ['NonSecure', '', PosInterface::MODEL_NON_SECURE], + ['blabla', '', null], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/PosNetResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/PosNetResponseValueMapperTest.php new file mode 100644 index 00000000..c0a50ea0 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/PosNetResponseValueMapperTest.php @@ -0,0 +1,100 @@ +mapper = ResponseValueMapperFactory::createForGateway( + PosNet::class, + RequestValueMapperFactory::createForGateway(PosNet::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(PosNet::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + public function testMapOrderStatus(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapOrderStatus('S'); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapSecureType('3DModel', PosInterface::TX_TYPE_PAY_AUTH); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['TL', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['TL', '', PosInterface::CURRENCY_TRY], + ['US', '', PosInterface::CURRENCY_USD], + ['EU', '', PosInterface::CURRENCY_EUR], + ['GB', '', PosInterface::CURRENCY_GBP], + ['JP', '', PosInterface::CURRENCY_JPY], + ['RU', '', PosInterface::CURRENCY_RUB], + ['TRY', '', null], + ]; + } + + + public static function mapTxTypeDataProvider(): array + { + return [ + ['Sale', PosInterface::TX_TYPE_PAY_AUTH], + ['Auth', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['Capt', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['reverse', PosInterface::TX_TYPE_CANCEL], + ['return', PosInterface::TX_TYPE_REFUND], + ['agreement', PosInterface::TX_TYPE_STATUS], + ['', null], + ['blabla', null], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/PosNetV1PosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/PosNetV1PosResponseValueMapperTest.php new file mode 100644 index 00000000..de613467 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/PosNetV1PosResponseValueMapperTest.php @@ -0,0 +1,121 @@ +mapper = ResponseValueMapperFactory::createForGateway( + PosNetV1Pos::class, + RequestValueMapperFactory::createForGateway(PosNetV1Pos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(PosNetV1Pos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType(string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + /** + * @dataProvider mapOrderStatusDataProvider + */ + public function testMapOrderStatus( + string $orderStatus, + string $expected + ): void { + $this->assertSame( + $expected, + $this->mapper->mapOrderStatus($orderStatus) + ); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapSecureType('3DModel', PosInterface::TX_TYPE_PAY_AUTH); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['TL', PosInterface::TX_TYPE_STATUS, PosInterface::CURRENCY_TRY], + ['US', PosInterface::TX_TYPE_STATUS, PosInterface::CURRENCY_USD], + ['EU', PosInterface::TX_TYPE_STATUS, PosInterface::CURRENCY_EUR], + ['GB', PosInterface::TX_TYPE_STATUS, PosInterface::CURRENCY_GBP], + ['JP', PosInterface::TX_TYPE_STATUS, PosInterface::CURRENCY_JPY], + ['RU', PosInterface::TX_TYPE_STATUS, PosInterface::CURRENCY_RUB], + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['840', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_USD], + ['978', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_EUR], + ['826', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_GBP], + ['392', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_JPY], + ['643', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_RUB], + ['TRY', '', null], + ]; + } + + + public static function mapTxTypeDataProvider(): array + { + return [ + ['Sale', PosInterface::TX_TYPE_PAY_AUTH], + ['Auth', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['Capture', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['Reverse', PosInterface::TX_TYPE_CANCEL], + ['Return', PosInterface::TX_TYPE_REFUND], + ['TransactionInquiry', PosInterface::TX_TYPE_STATUS], + ['', null], + ['blabla', null], + ]; + } + + public static function mapOrderStatusDataProvider(): array + { + return [ + [PosInterface::TX_TYPE_PAY_AUTH, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + [PosInterface::TX_TYPE_CANCEL, PosInterface::PAYMENT_STATUS_CANCELED], + [PosInterface::TX_TYPE_REFUND, PosInterface::PAYMENT_STATUS_FULLY_REFUNDED], + ['blabla', 'blabla'], + ]; + } +} diff --git a/tests/Unit/DataMapper/ResponseValueMapper/ToslaPosResponseValueMapperTest.php b/tests/Unit/DataMapper/ResponseValueMapper/ToslaPosResponseValueMapperTest.php new file mode 100644 index 00000000..22f43246 --- /dev/null +++ b/tests/Unit/DataMapper/ResponseValueMapper/ToslaPosResponseValueMapperTest.php @@ -0,0 +1,117 @@ +mapper = ResponseValueMapperFactory::createForGateway( + ToslaPos::class, + RequestValueMapperFactory::createForGateway(ToslaPos::class) + ); + } + + public function testSupports(): void + { + $result = $this->mapper::supports(ToslaPos::class); + $this->assertTrue($result); + + $result = $this->mapper::supports(EstV3Pos::class); + $this->assertFalse($result); + } + + /** + * @dataProvider mapTxTypeDataProvider + */ + public function testMapTxType($txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapTxType($txType)); + } + + /** + * @dataProvider mapOrderStatusDataProvider + */ + public function testMapOrderStatus( + $orderStatus, + string $expected + ): void { + $this->assertSame( + $expected, + $this->mapper->mapOrderStatus($orderStatus) + ); + } + + /** + * @dataProvider mapCurrencyDataProvider + */ + public function testMapCurrency(string $currency, string $txType, ?string $expected): void + { + $this->assertSame($expected, $this->mapper->mapCurrency($currency, $txType)); + } + + public function testMapSecureType(): void + { + $this->expectException(\LogicException::class); + $this->mapper->mapSecureType('3D', PosInterface::TX_TYPE_PAY_AUTH); + } + + public static function mapCurrencyDataProvider(): array + { + return [ + ['949', PosInterface::TX_TYPE_PAY_AUTH, PosInterface::CURRENCY_TRY], + ['949', '', PosInterface::CURRENCY_TRY], + ['840', '', PosInterface::CURRENCY_USD], + ['978', '', PosInterface::CURRENCY_EUR], + ['826', '', PosInterface::CURRENCY_GBP], + ['392', '', PosInterface::CURRENCY_JPY], + ['643', '', PosInterface::CURRENCY_RUB], + ['TRY', '', null], + ]; + } + + + public static function mapTxTypeDataProvider(): array + { + return [ + ['1', PosInterface::TX_TYPE_PAY_AUTH], + ['2', PosInterface::TX_TYPE_PAY_PRE_AUTH], + ['3', PosInterface::TX_TYPE_PAY_POST_AUTH], + ['4', PosInterface::TX_TYPE_CANCEL], + ['5', PosInterface::TX_TYPE_REFUND], + [0, null], + ['', null], + ]; + } + + public static function mapOrderStatusDataProvider(): array + { + return [ + [0, PosInterface::PAYMENT_STATUS_ERROR], + [1, PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED], + [2, PosInterface::PAYMENT_STATUS_CANCELED], + [3, PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED], + [4, PosInterface::PAYMENT_STATUS_FULLY_REFUNDED], + ['blabla', 'blabla'], + ]; + } +} diff --git a/tests/Unit/Factory/AccountFactoryTest.php b/tests/Unit/Factory/AccountFactoryTest.php index e4ba21d5..f4a3e2da 100644 --- a/tests/Unit/Factory/AccountFactoryTest.php +++ b/tests/Unit/Factory/AccountFactoryTest.php @@ -29,7 +29,6 @@ public function testCreateKuveytPosAccount(): void '11111', 'kdsnsksl', PosInterface::MODEL_3D_SECURE, - PosInterface::LANG_TR, 'SUB1', ); @@ -47,7 +46,6 @@ public function testCreateAkbankPosAccount(): void '1', 'APIUSER', 'kdsnsksl', - PosInterface::LANG_EN, 'SUB1', ); @@ -55,7 +53,6 @@ public function testCreateAkbankPosAccount(): void $this->assertSame('APIUSER', $account->getTerminalId()); $this->assertSame('kdsnsksl', $account->getStoreKey()); $this->assertSame('SUB1', $account->getSubMerchantId()); - $this->assertSame(PosInterface::LANG_EN, $account->getLang()); } public function testCreateParamPosAccount(): void @@ -72,7 +69,6 @@ public function testCreateParamPosAccount(): void $this->assertSame('APIUSER', $account->getUsername()); $this->assertSame('kdsnsksl', $account->getPassword()); $this->assertSame('guid123', $account->getStoreKey()); - $this->assertSame(PosInterface::LANG_TR, $account->getLang()); } public function testCreatePayForPosAccount(): void @@ -84,7 +80,6 @@ public function testCreatePayForPosAccount(): void 'UcBN0', PosInterface::MODEL_3D_SECURE, '12345678', - PosInterface::LANG_EN, \Mews\Pos\Entity\Account\PayForAccount::MBR_ID_ZIRAAT_KATILIM ); @@ -92,7 +87,6 @@ public function testCreatePayForPosAccount(): void $this->assertSame('QNB_API_KULLANICI_3DPAY', $account->getUsername()); $this->assertSame('UcBN0', $account->getPassword()); $this->assertSame('12345678', $account->getStoreKey()); - $this->assertSame(PosInterface::LANG_EN, $account->getLang()); $this->assertSame(PayForAccount::MBR_ID_ZIRAAT_KATILIM, $account->getMbrId()); } } diff --git a/tests/Unit/Factory/CreditCardFactoryTest.php b/tests/Unit/Factory/CreditCardFactoryTest.php index 06ed02dc..daaacb77 100644 --- a/tests/Unit/Factory/CreditCardFactoryTest.php +++ b/tests/Unit/Factory/CreditCardFactoryTest.php @@ -39,9 +39,7 @@ public function testCreateForGatewaySuccess(): void ); $this->assertSame('4444555566667777', $card->getNumber()); - $this->assertSame('2022', $card->getExpireYear('Y')); - $this->assertSame('02', $card->getExpireMonth('m')); - $this->assertSame('202202', $card->getExpirationDate('Ym')); + $this->assertSame('202202', $card->getExpirationDate()->format('Ym')); $this->assertSame('john', $card->getHolderName()); $this->assertSame('123', $card->getCvv()); } diff --git a/tests/Unit/Factory/CryptFactoryTest.php b/tests/Unit/Factory/CryptFactoryTest.php index d572de5e..881c0d3e 100644 --- a/tests/Unit/Factory/CryptFactoryTest.php +++ b/tests/Unit/Factory/CryptFactoryTest.php @@ -18,11 +18,11 @@ class CryptFactoryTest extends TestCase /** * @dataProvider createGatewayCryptDataProvider */ - public function testCreateGatewayCrypt(string $gatewayClass, string $serializerClass): void + public function testCreateGatewayCrypt(string $gatewayClass, string $cryptClass): void { $logger = $this->createMock(LoggerInterface::class); $crypt = CryptFactory::createGatewayCrypt($gatewayClass, $logger); - $this->assertInstanceOf($serializerClass, $crypt); + $this->assertInstanceOf($cryptClass, $crypt); } public static function createGatewayCryptDataProvider(): array @@ -34,6 +34,7 @@ public static function createGatewayCryptDataProvider(): array [\Mews\Pos\Gateways\GarantiPos::class, \Mews\Pos\Crypt\GarantiPosCrypt::class], [\Mews\Pos\Gateways\InterPos::class, \Mews\Pos\Crypt\InterPosCrypt::class], [\Mews\Pos\Gateways\KuveytPos::class, \Mews\Pos\Crypt\KuveytPosCrypt::class], + [\Mews\Pos\Gateways\KuveytSoapApiPos::class, \Mews\Pos\Crypt\KuveytPosCrypt::class], [\Mews\Pos\Gateways\ParamPos::class, \Mews\Pos\Crypt\ParamPosCrypt::class], [\Mews\Pos\Gateways\PayFlexV4Pos::class, \Mews\Pos\Crypt\NullCrypt::class], [\Mews\Pos\Gateways\PayFlexCPV4Pos::class, \Mews\Pos\Crypt\PayFlexCPV4Crypt::class], diff --git a/tests/Unit/Factory/HttpClientFactoryTest.php b/tests/Unit/Factory/HttpClientFactoryTest.php new file mode 100644 index 00000000..5a878e40 --- /dev/null +++ b/tests/Unit/Factory/HttpClientFactoryTest.php @@ -0,0 +1,83 @@ +createMock(SerializerInterface::class), + $this->createMock(CryptInterface::class), + $this->createMock(RequestValueMapperInterface::class), + $this->createMock(LoggerInterface::class), + $this->createMock(ClientInterface::class), + $this->createMock(RequestFactoryInterface::class), + $this->createMock(StreamFactoryInterface::class), + ); + + $this->assertInstanceOf($clientClass, $client); + } + + public static function createForGatewayDataProvider(): array + { + return [ + [AkbankPosHttpClient::class], + [EstPosHttpClient::class], + [GarantiPosHttpClient::class], + [InterPosHttpClient::class], + [KuveytPos3DFormHttpClient::class], + [KuveytPosHttpClient::class], + [ParamPosHttpClient::class], + [ParamPosHttpClient::class], + [PayFlexCPV4Pos3DFormHttpClient::class], + [PayFlexCPV4PosHttpClient::class], + [PayFlexV4Pos3DFormHttpClient::class], + [PayFlexV4PosHttpClient::class], + [PayFlexV4PosSearchApiHttpClient::class], + [PayForPosHttpClient::class], + [PosNetPosHttpClient::class], + [PosNetV1PosHttpClient::class], + [ToslaPosHttpClient::class], + [VakifKatilimPos3DFormHttpClient::class], + [VakifKatilimPosHttpClient::class], + ]; + } +} diff --git a/tests/Unit/Factory/PosFactoryTest.php b/tests/Unit/Factory/PosFactoryTest.php index 1128981f..3f1bf5df 100644 --- a/tests/Unit/Factory/PosFactoryTest.php +++ b/tests/Unit/Factory/PosFactoryTest.php @@ -1,11 +1,16 @@ willReturn($configKey); $eventDispatcher = $this->createMock(\Psr\EventDispatcher\EventDispatcherInterface::class); - $httpClient = $this->createMock(\Mews\Pos\Client\HttpClient::class); $logger = $this->createMock(\Psr\Log\LoggerInterface::class); $gateway = PosFactory::createPosGateway( $account, $config, $eventDispatcher, - $httpClient, + null, $logger ); $this->assertInstanceOf($expectedGatewayClass, $gateway); @@ -134,21 +138,33 @@ public static function createPosGatewayDataExceptionProvider(): \Generator 'expected_exception_class' => \InvalidArgumentException::class, ]; - yield 'non_existing_config_key' => [ + yield 'serializer_not_found' => [ 'config' => [ 'banks' => [ - 'estpos' => [ + 'akbank' => [ 'name' => 'Akbank', - 'class' => \stdClass::class, + 'class' => \Mews\Pos\Gateways\AkbankPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://apipre.akbank.com/api/v1/payment/virtualpos', - 'gateway_3d' => 'https://virtualpospaymentgatewaypre.akbank.com/securepay', - 'gateway_3d_host' => 'https://virtualpospaymentgatewaypre.akbank.com/payhosting', ], ], ], ], 'config_key' => 'akbank', + 'expected_exception_class' => \DomainException::class, + ]; + + yield 'bank_not_found' => [ + 'config' => [ + 'banks' => [ + 'akbank' => [ + 'name' => 'Akbank', + 'class' => \Mews\Pos\Gateways\AkbankPos::class, + 'gateway_endpoints' => [ + ], + ], + ], + ], + 'config_key' => 'akbank2', 'expected_exception_class' => BankNotFoundException::class, ]; } @@ -156,34 +172,48 @@ public static function createPosGatewayDataExceptionProvider(): \Generator public static function createPosGatewayDataProvider(): \Generator { $gatewayClasses = [ - \Mews\Pos\Gateways\AkbankPos::class => false, - \Mews\Pos\Gateways\EstPos::class => false, - \Mews\Pos\Gateways\EstV3Pos::class => false, - \Mews\Pos\Gateways\GarantiPos::class => false, - \Mews\Pos\Gateways\InterPos::class => true, - \Mews\Pos\Gateways\KuveytPos::class => true, - \Mews\Pos\Gateways\ParamPos::class => false, - \Mews\Pos\Gateways\PayFlexCPV4Pos::class => true, - \Mews\Pos\Gateways\PayFlexV4Pos::class => true, - \Mews\Pos\Gateways\PayForPos::class => false, - \Mews\Pos\Gateways\PosNet::class => false, - \Mews\Pos\Gateways\PosNetV1Pos::class => false, - \Mews\Pos\Gateways\ToslaPos::class => false, - \Mews\Pos\Gateways\VakifKatilimPos::class => false, + \Mews\Pos\Gateways\AkbankPos::class => false, + \Mews\Pos\Gateways\EstPos::class => false, + \Mews\Pos\Gateways\EstV3Pos::class => false, + \Mews\Pos\Gateways\GarantiPos::class => false, + \Mews\Pos\Gateways\InterPos::class => true, + \Mews\Pos\Gateways\KuveytPos::class => true, + \Mews\Pos\Gateways\KuveytSoapApiPos::class => true, + \Mews\Pos\Gateways\Param3DHostPos::class => false, + \Mews\Pos\Gateways\ParamPos::class => false, + \Mews\Pos\Gateways\PayFlexCPV4Pos::class => true, + \Mews\Pos\Gateways\PayFlexV4Pos::class => true, + \Mews\Pos\Gateways\PayForPos::class => false, + \Mews\Pos\Gateways\PosNet::class => false, + \Mews\Pos\Gateways\PosNetV1Pos::class => false, + \Mews\Pos\Gateways\ToslaPos::class => false, + \Mews\Pos\Gateways\VakifKatilimPos::class => false, ]; foreach ($gatewayClasses as $gatewayClass => $cardTypeMapping) { + $lang = array_rand([ + PosInterface::LANG_EN, + PosInterface::LANG_TR, + null, + ]); $configKey = 'abcdse'; + $gatewayEndpoints = [ + 'payment_api' => 'https://apipre.akbank.com/api/v1/payment/virtualpos', + 'gateway_3d' => 'https://virtualpospaymentgatewaypre.akbank.com/securepay', + 'gateway_3d_host' => 'https://virtualpospaymentgatewaypre.akbank.com/payhosting', + ]; + + if (\Mews\Pos\Gateways\KuveytSoapApiPos::class === $gatewayClass) { + $gatewayEndpoints['query_api'] = 'https://apipre.akbank.com/api/v1/payment/virtualpos'; + } + $config = [ 'banks' => [ $configKey => [ 'name' => 'Akbank', 'class' => $gatewayClass, - 'gateway_endpoints' => [ - 'payment_api' => 'https://apipre.akbank.com/api/v1/payment/virtualpos', - 'gateway_3d' => 'https://virtualpospaymentgatewaypre.akbank.com/securepay', - 'gateway_3d_host' => 'https://virtualpospaymentgatewaypre.akbank.com/payhosting', - ], + 'lang' => $lang, + 'gateway_endpoints' => $gatewayEndpoints, ], ], ]; diff --git a/tests/Unit/Factory/PosHttpClientStrategyFactoryTest.php b/tests/Unit/Factory/PosHttpClientStrategyFactoryTest.php new file mode 100644 index 00000000..ce0efcfc --- /dev/null +++ b/tests/Unit/Factory/PosHttpClientStrategyFactoryTest.php @@ -0,0 +1,97 @@ +createMock(CryptInterface::class); + $requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $logger = $this->createMock(LoggerInterface::class); + + + $clientStrategy = PosHttpClientStrategyFactory::createForGateway( + $gatewayClass, + [ + 'payment_api' => 'https://example.com/api', + 'query_api' => 'https://example.com/api', + ], + $crypt, + $requestValueMapper, + $logger + ); + + $this->assertInstanceOf(GenericPosHttpClientStrategy::class, $clientStrategy); + } + + public function testCreateForGatewayWithUnsupportedGateway(): void + { + $crypt = $this->createMock(CryptInterface::class); + $requestValueMapper = $this->createMock(RequestValueMapperInterface::class); + $logger = $this->createMock(LoggerInterface::class); + + $this->expectException(\DomainException::class); + $this->expectExceptionMessage('Client not found for the gateway UnsupportedGateway'); + + PosHttpClientStrategyFactory::createForGateway( + 'UnsupportedGateway', + [ + 'payment_api' => 'https://example.com/api', + ], + $crypt, + $requestValueMapper, + $logger + ); + } + + public static function createForGatewayDataProvider(): array + { + return [ + [AkbankPos::class], + [EstV3Pos::class], + [GarantiPos::class], + [InterPos::class], + [KuveytPos::class], + [KuveytSoapApiPos::class], + [Param3DHostPos::class], + [ParamPos::class], + [PayFlexCPV4Pos::class], + [PayFlexV4Pos::class], + [PayForPos::class], + [PosNet::class], + [PosNetV1Pos::class], + [ToslaPos::class], + [VakifKatilimPos::class], + ]; + } +} diff --git a/tests/Unit/Factory/RequestDataMapperFactoryTest.php b/tests/Unit/Factory/RequestDataMapperFactoryTest.php index 18159af4..5857ba9d 100644 --- a/tests/Unit/Factory/RequestDataMapperFactoryTest.php +++ b/tests/Unit/Factory/RequestDataMapperFactoryTest.php @@ -6,7 +6,10 @@ namespace Mews\Pos\Tests\Unit\Factory; +use Mews\Pos\DataMapper\RequestValueFormatter\RequestValueFormatterInterface; +use Mews\Pos\DataMapper\RequestValueMapper\RequestValueMapperInterface; use Mews\Pos\Factory\RequestDataMapperFactory; +use Mews\Pos\PosInterface; use PHPUnit\Framework\TestCase; /** @@ -19,29 +22,35 @@ class RequestDataMapperFactoryTest extends TestCase */ public function testCreateGatewayRequestMapper(string $gatewayClass, string $mapperClass): void { + $valueMapper = $this->createMock(RequestValueMapperInterface::class); + $valueFormatter = $this->createMock(RequestValueFormatterInterface::class); $eventDispatcher = $this->createMock(\Psr\EventDispatcher\EventDispatcherInterface::class); $crypt = $this->createMock(\Mews\Pos\Crypt\CryptInterface::class); - $currencies = []; $mapper = RequestDataMapperFactory::createGatewayRequestMapper( $gatewayClass, + $valueMapper, + $valueFormatter, $eventDispatcher, $crypt, - $currencies + PosInterface::LANG_EN ); $this->assertInstanceOf($mapperClass, $mapper); } public function testCreateGatewayRequestMapperUnsupported(): void { + $valueMapper = $this->createMock(RequestValueMapperInterface::class); + $valueFormatter = $this->createMock(RequestValueFormatterInterface::class); $eventDispatcher = $this->createMock(\Psr\EventDispatcher\EventDispatcherInterface::class); $crypt = $this->createMock(\Mews\Pos\Crypt\CryptInterface::class); - $currencies = []; $this->expectException(\DomainException::class); RequestDataMapperFactory::createGatewayRequestMapper( \stdClass::class, + $valueMapper, + $valueFormatter, $eventDispatcher, $crypt, - $currencies + PosInterface::LANG_EN ); } @@ -54,7 +63,9 @@ public static function createGatewayRequestMapperDataProvider(): array [\Mews\Pos\Gateways\GarantiPos::class, \Mews\Pos\DataMapper\RequestDataMapper\GarantiPosRequestDataMapper::class], [\Mews\Pos\Gateways\InterPos::class, \Mews\Pos\DataMapper\RequestDataMapper\InterPosRequestDataMapper::class], [\Mews\Pos\Gateways\KuveytPos::class, \Mews\Pos\DataMapper\RequestDataMapper\KuveytPosRequestDataMapper::class], + [\Mews\Pos\Gateways\KuveytSoapApiPos::class, \Mews\Pos\DataMapper\RequestDataMapper\KuveytSoapApiPosRequestDataMapper::class], [\Mews\Pos\Gateways\ParamPos::class, \Mews\Pos\DataMapper\RequestDataMapper\ParamPosRequestDataMapper::class], + [\Mews\Pos\Gateways\Param3DHostPos::class, \Mews\Pos\DataMapper\RequestDataMapper\Param3DHostPosRequestDataMapper::class], [\Mews\Pos\Gateways\PayFlexCPV4Pos::class, \Mews\Pos\DataMapper\RequestDataMapper\PayFlexCPV4PosRequestDataMapper::class], [\Mews\Pos\Gateways\PayForPos::class, \Mews\Pos\DataMapper\RequestDataMapper\PayForPosRequestDataMapper::class], [\Mews\Pos\Gateways\PosNet::class, \Mews\Pos\DataMapper\RequestDataMapper\PosNetRequestDataMapper::class], diff --git a/tests/Unit/Factory/RequestValueFormatterFactoryTest.php b/tests/Unit/Factory/RequestValueFormatterFactoryTest.php new file mode 100644 index 00000000..79d37be9 --- /dev/null +++ b/tests/Unit/Factory/RequestValueFormatterFactoryTest.php @@ -0,0 +1,81 @@ +assertInstanceOf( + $expectedFormatterClass, + RequestValueFormatterFactory::createForGateway($gatewayClass) + ); + } + + public function testCreateForGatewayInvalidGateway(): void + { + $this->expectException(\DomainException::class); + RequestValueFormatterFactory::createForGateway(\stdClass::class); + } + + public static function gatewayClassDataProvider(): array + { + return [ + [ToslaPos::class, ToslaPosRequestValueFormatter::class], + [AkbankPos::class, AkbankPosRequestValueFormatter::class], + [EstPos::class, EstPosRequestValueFormatter::class], + [EstV3Pos::class, EstPosRequestValueFormatter::class], + [GarantiPos::class, GarantiPosRequestValueFormatter::class], + [InterPos::class, InterPosRequestValueFormatter::class], + [KuveytPos::class, KuveytPosRequestValueFormatter::class], + [KuveytSoapApiPos::class, KuveytPosRequestValueFormatter::class], + [VakifKatilimPos::class, VakifKatilimPosRequestValueFormatter::class], + [ParamPos::class, ParamPosRequestValueFormatter::class], + [Param3DHostPos::class, ParamPosRequestValueFormatter::class], + [PayForPos::class, PayForPosRequestValueFormatter::class], + [PosNet::class, PosNetRequestValueFormatter::class], + [PosNetV1Pos::class, PosNetV1PosRequestValueFormatter::class], + [PayFlexCPV4Pos::class, PayFlexCPV4PosRequestValueFormatter::class], + ]; + } +} diff --git a/tests/Unit/Factory/RequestValueMapperFactoryTest.php b/tests/Unit/Factory/RequestValueMapperFactoryTest.php new file mode 100644 index 00000000..7674d0cc --- /dev/null +++ b/tests/Unit/Factory/RequestValueMapperFactoryTest.php @@ -0,0 +1,84 @@ +assertInstanceOf( + $expectedFormatterClass, + RequestValueMapperFactory::createForGateway($gatewayClass) + ); + } + + public function testCreateForGatewayInvalidGateway(): void + { + $this->expectException(\DomainException::class); + RequestValueMapperFactory::createForGateway(\stdClass::class); + } + + public static function gatewayClassDataProvider(): array + { + return [ + [AkbankPos::class, AkbankPosRequestValueMapper::class], + [EstPos::class, EstPosRequestValueMapper::class], + [EstV3Pos::class, EstPosRequestValueMapper::class], + [GarantiPos::class, GarantiPosRequestValueMapper::class], + [InterPos::class, InterPosRequestValueMapper::class], + [KuveytPos::class, KuveytPosRequestValueMapper::class], + [KuveytSoapApiPos::class, KuveytPosRequestValueMapper::class], + [ParamPos::class, ParamPosRequestValueMapper::class], + [Param3DHostPos::class, ParamPosRequestValueMapper::class], + [PayFlexCPV4Pos::class, PayFlexCPV4PosRequestValueMapper::class], + [PayFlexV4Pos::class, PayFlexV4PosRequestValueMapper::class], + [PayForPos::class, PayForPosRequestValueMapper::class], + [PosNet::class, PosNetRequestValueMapper::class], + [PosNetV1Pos::class, PosNetV1PosRequestValueMapper::class], + [ToslaPos::class, ToslaPosRequestValueMapper::class], + [VakifKatilimPos::class, VakifKatilimPosRequestValueMapper::class], + ]; + } +} diff --git a/tests/Unit/Factory/ResponseDataMapperFactoryTest.php b/tests/Unit/Factory/ResponseDataMapperFactoryTest.php index 8736d1ca..5e78d12c 100644 --- a/tests/Unit/Factory/ResponseDataMapperFactoryTest.php +++ b/tests/Unit/Factory/ResponseDataMapperFactoryTest.php @@ -6,7 +6,8 @@ namespace Mews\Pos\Tests\Unit\Factory; -use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Factory\ResponseDataMapperFactory; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -21,11 +22,13 @@ class ResponseDataMapperFactoryTest extends TestCase */ public function testCreateGatewayResponseMapper(string $gatewayClass, string $mapperClass): void { - $requestDataMapper = $this->createMock(RequestDataMapperInterface::class); - $logger = $this->createMock(LoggerInterface::class); - $mapper = ResponseDataMapperFactory::createGatewayResponseMapper( + $responseDataMapper = $this->createMock(ResponseValueMapperInterface::class); + $responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $logger = $this->createMock(LoggerInterface::class); + $mapper = ResponseDataMapperFactory::createGatewayResponseMapper( $gatewayClass, - $requestDataMapper, + $responseValueFormatter, + $responseDataMapper, $logger ); $this->assertInstanceOf($mapperClass, $mapper); @@ -33,12 +36,14 @@ public function testCreateGatewayResponseMapper(string $gatewayClass, string $ma public function testCreateGatewayResponseMapperUnsupported(): void { - $requestDataMapper = $this->createMock(RequestDataMapperInterface::class); - $logger = $this->createMock(LoggerInterface::class); + $responseDataMapper = $this->createMock(ResponseValueMapperInterface::class); + $responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $logger = $this->createMock(LoggerInterface::class); $this->expectException(\DomainException::class); ResponseDataMapperFactory::createGatewayResponseMapper( \stdClass::class, - $requestDataMapper, + $responseValueFormatter, + $responseDataMapper, $logger ); } @@ -52,7 +57,9 @@ public static function createGatewayResponseMapperDataProvider(): array [\Mews\Pos\Gateways\GarantiPos::class, \Mews\Pos\DataMapper\ResponseDataMapper\GarantiPosResponseDataMapper::class], [\Mews\Pos\Gateways\InterPos::class, \Mews\Pos\DataMapper\ResponseDataMapper\InterPosResponseDataMapper::class], [\Mews\Pos\Gateways\KuveytPos::class, \Mews\Pos\DataMapper\ResponseDataMapper\KuveytPosResponseDataMapper::class], + [\Mews\Pos\Gateways\KuveytSoapApiPos::class, \Mews\Pos\DataMapper\ResponseDataMapper\KuveytSoapApiPosResponseDataMapper::class], [\Mews\Pos\Gateways\ParamPos::class, \Mews\Pos\DataMapper\ResponseDataMapper\ParamPosResponseDataMapper::class], + [\Mews\Pos\Gateways\Param3DHostPos::class, \Mews\Pos\DataMapper\ResponseDataMapper\ParamPosResponseDataMapper::class], [\Mews\Pos\Gateways\PayFlexCPV4Pos::class, \Mews\Pos\DataMapper\ResponseDataMapper\PayFlexCPV4PosResponseDataMapper::class], [\Mews\Pos\Gateways\PayFlexV4Pos::class, \Mews\Pos\DataMapper\ResponseDataMapper\PayFlexV4PosResponseDataMapper::class], [\Mews\Pos\Gateways\PayForPos::class, \Mews\Pos\DataMapper\ResponseDataMapper\PayForPosResponseDataMapper::class], diff --git a/tests/Unit/Factory/ResponseValueFormatterFactoryTest.php b/tests/Unit/Factory/ResponseValueFormatterFactoryTest.php new file mode 100644 index 00000000..415c2f6d --- /dev/null +++ b/tests/Unit/Factory/ResponseValueFormatterFactoryTest.php @@ -0,0 +1,77 @@ +assertInstanceOf($expectedFormatterClass, $formatter); + } + + public function testCreateForGatewayInvalidGateway(): void + { + $this->expectException(\DomainException::class); + ResponseValueFormatterFactory::createForGateway(\stdClass::class); + } + + public static function createForGatewayProvider(): array + { + return [ + [AkbankPos::class, BasicResponseValueFormatter::class], + [EstPos::class, EstPosResponseValueFormatter::class], + [EstV3Pos::class, EstPosResponseValueFormatter::class], + [GarantiPos::class, GarantiPosResponseValueFormatter::class], + [InterPos::class, InterPosResponseValueFormatter::class], + [KuveytPos::class, BoaPosResponseValueFormatter::class], + [KuveytSoapApiPos::class, BoaPosResponseValueFormatter::class], + [ParamPos::class, ParamPosResponseValueFormatter::class], + [Param3DHostPos::class, ParamPosResponseValueFormatter::class], + [PayFlexCPV4Pos::class, BasicResponseValueFormatter::class], + [PayFlexV4Pos::class, BasicResponseValueFormatter::class], + [PayForPos::class, BasicResponseValueFormatter::class], + [PosNet::class, PosNetResponseValueFormatter::class], + [PosNetV1Pos::class, PosNetResponseValueFormatter::class], + [ToslaPos::class, ToslaPosResponseValueFormatter::class], + [VakifKatilimPos::class, BoaPosResponseValueFormatter::class], + ]; + } +} diff --git a/tests/Unit/Factory/ResponseValueMapperFactoryTest.php b/tests/Unit/Factory/ResponseValueMapperFactoryTest.php new file mode 100644 index 00000000..6114d251 --- /dev/null +++ b/tests/Unit/Factory/ResponseValueMapperFactoryTest.php @@ -0,0 +1,134 @@ +createMock(RequestValueMapperInterface::class); + if ($txTypeMappingSupported) { + $requestValueMapper->expects($this->once()) + ->method('getTxTypeMappings') + ->willReturn([ + PosInterface::TX_TYPE_PAY_AUTH => 'Auth', + ]); + } else { + $requestValueMapper->expects($this->never()) + ->method('getTxTypeMappings'); + } + if ($secureTypeMappingSupported) { + $requestValueMapper->expects($this->once()) + ->method('getSecureTypeMappings') + ->willReturn([ + PosInterface::MODEL_3D_SECURE => '3D', + ]); + } else { + $requestValueMapper->expects($this->never()) + ->method('getSecureTypeMappings'); + } + if ($currencyMappingSupported) { + $requestValueMapper->expects($this->once()) + ->method('getCurrencyMappings') + ->willReturn([ + PosInterface::CURRENCY_EUR => '978', + ]); + } else { + $requestValueMapper->expects($this->never()) + ->method('getCurrencyMappings'); + } + $this->assertInstanceOf( + $expectedFormatterClass, + $valueMapper = ResponseValueMapperFactory::createForGateway($gatewayClass, $requestValueMapper) + ); + + if ($txTypeMappingSupported) { + $valueMapper->mapTxType(PosInterface::TX_TYPE_PAY_AUTH); + } + if ($currencyMappingSupported) { + $valueMapper->mapCurrency(PosInterface::CURRENCY_EUR); + } + if ($secureTypeMappingSupported) { + $valueMapper->mapSecureType(PosInterface::MODEL_3D_SECURE); + } + } + + public function testCreateForGatewayInvalidGateway(): void + { + $this->expectException(\DomainException::class); + ResponseValueMapperFactory::createForGateway( + \stdClass::class, + $this->createMock(RequestValueMapperInterface::class) + ); + } + + public static function gatewayClassDataProvider(): array + { + return [ + [AkbankPos::class, AkbankPosResponseValueMapper::class, true, true, false], + [EstPos::class, EstPosResponseValueMapper::class, false, true, true], + [EstV3Pos::class, EstPosResponseValueMapper::class, false, true, true], + [GarantiPos::class, GarantiPosResponseValueMapper::class, true, true, true], + [InterPos::class, InterPosResponseValueMapper::class, false, true, false], + [KuveytPos::class, BoaPosResponseValueMapper::class, true, true, true], + [KuveytSoapApiPos::class, BoaPosResponseValueMapper::class, true, true, true], + [Param3DHostPos::class, ParamPosResponseValueMapper::class, false, false, false], + [ParamPos::class, ParamPosResponseValueMapper::class, false, false, false], + [PayForPos::class, PayForPosResponseValueMapper::class, true, true, true], + [PayFlexV4Pos::class, PayFlexV4PosResponseValueMapper::class, true, true, false], + [PayFlexCPV4Pos::class, PayFlexCPV4PosResponseValueMapper::class, true, true, false], + [PosNet::class, PosNetResponseValueMapper::class, true, true, false], + [PosNetV1Pos::class, PosNetV1PosResponseValueMapper::class, true, true, false], + [ToslaPos::class, ToslaPosResponseValueMapper::class, true, true, false], + [VakifKatilimPos::class, BoaPosResponseValueMapper::class, true, true, true], + ]; + } +} diff --git a/tests/Unit/Factory/SerializerFactoryTest.php b/tests/Unit/Factory/SerializerFactoryTest.php index 9b7ba0bf..62a04e1b 100644 --- a/tests/Unit/Factory/SerializerFactoryTest.php +++ b/tests/Unit/Factory/SerializerFactoryTest.php @@ -38,7 +38,9 @@ public function createGatewaySerializerDataProvider(): array [\Mews\Pos\Gateways\GarantiPos::class, \Mews\Pos\Serializer\GarantiPosSerializer::class], [\Mews\Pos\Gateways\InterPos::class, \Mews\Pos\Serializer\InterPosSerializer::class], [\Mews\Pos\Gateways\KuveytPos::class, \Mews\Pos\Serializer\KuveytPosSerializer::class], + [\Mews\Pos\Gateways\KuveytSoapApiPos::class, \Mews\Pos\Serializer\KuveytSoapApiPosSerializer::class], [\Mews\Pos\Gateways\ParamPos::class, \Mews\Pos\Serializer\ParamPosSerializer::class], + [\Mews\Pos\Gateways\Param3DHostPos::class, \Mews\Pos\Serializer\ParamPosSerializer::class], [\Mews\Pos\Gateways\PayFlexCPV4Pos::class, \Mews\Pos\Serializer\PayFlexCPV4PosSerializer::class], [\Mews\Pos\Gateways\PayFlexV4Pos::class, \Mews\Pos\Serializer\PayFlexV4PosSerializer::class], [\Mews\Pos\Gateways\PayForPos::class, \Mews\Pos\Serializer\PayForPosSerializer::class], diff --git a/tests/Unit/Gateways/AkbankPosTest.php b/tests/Unit/Gateways/AkbankPosTest.php index 6665a603..0527ffb5 100644 --- a/tests/Unit/Gateways/AkbankPosTest.php +++ b/tests/Unit/Gateways/AkbankPosTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\AkbankPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\AkbankPosAccount; @@ -23,7 +25,6 @@ use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\AkbankPosRequestDataMapperTest; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\AkbankPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -36,8 +37,6 @@ */ class AkbankPosTest extends TestCase { - use HttpClientTestTrait; - private array $config; private CreditCardInterface $card; @@ -56,7 +55,11 @@ class AkbankPosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -68,6 +71,8 @@ class AkbankPosTest extends TestCase /** @var SerializerInterface & MockObject */ private MockObject $serializerMock; + private AkbankPosRequestValueMapper $requestValueMapper; + protected function setUp(): void { parent::setUp(); @@ -76,7 +81,6 @@ protected function setUp(): void 'name' => 'AKBANK T.A.S.', 'class' => AkbankPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://apipre.akbank.com/api/v1/payment/virtualpos', 'gateway_3d' => 'https://virtualpospaymentgateway.akbank.com/securepay', 'gateway_3d_host' => 'https://virtualpospaymentgateway.akbank.com/payhosting', ], @@ -90,11 +94,13 @@ protected function setUp(): void PosInterface::LANG_TR ); + $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->requestValueMapper = new AkbankPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(RequestDataMapperInterface::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); - $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -112,11 +118,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new AkbankPos( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -128,32 +135,12 @@ public function testInit(): void $this->assertFalse($this->pos->isTestMode()); } - /** - * @dataProvider getApiUrlDataProvider - */ - public function testGetApiURL(?string $txType, string $paymentModel, string $expected): void - { - $actual = $this->pos->getApiURL($txType, $paymentModel); - - $this->assertSame($expected, $actual); - } - - /** - * @dataProvider getApiUrlExceptionDataProvider - */ - public function testGetApiURLException(?string $txType, string $exceptionClass): void - { - $this->expectException($exceptionClass); - - $this->pos->getApiURL($txType); - } - public function testGet3DGatewayURL(): void { $actual = $this->pos->get3DGatewayURL(); $this->assertSame( - 'https://virtualpospaymentgateway.akbank.com/securepay', + $this->config['gateway_endpoints']['gateway_3d'], $actual ); } @@ -163,7 +150,7 @@ public function testGet3DHostGatewayURL(): void $actual = $this->pos->get3DGatewayURL(PosInterface::MODEL_3D_HOST); $this->assertSame( - 'https://virtualpospaymentgateway.akbank.com/payhosting', + $this->config['gateway_endpoints']['gateway_3d_host'], $actual ); } @@ -385,10 +372,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -405,10 +389,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -465,10 +445,7 @@ public function testMake3DPaymentWithoutHashCheck( $this->configureClientResponse( $txType, - 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -581,7 +558,7 @@ public function testGet3DFormDataWithBadInputs( /** * @dataProvider historyRequestDataProvider */ - public function testHistoryRequest(array $order, string $apiUrl): void + public function testHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_HISTORY; @@ -595,10 +572,7 @@ public function testHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, PosInterface::MODEL_NON_SECURE @@ -639,10 +613,7 @@ public function testOrderHistory( $this->configureClientResponse( $txType, - 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', $requestData, - $encodedRequest, - $responseContent, $decodedResponse, $order, PosInterface::MODEL_NON_SECURE @@ -658,7 +629,7 @@ public function testOrderHistory( /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -670,10 +641,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $requestData = ['createNonSecurePaymentRequestData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - $apiUrl, ['paymentResponse'], $order, PosInterface::MODEL_NON_SECURE @@ -690,7 +658,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPaymentBadRequest(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPaymentBadRequest(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -702,13 +670,11 @@ public function testMakeRegularPaymentBadRequest(array $order, string $txType, s $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - $apiUrl, ['code' => 123, 'message' => 'error'], $order, PosInterface::MODEL_NON_SECURE, + null, 400 ); @@ -719,7 +685,7 @@ public function testMakeRegularPaymentBadRequest(array $order, string $txType, s /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -732,10 +698,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - $apiUrl, ['paymentResponse'], $order, PosInterface::MODEL_NON_SECURE @@ -758,7 +721,7 @@ public function testStatusRequest(): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -771,10 +734,7 @@ public function testCancelRequest(array $order, string $apiUrl): void $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - $apiUrl, ['decodedResponse'], $order, PosInterface::MODEL_NON_SECURE @@ -791,7 +751,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $txType, string $apiUrl): void + public function testRefundRequest(array $order, string $txType): void { $account = $this->pos->getAccount(); $requestData = ['createRefundRequestData']; @@ -803,10 +763,7 @@ public function testRefundRequest(array $order, string $txType, string $apiUrl): $this->configureClientResponse( $txType, - $apiUrl, ['createRefundRequestData'], - 'request-body', - $apiUrl, ['decodedResponse'], $order, PosInterface::MODEL_NON_SECURE @@ -823,10 +780,10 @@ public function testRefundRequest(array $order, string $txType, string $apiUrl): /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; $updatedRequestData = $requestData + [ 'abc' => 'def', @@ -838,13 +795,11 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl ); $this->pos->customQuery($requestData, $apiUrl); @@ -854,73 +809,28 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/xxxx', - 'expected_api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/xxxx', + 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/xxxx', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', - ], - ]; - } - - public static function getApiUrlDataProvider(): array - { - return [ - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_SECURE, - 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', - ], - [ - 'txType' => PosInterface::TX_TYPE_HISTORY, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/portal/report/transaction', + 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', ], ]; } - public static function getApiUrlExceptionDataProvider(): array - { - return [ - [ - 'txType' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - ]; - } - - public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], ]; } @@ -929,10 +839,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', ], ]; } @@ -941,10 +850,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', ], ]; } @@ -958,7 +866,6 @@ public static function refundRequestDataProvider(): array 'amount' => 5, ], 'tx_type' => PosInterface::TX_TYPE_REFUND, - 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', ], 'partial_refund' => [ 'order' => [ @@ -967,7 +874,6 @@ public static function refundRequestDataProvider(): array 'order_amount' => 10, ], 'tx_type' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/transaction/process', ], ]; } @@ -1196,55 +1102,46 @@ public static function historyRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'batch_num' => 123, ], - 'api_url' => 'https://apipre.akbank.com/api/v1/payment/virtualpos/portal/report/transaction', ], ]; } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel, - ?int $statusCode = null + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?int $statusCode = null ): void { $updatedRequestDataPreparedEvent = null; - $this->cryptMock->expects(self::once()) - ->method('hashString') - ->with($encodedRequestData, $this->account->getStoreKey()) - ->willReturn('request-body-hash'); - - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); - - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'application/json', - 'auth-hash' => 'request-body-hash', - ], - 'body' => $encodedRequestData, - ], - $statusCode - ); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); + + $invocationMocker = $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $this->account + ); + if ($statusCode >= 400) { + $invocationMocker->willThrowException(new \RuntimeException()); + } else { + $invocationMocker->willReturn($decodedResponse); + } $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -1263,7 +1160,7 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, ) )) ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); $updatedRequestData['test-update-request-data-with-event'] = true; $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); diff --git a/tests/Unit/Gateways/EstPosTest.php b/tests/Unit/Gateways/EstPosTest.php index a17e9c58..1d5db257 100644 --- a/tests/Unit/Gateways/EstPosTest.php +++ b/tests/Unit/Gateways/EstPosTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\EstPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\EstPosAccount; @@ -22,7 +24,6 @@ use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\EstPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -35,8 +36,6 @@ */ class EstPosTest extends TestCase { - use HttpClientTestTrait; - private EstPosAccount $account; /** @var EstPos */ @@ -54,7 +53,10 @@ class EstPosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -70,6 +72,8 @@ class EstPosTest extends TestCase private array $order; + private EstPosRequestValueMapper $requestValueMapper; + protected function setUp(): void { parent::setUp(); @@ -78,7 +82,6 @@ protected function setUp(): void 'name' => 'AKBANK T.A.S.', 'class' => EstPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://entegrasyon.asseco-see.com.tr/fim/api', 'gateway_3d' => 'https://entegrasyon.asseco-see.com.tr/fim/est3Dgate', ], ]; @@ -102,11 +105,13 @@ protected function setUp(): void 'lang' => PosInterface::LANG_TR, ]; + $this->requestValueMapper = new EstPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(RequestDataMapperInterface::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -132,11 +137,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new EstPos( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -146,10 +152,7 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); @@ -174,7 +177,7 @@ public function testGet3DFormData( $order, $paymentModel, $txType, - 'https://entegrasyon.asseco-see.com.tr/fim/est3Dgate', + $this->config['gateway_endpoints']['gateway_3d'], $card ) ->willReturn(['formData']); @@ -268,7 +271,7 @@ public function testMake3DHostPaymentWithoutHashCheckSuccess(): void public function testMake3DHostPaymentHashMismatchException(): void { - $data = EstPosResponseDataMapperTest::threeDHostPaymentDataProvider()['success1']['paymentData']; + $data = EstPosResponseDataMapperTest::threeDHostPaymentDataProvider()['success1']['paymentData']; $request = Request::create('', 'POST', $data); $this->cryptMock->expects(self::once()) @@ -347,7 +350,7 @@ public function testMake3DPayPaymentWithoutHashCheckSuccess(): void public function testMake3DPayPaymentHashMismatchException(): void { - $data = EstPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData']; + $data = EstPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData']; $request = Request::create('', 'POST', $data); $this->cryptMock->expects(self::once()) @@ -379,13 +382,12 @@ public function testStatus(array $bankResponse, array $expectedData, bool $isSuc $this->configureClientResponse( $txType, - 'https://entegrasyon.asseco-see.com.tr/fim/api', $requestData, - 'request-body', - 'response-body', $bankResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -423,13 +425,12 @@ public function testOrderHistory(array $bankResponse, array $expectedData, bool $this->configureClientResponse( $txType, - 'https://entegrasyon.asseco-see.com.tr/fim/api', $requestData, - 'request-body', - 'response-body', $bankResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -461,13 +462,12 @@ public function testCancel(array $bankResponse, array $expectedData, bool $isSuc $this->configureClientResponse( $txType, - 'https://entegrasyon.asseco-see.com.tr/fim/api', $requestData, - 'request-body', - 'response-body', $bankResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -499,13 +499,12 @@ public function testRefund(array $bankResponse, array $expectedData, bool $isSuc $this->configureClientResponse( $txType, - 'https://entegrasyon.asseco-see.com.tr/fim/api', $requestData, - 'request-body', - 'response-body', $bankResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -560,13 +559,10 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - 'https://entegrasyon.asseco-see.com.tr/fim/api', $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, - PosInterface::MODEL_3D_SECURE + PosInterface::MODEL_3D_SECURE, ); $this->responseMapperMock->expects(self::once()) @@ -580,10 +576,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -640,13 +632,10 @@ public function testMake3DPaymentWithoutHashCheck( $this->configureClientResponse( $txType, - 'https://entegrasyon.asseco-see.com.tr/fim/api', $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, - PosInterface::MODEL_3D_SECURE + PosInterface::MODEL_3D_SECURE, ); $this->responseMapperMock->expects(self::once()) @@ -677,7 +666,7 @@ public function testMake3DPaymentWithoutHashCheck( public function testMake3DPaymentHashMismatchException(): void { - $data = EstPosResponseDataMapperTest::threeDPaymentDataProvider()['3d_auth_success_payment_fail']['threeDResponseData']; + $data = EstPosResponseDataMapperTest::threeDPaymentDataProvider()['3d_auth_success_payment_fail']['threeDResponseData']; $request = Request::create('', 'POST', $data); $this->cryptMock->expects(self::once()) @@ -693,10 +682,6 @@ public function testMake3DPaymentHashMismatchException(): void ->method('map3DPaymentData'); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); @@ -708,7 +693,7 @@ public function testMake3DPaymentHashMismatchException(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -721,13 +706,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['paymentResponse']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -741,7 +725,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -755,13 +739,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['paymentResponse']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -775,10 +758,10 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; $updatedRequestData = $requestData + [ 'abc' => 'def', @@ -790,13 +773,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $this->account ); $this->pos->customQuery($requestData, $apiUrl); @@ -806,18 +788,16 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://entegrasyon.asseco-see.com.tr/fim/api/xxxx', - 'expected_api_url' => 'https://entegrasyon.asseco-see.com.tr/fim/api/xxxx', + 'api_url' => 'https://entegrasyon.asseco-see.com.tr/fim/api/xxxx', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + 'api_url' => null, ], ]; } @@ -958,18 +938,16 @@ public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://entegrasyon.asseco-see.com.tr/fim/api', + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], ]; } @@ -978,34 +956,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ - 'id' => '2020110828BC', - ], - 'api_url' => 'https://entegrasyon.asseco-see.com.tr/fim/api', - ], - ]; - } - - public static function statusRequestDataProvider(): array - { - return [ - [ - 'order' => [ - 'id' => '2020110828BC', - ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', - ], - ]; - } - - public static function cancelRequestDataProvider(): array - { - return [ - [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', ], ]; } @@ -1053,35 +1006,34 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'body' => $encodedRequestData, - ], - ); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -1100,7 +1052,7 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, ) )) ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); $updatedRequestData['test-update-request-data-with-event'] = true; $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); diff --git a/tests/Unit/Gateways/GarantiPosTest.php b/tests/Unit/Gateways/GarantiPosTest.php index 5fda5a7e..166fda8d 100644 --- a/tests/Unit/Gateways/GarantiPosTest.php +++ b/tests/Unit/Gateways/GarantiPosTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\GarantiPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\GarantiPosAccount; @@ -22,7 +24,6 @@ use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\GarantiPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -35,8 +36,6 @@ */ class GarantiPosTest extends TestCase { - use HttpClientTestTrait; - private GarantiPosAccount $account; /** @var RequestDataMapperInterface & MockObject */ @@ -48,7 +47,10 @@ class GarantiPosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -67,6 +69,8 @@ class GarantiPosTest extends TestCase private CreditCardInterface $card; + private GarantiPosRequestValueMapper $requestValueMapper; + protected function setUp(): void { parent::setUp(); @@ -75,7 +79,6 @@ protected function setUp(): void 'name' => 'Garanti', 'class' => GarantiPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', 'gateway_3d' => 'https://sanalposprovtest.garantibbva.com.tr/servlet/gt3dengine', ], ]; @@ -92,11 +95,13 @@ protected function setUp(): void '123qweASD/' ); + $this->requestValueMapper = new GarantiPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(RequestDataMapperInterface::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -122,11 +127,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new GarantiPos( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -136,10 +142,7 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); @@ -163,7 +166,7 @@ public function testGet3DFormData( $order, $paymentModel, $txType, - 'https://sanalposprovtest.garantibbva.com.tr/servlet/gt3dengine', + $this->config['gateway_endpoints']['gateway_3d'], $card ) ->willReturn(['formData']); @@ -234,10 +237,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -254,10 +254,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -316,10 +312,7 @@ public function testMake3DPaymentWithoutHashCheck( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -369,10 +362,6 @@ public function testMake3DPaymentHashMismatchException(): void ->method('map3DPaymentData'); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); @@ -418,7 +407,7 @@ public function testMake3DPayPayment(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -432,13 +421,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['paymentResponse']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -452,7 +440,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -465,13 +453,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -485,7 +472,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -499,13 +486,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -519,7 +505,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -533,13 +519,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -553,7 +538,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; @@ -567,13 +552,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -587,7 +571,7 @@ public function testRefundRequest(array $order, string $apiUrl): void /** * @dataProvider historyRequestDataProvider */ - public function testHistoryRequest(array $order, string $apiUrl): void + public function testHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_HISTORY; @@ -601,13 +585,12 @@ public function testHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -621,7 +604,7 @@ public function testHistoryRequest(array $order, string $apiUrl): void /** * @dataProvider orderHistoryRequestDataProvider */ - public function testOrderHistoryRequest(array $order, string $apiUrl): void + public function testOrderHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_ORDER_HISTORY; @@ -635,13 +618,12 @@ public function testOrderHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -655,7 +637,7 @@ public function testOrderHistoryRequest(array $order, string $apiUrl): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; @@ -670,13 +652,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $this->account ); $this->pos->customQuery($requestData, $apiUrl); @@ -689,15 +670,13 @@ public static function customQueryRequestDataProvider(): array 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet/xxxx', - 'expected_api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet/xxxx', + 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet/xxxx', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + 'api_url' => null, ], ]; } @@ -783,18 +762,16 @@ public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], ]; } @@ -803,10 +780,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', ], ]; } @@ -815,10 +791,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', ], ]; } @@ -827,10 +802,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', ], ]; } @@ -839,10 +813,9 @@ public static function refundRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', ], ]; } @@ -851,10 +824,9 @@ public static function orderHistoryRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', ], ]; } @@ -901,36 +873,48 @@ public static function threeDFormDataBadInputsProvider(): array ]; } + + public static function historyRequestDataProvider(): array + { + return [ + [ + 'order' => [ + 'ip' => '127.0.0.1', + 'start_date' => new \DateTimeImmutable(), + 'end_date' => new \DateTimeImmutable(), + ], + ], + ]; + } + private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'body' => $encodedRequestData, - ], - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -956,18 +940,4 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, return $updatedRequestDataPreparedEvent; }); } - - public static function historyRequestDataProvider(): array - { - return [ - [ - 'order' => [ - 'ip' => '127.0.0.1', - 'start_date' => new \DateTimeImmutable(), - 'end_date' => new \DateTimeImmutable(), - ], - 'api_url' => 'https://sanalposprovtest.garantibbva.com.tr/VPServlet', - ], - ]; - } } diff --git a/tests/Unit/Gateways/InterPosTest.php b/tests/Unit/Gateways/InterPosTest.php index 41b3d189..7c076e89 100644 --- a/tests/Unit/Gateways/InterPosTest.php +++ b/tests/Unit/Gateways/InterPosTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\InterPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\InterPosAccount; @@ -22,7 +24,6 @@ use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\InterPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -35,8 +36,6 @@ */ class InterPosTest extends TestCase { - use HttpClientTestTrait; - private InterPosAccount $account; /** @var InterPos */ @@ -53,7 +52,10 @@ class InterPosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -62,12 +64,12 @@ class InterPosTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private MockObject $eventDispatcherMock; - /** @var SerializerInterface & MockObject */ - private MockObject $serializerMock; - private array $config; - private array $order; + private InterPosRequestValueMapper $requestValueMapper; + + /** @var SerializerInterface & MockObject */ + private MockObject $serializerMock; protected function setUp(): void { @@ -77,7 +79,6 @@ protected function setUp(): void 'name' => 'DenizBank-InterPos', 'class' => InterPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', 'gateway_3d' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', 'gateway_3d_host' => 'https://test.inter-vpos.com.tr/mpi/3DHost.aspx', ], @@ -97,22 +98,13 @@ protected function setUp(): void $merchantPass ); - $this->order = [ - 'id' => 'order222', - 'amount' => '100.25', - 'installment' => 0, - 'currency' => PosInterface::CURRENCY_TRY, - 'success_url' => 'https://domain.com/success', - 'fail_url' => 'https://domain.com/fail_url', - 'lang' => PosInterface::LANG_TR, - ]; - - + $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->requestValueMapper = new InterPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(RequestDataMapperInterface::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); - $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -130,11 +122,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new InterPos( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -144,10 +137,7 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); @@ -162,7 +152,9 @@ public function testGet3DFormData( ): void { $card = $isWithCard ? $this->card : null; $paymentModel = $isWithCard ? PosInterface::MODEL_3D_SECURE : PosInterface::MODEL_3D_HOST; - $gatewayUrl = $isWithCard ? 'https://test.inter-vpos.com.tr/mpi/Default.aspx' : 'https://test.inter-vpos.com.tr/mpi/3DHost.aspx'; + $gatewayUrl = $isWithCard + ? $this->config['gateway_endpoints']['gateway_3d'] + : $this->config['gateway_endpoints']['gateway_3d_host']; $order = ['id' => '124']; $txType = PosInterface::TX_TYPE_PAY_AUTH; @@ -244,10 +236,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -264,10 +253,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -326,10 +311,7 @@ public function testMake3DPaymentWithoutHashCheck( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -458,7 +440,7 @@ public function testOrderHistoryRequest(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -471,13 +453,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -491,7 +472,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -505,13 +486,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -526,7 +506,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -540,13 +520,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -560,7 +539,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -574,13 +553,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -594,7 +572,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; @@ -608,13 +586,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -628,7 +605,7 @@ public function testRefundRequest(array $order, string $apiUrl): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; @@ -643,13 +620,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - '$updatedRequestData', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $this->account ); $this->pos->customQuery($requestData, $apiUrl); @@ -659,18 +635,16 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx/xxxx', - 'expected_api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx/xxxx', + 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx/xxxx', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + 'api_url' => null, ], ]; } @@ -706,18 +680,16 @@ public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], ]; } @@ -726,10 +698,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', ], ]; } @@ -738,10 +709,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', ], ]; } @@ -750,10 +720,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', ], ]; } @@ -762,10 +731,9 @@ public static function refundRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test.inter-vpos.com.tr/mpi/Default.aspx', ], ]; } @@ -813,38 +781,33 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => $encodedRequestData, - ], - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') diff --git a/tests/Unit/Gateways/KuveytPosTest.php b/tests/Unit/Gateways/KuveytPosTest.php index acd6a6e0..6147fb2f 100644 --- a/tests/Unit/Gateways/KuveytPosTest.php +++ b/tests/Unit/Gateways/KuveytPosTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\KuveytPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueMapper\KuveytPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\KuveytPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; @@ -21,8 +23,6 @@ use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\KuveytPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; -use Mews\Pos\Tests\Unit\Serializer\KuveytPosSerializerTest; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -30,13 +30,11 @@ use Symfony\Component\HttpFoundation\Request; /** - * @covers \Mews\Pos\Gateways\KuveytPos - * @covers \Mews\Pos\Gateways\AbstractGateway + * @covers \Mews\Pos\Gateways\KuveytPos + * @covers \Mews\Pos\Gateways\AbstractGateway */ class KuveytPosTest extends TestCase { - use HttpClientTestTrait; - private KuveytPosAccount $account; private array $config; @@ -57,7 +55,10 @@ class KuveytPosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -69,6 +70,8 @@ class KuveytPosTest extends TestCase /** @var SerializerInterface & MockObject */ private MockObject $serializerMock; + private KuveytPosRequestValueMapper $requestValueMapper; + /** * @return void * @@ -82,9 +85,7 @@ protected function setUp(): void 'name' => 'kuveyt-pos', 'class' => KuveytPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home', - 'gateway_3d' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate', - 'query_api' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl', + 'gateway_3d' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate', ], ]; @@ -107,13 +108,15 @@ protected function setUp(): void 'lang' => PosInterface::LANG_TR, ]; - $this->requestMapperMock = $this->createMock(KuveytPosRequestDataMapper::class); - $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); - $this->serializerMock = $this->createMock(SerializerInterface::class); - $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); - $this->loggerMock = $this->createMock(LoggerInterface::class); - $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); + $this->requestValueMapper = new KuveytPosRequestValueMapper(); + $this->requestMapperMock = $this->createMock(KuveytPosRequestDataMapper::class); + $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); + $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->cryptMock = $this->createMock(CryptInterface::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); $this->requestMapperMock->expects(self::any()) ->method('getCrypt') @@ -122,11 +125,12 @@ protected function setUp(): void $this->pos = new KuveytPos( $this->config, $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); @@ -146,10 +150,7 @@ protected function setUp(): void */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); @@ -166,26 +167,6 @@ public function testSetTestMode(): void $this->assertTrue($this->pos->isTestMode()); } - /** - * @dataProvider getApiUrlDataProvider - */ - public function testGetApiURL(?string $txType, ?string $paymentModel, string $expected): void - { - $actual = $this->pos->getApiURL($txType, $paymentModel); - - $this->assertSame($expected, $actual); - } - - /** - * @dataProvider getApiUrlExceptionDataProvider - */ - public function testGetApiURLException(?string $txType, ?string $paymentModel, string $exceptionClass): void - { - $this->expectException($exceptionClass); - - $this->pos->getApiURL($txType, $paymentModel); - } - /** * @return void */ @@ -199,13 +180,11 @@ public function testGetCommon3DFormDataSuccessResponse(): void $order = $this->order; $this->configureClientResponse( $txType, - 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate', $requestData, - 'encoded-request-data', $response, - ['form_inputs' => ['form-inputs'], 'gateway' => 'form-action-url'], $order, - $paymentModel + $paymentModel, + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD ); $this->requestMapperMock->expects(self::once()) @@ -219,20 +198,12 @@ public function testGetCommon3DFormDataSuccessResponse(): void ) ->willReturn($requestData); - $this->requestMapperMock->expects(self::once()) - ->method('create3DFormData') - ->with( - $this->pos->getAccount(), - ['form-inputs'], - $paymentModel, - $txType, - 'form-action-url', - $card - ) - ->willReturn(['3d-form-data']); + $this->requestMapperMock->expects(self::never()) + ->method('create3DFormData'); + $result = $this->pos->get3DFormData($order, $paymentModel, $txType, $card); - $this->assertSame(['3d-form-data'], $result); + $this->assertSame($response, $result); } /** @@ -271,6 +242,13 @@ public function testMake3DPayment( $this->cryptMock->expects(self::never()) ->method('check3DHash'); + $this->serializerMock->expects(self::once()) + ->method('decode') + ->with( + \urldecode($request->request->get('AuthenticationResponse')), + $txType + )->willReturn($decodedRequest); + $this->responseMapperMock->expects(self::once()) ->method('extractMdStatus') ->with($decodedRequest) @@ -284,69 +262,19 @@ public function testMake3DPayment( $create3DPaymentRequestData = [ 'create3DPaymentRequestData', ]; - $encodedRequestData = 'request-body'; - if ($is3DSuccess) { $this->requestMapperMock->expects(self::once()) ->method('create3DPaymentRequestData') ->with($this->account, $order, $txType, $decodedRequest) ->willReturn($create3DPaymentRequestData); - $this->prepareClient( - $this->httpClientMock, - 'response-body', - 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelProvisionGate', - [ - 'body' => $encodedRequestData, - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - ], - ] + $this->configureClientResponse( + $txType, + $create3DPaymentRequestData, + $paymentResponse, + $order, + PosInterface::MODEL_3D_SECURE, ); - $paymentModel = PosInterface::MODEL_3D_SECURE; - $this->eventDispatcherMock->expects(self::once()) - ->method('dispatch') - ->with($this->logicalAnd( - $this->isInstanceOf(RequestDataPreparedEvent::class), - $this->callback( - function (RequestDataPreparedEvent $dispatchedEvent) use ($create3DPaymentRequestData, $txType, $order, $paymentModel, &$updatedRequestDataPreparedEvent): bool { - $updatedRequestDataPreparedEvent = $dispatchedEvent; - - return get_class($this->pos) === $dispatchedEvent->getGatewayClass() - && $txType === $dispatchedEvent->getTxType() - && $create3DPaymentRequestData === $dispatchedEvent->getRequestData() - && $order === $dispatchedEvent->getOrder() - && $paymentModel === $dispatchedEvent->getPaymentModel(); - } - ) - )) - ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); - $updatedRequestData['test-update-request-data-with-event'] = true; - $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); - - return $updatedRequestDataPreparedEvent; - }); - - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::exactly(2)) - ->method('decode') - ->willReturnMap([ - [ - urldecode($request->request->get('AuthenticationResponse')), - $txType, - $decodedRequest, - ], - [ - 'response-body', - $txType, - $paymentResponse, - ], - ]); $this->responseMapperMock->expects(self::once()) ->method('map3DPaymentData') @@ -358,11 +286,7 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($create3DPaymentReques ->with($decodedRequest, null, $txType, $order) ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) - ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::once()) - ->method('decode') + ->method('create3DPaymentRequestData') ->with(urldecode($request->request->get('AuthenticationResponse')), $txType) ->willReturn($decodedRequest); } @@ -393,8 +317,6 @@ public function testMake3DPaymentException(): void $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); $this->serializerMock->expects(self::never()) ->method('decode'); @@ -405,7 +327,7 @@ public function testMake3DPaymentException(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -419,10 +341,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_NON_SECURE @@ -442,6 +361,24 @@ public function testMakeRegularPostAuthPayment(): void $this->pos->makeRegularPostPayment([]); } + public function testStatusRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->status([]); + } + + public function testRefundRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->refund([]); + } + + public function testCancelRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->cancel([]); + } + public function testHistoryRequest(): void { $this->expectException(UnsupportedTransactionTypeException::class); @@ -470,232 +407,6 @@ public function testMake3DPayPayment(): void $this->pos->make3DPayPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); } - /** - * @dataProvider statusDataProvider - */ - public function testStatus(array $bankResponse, array $expectedData, bool $isSuccess): void - { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_STATUS; - $requestData = ['createStatusRequestData']; - $order = $this->order; - - $this->requestMapperMock->expects(self::once()) - ->method('createStatusRequestData') - ->with($account, $order) - ->willReturn($requestData); - - $this->configureClientResponse( - $txType, - $this->config['gateway_endpoints']['query_api'], - $requestData, - 'request-body', - 'response-body', - $bankResponse, - $order, - PosInterface::MODEL_NON_SECURE - ); - - $this->responseMapperMock->expects(self::once()) - ->method('mapStatusResponse') - ->with($bankResponse) - ->willReturn($expectedData); - - $this->pos->status($order); - - $result = $this->pos->getResponse(); - $this->assertSame($expectedData, $result); - $this->assertSame($isSuccess, $this->pos->isSuccess()); - } - - /** - * @dataProvider cancelDataProvider - */ - public function testCancel(array $bankResponse, array $expectedData, bool $isSuccess): void - { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_CANCEL; - $requestData = ['createCancelRequestData']; - $order = $this->order; - - $this->requestMapperMock->expects(self::once()) - ->method('createCancelRequestData') - ->with($account, $order) - ->willReturn($requestData); - - $this->configureClientResponse( - $txType, - $this->config['gateway_endpoints']['query_api'], - $requestData, - 'request-body', - 'response-body', - $bankResponse, - $order, - PosInterface::MODEL_NON_SECURE - ); - - $this->responseMapperMock->expects(self::once()) - ->method('mapCancelResponse') - ->with($bankResponse) - ->willReturn($expectedData); - - $this->pos->cancel($order); - - $result = $this->pos->getResponse(); - $this->assertSame($expectedData, $result); - $this->assertSame($isSuccess, $this->pos->isSuccess()); - } - - /** - * @dataProvider refundDataProvider - */ - public function testRefund(array $bankResponse, array $expectedData, bool $isSuccess): void - { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_REFUND; - $requestData = ['createRefundRequestData']; - $encodedRequestData = 'request'; - $responseContent = 'response'; - $order = $this->order; - - $this->requestMapperMock->expects(self::once()) - ->method('createRefundRequestData') - ->with($account, $order, $txType) - ->willReturn($requestData); - - $this->configureClientResponse( - $txType, - $this->config['gateway_endpoints']['query_api'], - $requestData, - $encodedRequestData, - $responseContent, - $bankResponse, - $order, - PosInterface::MODEL_NON_SECURE - ); - - $this->responseMapperMock->expects(self::once()) - ->method('mapRefundResponse') - ->with($bankResponse) - ->willReturn($expectedData); - - $this->pos->refund($order); - - $result = $this->pos->getResponse(); - $this->assertSame($expectedData, $result); - $this->assertSame($isSuccess, $this->pos->isSuccess()); - } - - public function testSendSoapRequestEmptyResponse(): void - { - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->willReturn('MappedAction'); - - $this->requestMapperMock->expects(self::once()) - ->method('createCancelRequestData') - ->willReturn(['data']); - - $this->eventDispatcherMock->expects(self::once()) - ->method('dispatch') - ->willReturnArgument(0); - - $this->serializerMock->expects(self::once()) - ->method('encode') - ->willReturn('request'); - $this->serializerMock->expects(self::never()) - ->method('decode'); - - $this->prepareClient( - $this->httpClientMock, - '', - $this->config['gateway_endpoints']['query_api'], - [ - 'body' => 'request', - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - 'SOAPAction' => 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/MappedAction', - ], - ] - ); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('Bankaya istek başarısız!'); - $this->expectExceptionCode(9303); - - $this->pos->cancel(['data']); - } - - - public function testSendSoapRequestFaultResponse(): void - { - $responseContent = 'fault'; - $decodedResponse = [ - 's:Fault' => [ - 'faultstring' => [ - '#' => 'Some SOAP Fault', - ], - ], - ]; - - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->willReturn('MappedAction'); - - $this->requestMapperMock->expects(self::once()) - ->method('createRefundRequestData') - ->willReturn(['data']); - - $this->eventDispatcherMock->expects(self::any()) - ->method('dispatch') - ->willReturnArgument(0); - - $this->serializerMock->expects(self::once()) - ->method('encode') - ->willReturn('request'); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->willReturn($decodedResponse); - - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $this->config['gateway_endpoints']['query_api'], - [ - 'body' => 'request', - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - 'SOAPAction' => 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/MappedAction', - ], - ] - ); - - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('Some SOAP Fault'); - - $this->pos->refund(['data']); - } - - public function testSendInvalidArgumentException(): void - { - $this->requestMapperMock->expects(self::once()) - ->method('createNonSecurePaymentRequestData') - ->willReturn(['data']); - - $this->eventDispatcherMock->expects(self::any()) - ->method('dispatch') - ->willReturnArgument(0); - - $this->serializerMock->expects(self::once()) - ->method('encode') - ->willReturn(['not-a-string']); - - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Argument type must be string, array provided.'); - - $this->pos->makeRegularPayment($this->order, $this->card, PosInterface::TX_TYPE_PAY_AUTH); - } public static function make3DPaymentDataProvider(): array { @@ -706,7 +417,7 @@ public static function make3DPaymentDataProvider(): array 'request' => Request::create( '', 'POST', - ['AuthenticationResponse' => KuveytPosSerializerTest::decodeHtmlDataProvider()['3d_auth_fail']['html']] + ['AuthenticationResponse' => 'base64-encoded-xml'] ), 'decodedRequest' => KuveytPosResponseDataMapperTest::threeDPaymentDataProvider()['3d_auth_fail']['threeDResponseData'], 'paymentResponse' => KuveytPosResponseDataMapperTest::threeDPaymentDataProvider()['3d_auth_fail']['paymentData'], @@ -720,7 +431,7 @@ public static function make3DPaymentDataProvider(): array 'request' => Request::create( '', 'POST', - ['AuthenticationResponse' => KuveytPosSerializerTest::decodeHtmlDataProvider()['3d_auth_success_1']['html']] + ['AuthenticationResponse' => 'base64-encoded-xml'] ), 'decodedRequest' => KuveytPosResponseDataMapperTest::threeDPaymentDataProvider()['3d_auth_success_payment_fail_1']['threeDResponseData'], 'paymentResponse' => KuveytPosResponseDataMapperTest::threeDPaymentDataProvider()['3d_auth_success_payment_fail_1']['paymentData'], @@ -734,7 +445,7 @@ public static function make3DPaymentDataProvider(): array 'request' => Request::create( '', 'POST', - ['AuthenticationResponse' => KuveytPosSerializerTest::decodeHtmlDataProvider()['3d_auth_success_1']['html']] + ['AuthenticationResponse' => 'base64-encoded-xml'] ), 'decodedRequest' => KuveytPosResponseDataMapperTest::threeDPaymentDataProvider()['success1']['threeDResponseData'], 'paymentResponse' => KuveytPosResponseDataMapperTest::threeDPaymentDataProvider()['success1']['paymentData'], @@ -745,132 +456,14 @@ public static function make3DPaymentDataProvider(): array ]; } - public static function statusDataProvider(): iterable - { - $testData = iterator_to_array(KuveytPosResponseDataMapperTest::statusTestDataProvider()); - yield [ - 'bank_response' => $testData['fail1']['responseData'], - 'expected_data' => $testData['fail1']['expectedData'], - 'isSuccess' => false, - ]; - yield [ - 'bank_response' => $testData['success1']['responseData'], - 'expected_data' => $testData['success1']['expectedData'], - 'isSuccess' => true, - ]; - } - - public static function cancelDataProvider(): array - { - $testData = iterator_to_array(KuveytPosResponseDataMapperTest::cancelTestDataProvider()); - - return [ - 'fail_1' => [ - 'bank_response' => $testData['fail1']['responseData'], - 'expected_data' => $testData['fail1']['expectedData'], - 'isSuccess' => false, - ], - 'success_1' => [ - 'bank_response' => $testData['success1']['responseData'], - 'expected_data' => $testData['success1']['expectedData'], - 'isSuccess' => true, - ], - ]; - } - - public static function refundDataProvider(): array - { - $testData = iterator_to_array(KuveytPosResponseDataMapperTest::refundTestDataProvider()); - return [ - 'fail_1' => [ - 'bank_response' => $testData['fail1']['responseData'], - 'expected_data' => $testData['fail1']['expectedData'], - 'isSuccess' => false, - ], - 'success_1' => [ - 'bank_response' => $testData['success1']['responseData'], - 'expected_data' => $testData['success1']['expectedData'], - 'isSuccess' => true, - ], - ]; - } - public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/Non3DPayGate', - ], - ]; - } - - public static function getApiUrlDataProvider(): array - { - return [ - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_SECURE, - 'expected' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelProvisionGate', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/Non3DPayGate', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl', - ], - [ - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl', - ], - [ - 'txType' => PosInterface::TX_TYPE_STATUS, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl', - ], - ]; - } - - public static function getApiUrlExceptionDataProvider(): array - { - return [ - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_PAY, - 'exception_class' => UnsupportedTransactionTypeException::class, - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'exception_class' => UnsupportedTransactionTypeException::class, - ], - [ - 'txType' => null, - 'paymentModel' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - [ - 'txType' => null, - 'paymentModel' => PosInterface::MODEL_3D_PAY, - 'exception_class' => \InvalidArgumentException::class, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], ]; } @@ -927,55 +520,32 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel, - ?int $statusCode = null + string $txType, + array $requestData, + $decodedResponse, + array $order, + string $paymentModel, + ?string $clientTxType = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); - - $soapHeaders = []; - if (PosInterface::TX_TYPE_REFUND === $txType - || PosInterface::TX_TYPE_REFUND_PARTIAL === $txType - || PosInterface::TX_TYPE_CANCEL === $txType - || PosInterface::TX_TYPE_STATUS === $txType - ) { - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->willReturn('MappedAction'); + $clientTxType ??= $txType; - $soapHeaders = [ - 'SOAPAction' => 'http://boa.net/BOA.Integration.VirtualPos/Service/IVirtualPosService/MappedAction', - ]; - } + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($clientTxType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - ] + $soapHeaders, - 'body' => $encodedRequestData, - ], - $statusCode - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') diff --git a/tests/Unit/Gateways/KuveytSoapApiPosTest.php b/tests/Unit/Gateways/KuveytSoapApiPosTest.php new file mode 100644 index 00000000..b94b4188 --- /dev/null +++ b/tests/Unit/Gateways/KuveytSoapApiPosTest.php @@ -0,0 +1,465 @@ +config = [ + 'name' => 'kuveyt-pos', + 'class' => KuveytSoapApiPos::class, + 'gateway_endpoints' => [ + 'payment_api' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic', + ], + ]; + + $this->account = AccountFactory::createKuveytPosAccount( + 'kuveytpos', + '496', + 'apiuser1', + '400235', + 'Api123' + ); + + $this->order = [ + 'id' => '2020110828BC', + 'amount' => 10.01, + 'installment' => '0', + 'currency' => PosInterface::CURRENCY_TRY, + 'success_url' => 'http://localhost/finansbank-payfor/3d/response.php', + 'fail_url' => 'http://localhost/finansbank-payfor/3d/response.php', + 'ip' => '127.0.0.1', + 'lang' => PosInterface::LANG_TR, + ]; + + $this->requestValueMapper = new KuveytPosRequestValueMapper(); + $this->requestMapperMock = $this->createMock(KuveytSoapApiPosRequestDataMapper::class); + $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); + $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->cryptMock = $this->createMock(CryptInterface::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); + + $this->requestMapperMock->expects(self::any()) + ->method('getCrypt') + ->willReturn($this->cryptMock); + + $this->pos = new KuveytSoapApiPos( + $this->config, + $this->account, + $this->requestValueMapper, + $this->requestMapperMock, + $this->responseMapperMock, + $this->serializerMock, + $this->eventDispatcherMock, + $this->httpClientStrategyMock, + $this->loggerMock, + ); + + $this->card = CreditCardFactory::createForGateway( + $this->pos, + '4155650100416111', + 25, + 1, + '123', + 'John Doe', + CreditCardInterface::CARD_TYPE_VISA + ); + } + + /** + * @return void + */ + public function testInit(): void + { + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); + $this->assertSame($this->config, $this->pos->getConfig()); + $this->assertSame($this->account, $this->pos->getAccount()); + $this->assertFalse($this->pos->isTestMode()); + } + + /** + * @return void + */ + public function testSetTestMode(): void + { + $this->pos->setTestMode(false); + $this->assertFalse($this->pos->isTestMode()); + $this->pos->setTestMode(true); + $this->assertTrue($this->pos->isTestMode()); + } + + /** + * @return void + */ + public function testGet3DFormData(): void + { + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->get3DFormData( + [], + PosInterface::MODEL_3D_SECURE, + PosInterface::TX_TYPE_PAY_AUTH, + $this->card + ); + } + + public function testMake3DPayment(): void + { + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->make3DPayment( + Request::create( + '', + 'POST', + ), + [], + PosInterface::TX_TYPE_PAY_AUTH + ); + } + + public function testMakeRegularPayment(): void + { + $this->expectException(UnsupportedPaymentModelException::class); + + $this->pos->makeRegularPayment( + [], + $this->card, + PosInterface::TX_TYPE_PAY_AUTH + ); + } + + public function testMakeRegularPostAuthPayment(): void + { + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->makeRegularPostPayment([]); + } + + public function testHistoryRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->history([]); + } + + public function testOrderHistoryRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->orderHistory([]); + } + + public function testMake3DHostPayment(): void + { + $request = Request::create('', 'POST'); + + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->make3DHostPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); + } + + public function testMake3DPayPayment(): void + { + $request = Request::create('', 'POST'); + + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->make3DPayPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); + } + + /** + * @dataProvider statusDataProvider + */ + public function testStatus(array $bankResponse, array $expectedData, bool $isSuccess): void + { + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_STATUS; + $requestData = ['createStatusRequestData']; + $order = $this->order; + + $this->requestMapperMock->expects(self::once()) + ->method('createStatusRequestData') + ->with($account, $order) + ->willReturn($requestData); + + $this->configureClientResponse( + $txType, + $requestData, + $bankResponse, + $order, + PosInterface::MODEL_NON_SECURE, + null, + $account, + ); + + $this->responseMapperMock->expects(self::once()) + ->method('mapStatusResponse') + ->with($bankResponse) + ->willReturn($expectedData); + + $this->pos->status($order); + + $result = $this->pos->getResponse(); + $this->assertSame($expectedData, $result); + $this->assertSame($isSuccess, $this->pos->isSuccess()); + } + /** + * @dataProvider cancelDataProvider + */ + public function testCancel(array $bankResponse, array $expectedData, bool $isSuccess): void + { + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_CANCEL; + $requestData = ['createCancelRequestData']; + $order = $this->order; + + $this->requestMapperMock->expects(self::once()) + ->method('createCancelRequestData') + ->with($account, $order) + ->willReturn($requestData); + + $this->configureClientResponse( + $txType, + $requestData, + $bankResponse, + $order, + PosInterface::MODEL_NON_SECURE, + null, + $account, + ); + + $this->responseMapperMock->expects(self::once()) + ->method('mapCancelResponse') + ->with($bankResponse) + ->willReturn($expectedData); + + $this->pos->cancel($order); + + $result = $this->pos->getResponse(); + $this->assertSame($expectedData, $result); + $this->assertSame($isSuccess, $this->pos->isSuccess()); + } + + /** + * @dataProvider refundDataProvider + */ + public function testRefund(array $bankResponse, array $expectedData, bool $isSuccess): void + { + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_REFUND; + $requestData = ['createRefundRequestData']; + $order = $this->order; + + $this->requestMapperMock->expects(self::once()) + ->method('createRefundRequestData') + ->with($account, $order, $txType) + ->willReturn($requestData); + + $this->configureClientResponse( + $txType, + $requestData, + $bankResponse, + $order, + PosInterface::MODEL_NON_SECURE, + null, + $account, + ); + + $this->responseMapperMock->expects(self::once()) + ->method('mapRefundResponse') + ->with($bankResponse) + ->willReturn($expectedData); + + $this->pos->refund($order); + + $result = $this->pos->getResponse(); + $this->assertSame($expectedData, $result); + $this->assertSame($isSuccess, $this->pos->isSuccess()); + } + + public function testCustomQueryRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->customQuery([]); + } + + public static function statusDataProvider(): iterable + { + $testData = iterator_to_array(KuveytSoapApiPosResponseDataMapperTest::statusTestDataProvider()); + yield [ + 'bank_response' => $testData['fail1']['responseData'], + 'expected_data' => $testData['fail1']['expectedData'], + 'isSuccess' => false, + ]; + yield [ + 'bank_response' => $testData['success1']['responseData'], + 'expected_data' => $testData['success1']['expectedData'], + 'isSuccess' => true, + ]; + } + + public static function cancelDataProvider(): array + { + $testData = iterator_to_array(KuveytSoapApiPosResponseDataMapperTest::cancelTestDataProvider()); + + return [ + 'fail_1' => [ + 'bank_response' => $testData['fail1']['responseData'], + 'expected_data' => $testData['fail1']['expectedData'], + 'isSuccess' => false, + ], + 'success_1' => [ + 'bank_response' => $testData['success1']['responseData'], + 'expected_data' => $testData['success1']['expectedData'], + 'isSuccess' => true, + ], + ]; + } + + public static function refundDataProvider(): array + { + $testData = iterator_to_array(KuveytSoapApiPosResponseDataMapperTest::refundTestDataProvider()); + return [ + 'fail_1' => [ + 'bank_response' => $testData['fail1']['responseData'], + 'expected_data' => $testData['fail1']['expectedData'], + 'isSuccess' => false, + ], + 'success_1' => [ + 'bank_response' => $testData['success1']['responseData'], + 'expected_data' => $testData['success1']['expectedData'], + 'isSuccess' => true, + ], + ]; + } + + private function configureClientResponse( + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null + ): void { + $updatedRequestDataPreparedEvent = null; + + + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); + + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); + + + $this->eventDispatcherMock->expects(self::once()) + ->method('dispatch') + ->with($this->logicalAnd( + $this->isInstanceOf(RequestDataPreparedEvent::class), + $this->callback( + function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, $order, $paymentModel, &$updatedRequestDataPreparedEvent): bool { + $updatedRequestDataPreparedEvent = $dispatchedEvent; + + return get_class($this->pos) === $dispatchedEvent->getGatewayClass() + && $txType === $dispatchedEvent->getTxType() + && $requestData === $dispatchedEvent->getRequestData() + && $order === $dispatchedEvent->getOrder() + && $paymentModel === $dispatchedEvent->getPaymentModel(); + } + ) + )) + ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData['test-update-request-data-with-event'] = true; + $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); + + return $updatedRequestDataPreparedEvent; + }); + } +} diff --git a/tests/Unit/Gateways/Param3DHostPosTest.php b/tests/Unit/Gateways/Param3DHostPosTest.php new file mode 100644 index 00000000..afc7f64b --- /dev/null +++ b/tests/Unit/Gateways/Param3DHostPosTest.php @@ -0,0 +1,460 @@ +config = [ + 'name' => 'param-pos', + 'class' => Param3DHostPos::class, + 'gateway_endpoints' => [ + 'gateway_3d_host' => 'https://test-pos.param.com.tr/default.aspx', + ], + ]; + + $this->account = AccountFactory::createParamPosAccount( + 'param-3d-host-pos', + 10738, + 'Test', + 'Test', + '0c13d406-873b-403b-9c09-a5766840d98c' + ); + + $this->requestValueMapperMock = $this->createMock(ParamPosRequestValueMapper::class); + $this->requestMapperMock = $this->createMock(Param3DHostPosRequestDataMapper::class); + $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); + $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->cryptMock = $this->createMock(CryptInterface::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); + + $this->requestMapperMock->expects(self::any()) + ->method('getCrypt') + ->willReturn($this->cryptMock); + + $this->pos = $this->createGateway($this->config); + } + + private function createGateway(array $config, ?AbstractPosAccount $account = null): PosInterface + { + return new Param3DHostPos( + $config, + $account ?? $this->account, + $this->requestValueMapperMock, + $this->requestMapperMock, + $this->responseMapperMock, + $this->serializerMock, + $this->eventDispatcherMock, + $this->httpClientStrategyMock, + $this->loggerMock + ); + } + + /** + * @return void + */ + public function testInit(): void + { + $this->requestValueMapperMock->expects(self::once()) + ->method('getCurrencyMappings') + ->willReturn([PosInterface::CURRENCY_TRY => '1000']); + $this->assertSame($this->config, $this->pos->getConfig()); + $this->assertSame($this->account, $this->pos->getAccount()); + $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + } + + /** + * @return void + */ + public function testSetTestMode(): void + { + $this->pos->setTestMode(false); + $this->assertFalse($this->pos->isTestMode()); + $this->pos->setTestMode(true); + $this->assertTrue($this->pos->isTestMode()); + } + + /** + * @dataProvider threeDFormDataProvider + */ + public function testGet3DFormData( + array $order, + string $txType, + array $requestData, + ?string $gatewayUrl, + string $encodedRequestData, + string $responseData, + array $decodedResponseData, + $formData + ): void { + $paymentModel = PosInterface::MODEL_3D_HOST; + $this->requestMapperMock->expects(self::once()) + ->method('create3DEnrollmentCheckRequestData') + ->with($this->pos->getAccount(), $order) + ->willReturn($requestData); + + $this->configureClientResponse( + $txType, + $requestData, + $decodedResponseData, + $order, + $paymentModel + ); + + $this->requestMapperMock->expects(self::once()) + ->method('create3DFormData') + ->with( + $this->pos->getAccount(), + $order, + $paymentModel, + $txType, + $gatewayUrl, + null, + $decodedResponseData + ) + ->willReturn($formData); + + $actual = $this->pos->get3DFormData($order, $paymentModel, $txType); + + $this->assertSame($actual, $formData); + } + + /** + * @dataProvider threeDFormDataBadInputsProvider + */ + public function testGet3DFormDataWithBadInputs( + array $order, + string $paymentModel, + string $txType, + bool $isWithCard, + string $expectedExceptionClass, + string $expectedExceptionMsg + ): void { + $card = $isWithCard ? $this->createMock(CreditCardInterface::class) : null; + $this->expectException($expectedExceptionClass); + $this->expectExceptionMessage($expectedExceptionMsg); + + $this->pos->get3DFormData($order, $paymentModel, $txType, $card); + } + + public function testMake3DPayment(): void + { + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->make3DPayment( + Request::create( + '', + 'POST', + ), + [], + PosInterface::TX_TYPE_PAY_AUTH + ); + } + + public function testMake3DPayPayment(): void + { + $request = Request::create('', 'POST'); + + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->make3DPayPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); + } + + public function testMake3DHostPaymentHashMismatchException(): void + { + $request = Request::create( + '', + 'POST', + ParamPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData'] + ); + $this->cryptMock->expects(self::once()) + ->method('check3DHash') + ->with($this->account, $request->request->all()) + ->willReturn(false); + + $this->expectException(HashMismatchException::class); + + $this->pos->make3DHostPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); + } + + public function testMake3DHostPayment(): void + { + $responseData = ParamPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData']; + $request = Request::create( + '', + 'POST', + $responseData + ); + $this->cryptMock->expects(self::once()) + ->method('check3DHash') + ->with($this->account, $request->request->all()) + ->willReturn(true); + + $order = ['id' => '123']; + $txType = PosInterface::TX_TYPE_PAY_AUTH; + + $this->responseMapperMock->expects(self::once()) + ->method('map3DHostResponseData') + ->with($request->request->all(), $txType, $order) + ->willReturn(['status' => 'approved']); + + $pos = $this->pos; + + $pos->make3DHostPayment($request, $order, $txType); + + $result = $pos->getResponse(); + $this->assertSame(['status' => 'approved'], $result); + $this->assertTrue($pos->isSuccess()); + } + + /** + * @return void + */ + public function testMake3DHostPaymentWithoutHashCheck(): void + { + $config = $this->config; + $config += [ + 'gateway_configs' => [ + 'disable_3d_hash_check' => true, + ], + ]; + + $pos = $this->createGateway($config); + + $this->cryptMock->expects(self::never()) + ->method('check3DHash'); + + $responseData = ParamPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData']; + $request = Request::create( + '', + 'POST', + $responseData + ); + + $order = ['id' => '123']; + $txType = PosInterface::TX_TYPE_PAY_AUTH; + + $this->responseMapperMock->expects(self::once()) + ->method('map3DHostResponseData') + ->with($request->request->all(), $txType, $order) + ->willReturn(['status' => 'approved']); + + $pos->make3DHostPayment($request, $order, $txType); + + $result = $pos->getResponse(); + $this->assertSame(['status' => 'approved'], $result); + $this->assertTrue($pos->isSuccess()); + } + + public function testMakeRegularPayment(): void + { + $this->expectException(UnsupportedPaymentModelException::class); + + $this->pos->makeRegularPayment( + [], + $this->createMock(CreditCardInterface::class), + PosInterface::TX_TYPE_PAY_AUTH + ); + } + + public function testMakeRegularPostAuthPayment(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->makeRegularPostPayment([]); + } + + + public function testStatusRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->status([]); + } + + public function testCancelRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->cancel([]); + } + + public function testRefundRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->refund([]); + } + + public function testHistoryRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->history([]); + } + + public function testOrderHistoryRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->orderHistory([]); + } + + public function testCustomQueryRequest(): void + { + $this->expectException(UnsupportedTransactionTypeException::class); + $this->pos->customQuery([]); + } + + public static function threeDFormDataBadInputsProvider(): array + { + return [ + 'unsupported_payment_model' => [ + 'order' => ['id' => '2020110828BC'], + 'paymentModel' => PosInterface::MODEL_3D_SECURE, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'isWithCard' => true, + 'expectedExceptionClass' => \LogicException::class, + 'expectedExceptionMsg' => 'Mews\Pos\Gateways\Param3DHostPos ödeme altyapıda [pay] işlem tipi [3d_host] ödeme model(ler) desteklemektedir. Sağlanan ödeme model: [3d].', + ], + ]; + } + + public static function threeDFormDataProvider(): iterable + { + yield '3d_host' => [ + 'order' => Param3DHostPosRequestDataMapperTest::threeDFormDataProvider()['3d_host_form_data']['order'], + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'requestData' => ['request-data'], + 'gateway_url' => 'https://test-pos.param.com.tr/default.aspx', + 'encodedRequestData' => '', + 'responseData' => '', + 'decodedResponseData' => Param3DHostPosRequestDataMapperTest::threeDFormDataProvider()['3d_host_form_data']['extra_data'], + 'formData' => Param3DHostPosRequestDataMapperTest::threeDFormDataProvider()['3d_host_form_data']['expected'], + ]; + } + + private function configureClientResponse( + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null + ): void { + $updatedRequestDataPreparedEvent = null; + + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); + + $mockMethod = $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + ); + if (isset($decodedResponse['soap:Fault'])) { + $mockMethod->willThrowException(new \RuntimeException($decodedResponse['soap:Fault']['faultstring'])); + } else { + $mockMethod->willReturn($decodedResponse); + } + + + $this->eventDispatcherMock->expects(self::once()) + ->method('dispatch') + ->with($this->logicalAnd( + $this->isInstanceOf(RequestDataPreparedEvent::class), + $this->callback(function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, $order, $paymentModel, &$updatedRequestDataPreparedEvent): bool { + $updatedRequestDataPreparedEvent = $dispatchedEvent; + + return get_class($this->pos) === $dispatchedEvent->getGatewayClass() + && $txType === $dispatchedEvent->getTxType() + && $requestData === $dispatchedEvent->getRequestData() + && $order === $dispatchedEvent->getOrder() + && $paymentModel === $dispatchedEvent->getPaymentModel(); + }) + )) + ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData['test-update-request-data-with-event'] = true; + $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); + + return $updatedRequestDataPreparedEvent; + }); + } +} diff --git a/tests/Unit/Gateways/ParamPosTest.php b/tests/Unit/Gateways/ParamPosTest.php index 6f1725e1..e14e7832 100644 --- a/tests/Unit/Gateways/ParamPosTest.php +++ b/tests/Unit/Gateways/ParamPosTest.php @@ -6,16 +6,19 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\ParamPosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\ParamPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\ParamPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\RequestDataPreparedEvent; use Mews\Pos\Exceptions\HashMismatchException; +use Mews\Pos\Exceptions\UnsupportedPaymentModelException; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; @@ -24,7 +27,6 @@ use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\ParamPosRequestDataMapperTest; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\ParamPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use Mews\Pos\Tests\Unit\Serializer\ParamPosSerializerTest; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -38,8 +40,6 @@ */ class ParamPosTest extends TestCase { - use HttpClientTestTrait; - private ParamPosAccount $account; private array $config; @@ -56,7 +56,10 @@ class ParamPosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -68,6 +71,9 @@ class ParamPosTest extends TestCase /** @var SerializerInterface & MockObject */ private MockObject $serializerMock; + /** @var ParamPosRequestValueMapper & MockObject */ + private ParamPosRequestValueMapper $requestValueMapperMock; + private CreditCardInterface $card; protected function setUp(): void @@ -77,11 +83,7 @@ protected function setUp(): void $this->config = [ 'name' => 'param-pos', 'class' => ParamPos::class, - 'gateway_endpoints' => [ - 'payment_api' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', - 'payment_api_2' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', - 'gateway_3d_host' => 'https://test-pos.param.com.tr/default.aspx', - ], + 'gateway_endpoints' => [], ]; $this->account = AccountFactory::createParamPosAccount( @@ -92,13 +94,15 @@ protected function setUp(): void '0c13d406-873b-403b-9c09-a5766840d98c' ); - $this->requestMapperMock = $this->createMock(ParamPosRequestDataMapper::class); - $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); - $this->serializerMock = $this->createMock(SerializerInterface::class); - $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); - $this->loggerMock = $this->createMock(LoggerInterface::class); - $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); + $this->requestValueMapperMock = $this->createMock(ParamPosRequestValueMapper::class); + $this->requestMapperMock = $this->createMock(ParamPosRequestDataMapper::class); + $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); + $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->cryptMock = $this->createMock(CryptInterface::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); $this->requestMapperMock->expects(self::any()) ->method('getCrypt') @@ -122,12 +126,13 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new ParamPos( $config, $account ?? $this->account, + $this->requestValueMapperMock, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, - $this->loggerMock, + $this->httpClientStrategyMock, + $this->loggerMock ); } @@ -136,27 +141,13 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) + $this->requestValueMapperMock->expects(self::once()) ->method('getCurrencyMappings') ->willReturn([PosInterface::CURRENCY_TRY => '1000']); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); $this->assertFalse($this->pos->isTestMode()); - - $this->assertSame($this->config['gateway_endpoints']['gateway_3d_host'], $this->pos->get3DGatewayURL(PosInterface::MODEL_3D_HOST)); - $this->assertSame($this->config['gateway_endpoints']['payment_api'], $this->pos->getApiURL()); - $this->assertSame($this->config['gateway_endpoints']['payment_api_2'], $this->pos->getApiURL(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_HOST)); - } - - public function testGetAPIURLException(): void - { - $configs = $this->config; - unset($configs['gateway_endpoints']['payment_api_2']); - $this->pos = $this->createGateway($configs); - - $this->expectException(\RuntimeException::class); - $this->pos->getApiURL(PosInterface::TX_TYPE_PAY_AUTH, PosInterface::MODEL_3D_HOST); } /** @@ -179,7 +170,6 @@ public function testGet3DFormData( string $txType, bool $isWithCard, array $requestData, - string $apiUrl, ?string $gatewayUrl, string $encodedRequestData, string $responseData, @@ -195,10 +185,7 @@ public function testGet3DFormData( $this->configureClientResponse( $txType, - $apiUrl, $requestData, - $encodedRequestData, - $responseData, $decodedResponseData, $order, $paymentModel @@ -241,10 +228,7 @@ public function testGet3DFormDataFailResponse( $this->configureClientResponse( $txType, - 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', $requestData, - $encodedRequestData, - $responseData, $decodedResponseData, $order, $paymentModel @@ -319,10 +303,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -339,10 +320,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -401,10 +378,7 @@ public function testMake3DPaymentWithoutHashCheck( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -486,10 +460,6 @@ public function testMake3DPaymentHashMismatchException(): void ->method('map3DPaymentData'); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); @@ -585,99 +555,18 @@ public function testMake3DPayPaymentHashMismatchException(): void $this->pos->make3DPayPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); } - public function testMake3DHostPaymentHashMismatchException(): void - { - $request = Request::create( - '', - 'POST', - ParamPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData'] - ); - $this->cryptMock->expects(self::once()) - ->method('check3DHash') - ->with($this->account, $request->request->all()) - ->willReturn(false); - - $this->expectException(HashMismatchException::class); - - $this->pos->make3DHostPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); - } - - /** - * @return void - */ public function testMake3DHostPayment(): void { - $responseData = ParamPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData']; - $request = Request::create( - '', - 'POST', - $responseData - ); - $this->cryptMock->expects(self::once()) - ->method('check3DHash') - ->with($this->account, $request->request->all()) - ->willReturn(true); - - $order = ['id' => '123']; - $txType = PosInterface::TX_TYPE_PAY_AUTH; - - $this->responseMapperMock->expects(self::once()) - ->method('map3DHostResponseData') - ->with($request->request->all(), $txType, $order) - ->willReturn(['status' => 'approved']); - - $pos = $this->pos; - - $pos->make3DHostPayment($request, $order, $txType); - - $result = $pos->getResponse(); - $this->assertSame(['status' => 'approved'], $result); - $this->assertTrue($pos->isSuccess()); - } - - /** - * @return void - */ - public function testMake3DHostPaymentWithoutHashCheck(): void - { - $config = $this->config; - $config += [ - 'gateway_configs' => [ - 'disable_3d_hash_check' => true, - ], - ]; - - $pos = $this->createGateway($config); + $request = Request::create('', 'POST'); - $this->cryptMock->expects(self::never()) - ->method('check3DHash'); - - $responseData = ParamPosResponseDataMapperTest::threeDPayPaymentDataProvider()['success1']['paymentData']; - $request = Request::create( - '', - 'POST', - $responseData - ); - - $order = ['id' => '123']; - $txType = PosInterface::TX_TYPE_PAY_AUTH; - - $this->responseMapperMock->expects(self::once()) - ->method('map3DHostResponseData') - ->with($request->request->all(), $txType, $order) - ->willReturn(['status' => 'approved']); - - $pos->make3DHostPayment($request, $order, $txType); - - $result = $pos->getResponse(); - $this->assertSame(['status' => 'approved'], $result); - $this->assertTrue($pos->isSuccess()); + $this->expectException(UnsupportedPaymentModelException::class); + $this->pos->make3DHostPayment($request, [], PosInterface::TX_TYPE_PAY_AUTH); } /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -690,13 +579,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -710,7 +598,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -724,13 +612,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -745,7 +632,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -759,13 +646,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -779,7 +665,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -793,13 +679,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -813,7 +698,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; @@ -827,13 +712,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -847,7 +731,7 @@ public function testRefundRequest(array $order, string $apiUrl): void /** * @dataProvider historyRequestDataProvider */ - public function testHistoryRequest(array $order, string $apiUrl): void + public function testHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_HISTORY; @@ -861,13 +745,12 @@ public function testHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -887,7 +770,7 @@ public function testOrderHistoryRequest(): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; @@ -902,13 +785,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $this->account ); $this->pos->customQuery($requestData, $apiUrl); @@ -918,18 +800,16 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx/abc', - 'expected_api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx/abc', + 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx/abc', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + 'api_url' => null, ], ]; } @@ -1000,18 +880,16 @@ public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], ]; } @@ -1020,10 +898,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', ], ]; } @@ -1032,10 +909,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', ], ]; } @@ -1044,10 +920,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', ], ]; } @@ -1056,10 +931,9 @@ public static function refundRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', ], ]; } @@ -1070,11 +944,10 @@ public static function historyRequestDataProvider(): array return [ [ - 'order' => [ + 'order' => [ 'start_date' => $txTime->modify('-23 hour'), 'end_date' => $txTime, ], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', ], ]; } @@ -1098,7 +971,7 @@ public static function threeDFormDataBadInputsProvider(): array 'isWithCard' => false, 'create_without_card' => false, 'expectedExceptionClass' => \LogicException::class, - 'expectedExceptionMsg' => 'Mews\Pos\Gateways\ParamPos ödeme altyapıda [pay] işlem tipi [3d, 3d_pay, 3d_host, regular] ödeme model(ler) desteklemektedir. Sağlanan ödeme model: [3d_pay_hosting].', + 'expectedExceptionMsg' => 'Mews\Pos\Gateways\ParamPos ödeme altyapıda [pay] işlem tipi [3d, 3d_pay, regular] ödeme model(ler) desteklemektedir. Sağlanan ödeme model: [3d_pay_hosting].', ], '3d_pay_without_card' => [ 'order' => ['id' => '2020110828BC'], @@ -1197,7 +1070,6 @@ public static function threeDFormDataProvider(): iterable 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'isWithCard' => true, 'requestData' => ParamPosRequestDataMapperTest::paymentRegisterRequestDataProvider()[0]['expected'], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', 'gateway_url' => null, 'encodedRequestData' => 'encoded-request-data', 'responseData' => $responseTestData['3d_form_success']['input'], @@ -1206,28 +1078,12 @@ public static function threeDFormDataProvider(): iterable ]; - yield '3d_host' => [ - 'order' => ParamPosRequestDataMapperTest::threeDFormDataProvider()['3d_host_form_data']['order'], - 'paymentModel' => PosInterface::MODEL_3D_HOST, - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'isWithCard' => false, - 'requestData' => ['request-data'], - 'api_url' => 'https://test-pos.param.com.tr/to.ws/Service_Odeme.asmx', - 'gateway_url' => 'https://test-pos.param.com.tr/default.aspx', - 'encodedRequestData' => '', - 'responseData' => '', - 'decodedResponseData' => ParamPosRequestDataMapperTest::threeDFormDataProvider()['3d_host_form_data']['extra_data'], - 'formData' => ParamPosRequestDataMapperTest::threeDFormDataProvider()['3d_host_form_data']['expected'], - ]; - - yield '3d_pay' => [ 'order' => ParamPosRequestDataMapperTest::threeDFormDataProvider()['3d_pay']['order'], 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'isWithCard' => true, 'requestData' => ['request-data'], - 'api_url' => 'https://test-dmz.param.com.tr/turkpos.ws/service_turkpos_test.asmx', 'gateway_url' => null, 'encodedRequestData' => '', 'responseData' => '', @@ -1257,38 +1113,39 @@ public static function make3DPayPaymentDataProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $mockMethod = $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + ); + if (isset($decodedResponse['soap:Fault'])) { + $mockMethod->willThrowException(new \RuntimeException($decodedResponse['soap:Fault']['faultstring'])); + } else { + $mockMethod->willReturn($decodedResponse); + } - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'text/xml', - ], - 'body' => $encodedRequestData, - ], - ); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') diff --git a/tests/Unit/Gateways/PayFlexCPV4PosTest.php b/tests/Unit/Gateways/PayFlexCPV4PosTest.php index bf4cc1b2..0a3acd61 100644 --- a/tests/Unit/Gateways/PayFlexCPV4PosTest.php +++ b/tests/Unit/Gateways/PayFlexCPV4PosTest.php @@ -7,12 +7,15 @@ namespace Mews\Pos\Tests\Unit\Gateways; use Exception; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PayFlexCPV4PosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\PayFlexCPV4PosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayFlexCPV4PosResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PayFlexAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\RequestDataPreparedEvent; @@ -25,7 +28,6 @@ use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\PayFlexCPV4PosRequestDataMapperTest; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\PayFlexCPV4PosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -38,8 +40,6 @@ */ class PayFlexCPV4PosTest extends TestCase { - use HttpClientTestTrait; - private PayFlexAccount $account; /** @var PayFlexCPV4Pos */ @@ -60,7 +60,10 @@ class PayFlexCPV4PosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -69,8 +72,7 @@ class PayFlexCPV4PosTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private MockObject $eventDispatcherMock; - /** @var SerializerInterface & MockObject */ - private MockObject $serializerMock; + private PayFlexCPV4PosRequestValueMapper $requestValueMapper; protected function setUp(): void { @@ -80,8 +82,7 @@ protected function setUp(): void 'name' => 'VakifBank-PayFlex-Common-Payment', 'class' => PayFlexCPV4Pos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', - 'gateway_3d' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/RegisterTransaction', + 'gateway_3d' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/RegisterTransaction', ], ]; @@ -104,11 +105,13 @@ protected function setUp(): void 'ip' => '127.0.0.1', ]; + $this->requestValueMapper = new PayFlexCPV4PosRequestValueMapper(); $this->requestMapperMock = $this->createMock(PayFlexCPV4PosRequestDataMapper::class); $this->responseMapperMock = $this->createMock(PayFlexCPV4PosResponseDataMapper::class); - $this->serializerMock = $this->createMock(SerializerInterface::class); + $serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -119,11 +122,12 @@ protected function setUp(): void $this->pos = new PayFlexCPV4Pos( $this->config, $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, - $this->serializerMock, + $serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); @@ -135,10 +139,7 @@ protected function setUp(): void */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); @@ -155,7 +156,6 @@ public function testGet3DFormDataSuccess(): void $txType = PosInterface::TX_TYPE_PAY_AUTH; $paymentModel = PosInterface::MODEL_3D_PAY; $requestData = ['request-data']; - $encodedRequestData = 'encoded-request-data'; $card = $this->card; $order = $this->order; @@ -172,13 +172,13 @@ public function testGet3DFormDataSuccess(): void $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['gateway_3d'], $requestData, - $encodedRequestData, - 'response-body', $enrollmentResponse, $order, - $paymentModel + $paymentModel, + null, + null, + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, ); $this->requestMapperMock->expects(self::once()) @@ -231,13 +231,13 @@ public function testGet3DFormDataEnrollmentFail(): void ]; $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['gateway_3d'], $requestData, - 'encoded-request-data', - 'response-body', $enrollmentResponse, $order, - $paymentModel + $paymentModel, + null, + null, + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, ); $this->requestMapperMock->expects(self::never()) @@ -308,10 +308,7 @@ public function testMake3DPayPayment( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentStatusRequestData, - 'encoded-request-data', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_NON_SECURE @@ -328,10 +325,6 @@ public function testMake3DPayPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -377,10 +370,7 @@ public function testMake3DHostPayment( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentStatusRequestData, - 'encoded-request-data', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_NON_SECURE @@ -397,10 +387,6 @@ public function testMake3DHostPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -457,10 +443,10 @@ public function testOrderHistoryRequest(): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; $updatedRequestData = $requestData + [ 'abc' => 'def', @@ -472,13 +458,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $this->account ); $this->pos->customQuery($requestData, $apiUrl); @@ -488,18 +473,16 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://cptest.vakifbank.com.tr/CommonPayment/SecurePayment/xxxx', - 'expected_api_url' => 'https://cptest.vakifbank.com.tr/CommonPayment/SecurePayment/xxxx', + 'api_url' => 'https://cptest.vakifbank.com.tr/CommonPayment/SecurePayment/xxxx', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://cptest.vakifbank.com.tr/CommonPayment/api/VposTransaction', + 'api_url' => null, ], ]; } @@ -511,7 +494,7 @@ public static function make3DPayPaymentDataProvider(): array ); return [ - 'auth_fail' => [ + 'auth_fail' => [ 'order' => $testData['fail_response_from_gateway_1']['order'], 'txType' => PosInterface::TX_TYPE_STATUS, 'request' => Request::create( @@ -524,7 +507,7 @@ public static function make3DPayPaymentDataProvider(): array 'is3DSuccess' => false, 'isSuccess' => false, ], - 'success' => [ + 'success' => [ 'order' => $testData['success_response_from_gateway_1']['order'], 'txType' => PosInterface::TX_TYPE_STATUS, 'request' => Request::create( @@ -543,7 +526,7 @@ public static function make3DPayPaymentDataProvider(): array public static function threeDFormDataBadInputsProvider(): array { return [ - '3d_pay_without_card' => [ + '3d_pay_without_card' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, @@ -563,39 +546,36 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null, + ?string $clientTxType = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); + $clientTxType ??= $txType; - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($clientTxType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'body' => $encodedRequestData, - 'headers' => [ - 'Accept' => 'text/xml', - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - ], - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -614,7 +594,7 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, ) )) ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); $updatedRequestData['test-update-request-data-with-event'] = true; $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); diff --git a/tests/Unit/Gateways/PayFlexV4PosTest.php b/tests/Unit/Gateways/PayFlexV4PosTest.php index 56fe47aa..7c485aa2 100644 --- a/tests/Unit/Gateways/PayFlexV4PosTest.php +++ b/tests/Unit/Gateways/PayFlexV4PosTest.php @@ -7,11 +7,15 @@ namespace Mews\Pos\Tests\Unit\Gateways; use Exception; -use Mews\Pos\Client\HttpClient; +use LogicException; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PayFlexV4PosRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\PayFlexV4PosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PayFlexAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\RequestDataPreparedEvent; @@ -24,11 +28,11 @@ use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\PayFlexV4PosRequestDataMapperTest; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\PayFlexV4PosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; +use RuntimeException; use Symfony\Component\HttpFoundation\Request; /** @@ -37,8 +41,6 @@ */ class PayFlexV4PosTest extends TestCase { - use HttpClientTestTrait; - private PayFlexAccount $account; /** @var PayFlexV4Pos */ @@ -59,7 +61,10 @@ class PayFlexV4PosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -68,8 +73,7 @@ class PayFlexV4PosTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private MockObject $eventDispatcherMock; - /** @var SerializerInterface & MockObject */ - private MockObject $serializerMock; + private PayFlexV4PosRequestValueMapper $requestValueMapper; protected function setUp(): void { @@ -79,9 +83,7 @@ protected function setUp(): void 'name' => 'VakifBank-VPOS', 'class' => PayFlexV4Pos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', - 'gateway_3d' => 'https://3dsecuretest.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspxs', - 'query_api' => 'https://sanalpos.vakifbank.com.tr/v4/UIWebService/Search.aspx', + 'gateway_3d' => 'https://3dsecuretest.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspxs', ], ]; @@ -104,13 +106,15 @@ protected function setUp(): void 'ip' => '127.0.0.1', ]; - $this->requestMapperMock = $this->createMock(PayFlexV4PosRequestDataMapper::class); - $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); - $this->serializerMock = $this->createMock(SerializerInterface::class); - $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); - $this->loggerMock = $this->createMock(LoggerInterface::class); - $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); + $this->requestValueMapper = new PayFlexV4PosRequestValueMapper(); + $this->requestMapperMock = $this->createMock(PayFlexV4PosRequestDataMapper::class); + $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); + $serializerMock = $this->createMock(SerializerInterface::class); + $this->cryptMock = $this->createMock(CryptInterface::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); + $this->loggerMock = $this->createMock(LoggerInterface::class); + $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); $this->requestMapperMock->expects(self::any()) ->method('getCrypt') @@ -119,11 +123,12 @@ protected function setUp(): void $this->pos = new PayFlexV4Pos( $this->config, $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, - $this->serializerMock, + $serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); @@ -142,10 +147,7 @@ protected function setUp(): void */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); @@ -168,19 +170,19 @@ public function testGet3DFormDataEnrollmentFail(array $response): void $this->configureClientResponse( $txType, - 'https://3dsecuretest.vakifbank.com.tr:4443/MPIAPI/MPI_Enrollment.aspxs', - $requestData, $requestData, - 'response-body', $response, $order, - PosInterface::MODEL_3D_SECURE + PosInterface::MODEL_3D_SECURE, + null, + null, + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD ); $this->requestMapperMock->expects(self::never()) ->method('create3DFormData'); - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->pos->get3DFormData($order, PosInterface::MODEL_3D_SECURE, $txType, $this->card); } @@ -224,13 +226,13 @@ public function testGet3DFormDataSuccess(): void $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['gateway_3d'], - $requestData, $requestData, - 'response-body', $enrollmentResponse, $order, - $paymentModel + $paymentModel, + null, + null, + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD ); $this->requestMapperMock->expects(self::once()) @@ -273,13 +275,13 @@ public function testGet3DFormDataSubMerchantSuccess(): void $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['gateway_3d'], - $requestData, $requestData, - 'response-body', $enrollmentResponse, $order, - $paymentModel + $paymentModel, + null, + null, + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD ); $this->requestMapperMock->expects(self::once()) @@ -338,10 +340,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -358,10 +357,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -392,7 +387,7 @@ public function testMake3DPayPayment(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -405,13 +400,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -425,7 +419,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -438,13 +432,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -459,7 +452,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -473,13 +466,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -493,7 +485,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -507,13 +499,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -527,7 +518,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; @@ -541,13 +532,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -573,10 +563,10 @@ public function testOrderHistoryRequest(): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; $updatedRequestData = $requestData + [ 'abc' => 'def', @@ -588,13 +578,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $account ); $this->pos->customQuery($requestData, $apiUrl); @@ -604,18 +593,16 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx/xxx', - 'expected_api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx/xxx', + 'api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx/xxx', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + 'api_url' => null, ], ]; } @@ -642,18 +629,16 @@ public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], ]; } @@ -662,10 +647,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', ], ]; } @@ -674,10 +658,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://sanalpos.vakifbank.com.tr/v4/UIWebService/Search.aspx', ], ]; } @@ -686,10 +669,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', ], ]; } @@ -698,10 +680,9 @@ public static function refundRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx', ], ]; } @@ -757,7 +738,7 @@ public static function threeDFormDataBadInputsProvider(): array 'paymentModel' => PosInterface::MODEL_3D_SECURE, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'isWithCard' => false, - 'expectedExceptionClass' => \LogicException::class, + 'expectedExceptionClass' => LogicException::class, 'expectedExceptionMsg' => 'Bu ödeme modeli için kart bilgileri zorunlu!', ], 'unsupported_payment_model' => [ @@ -765,7 +746,7 @@ public static function threeDFormDataBadInputsProvider(): array 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'isWithCard' => false, - 'expectedExceptionClass' => \LogicException::class, + 'expectedExceptionClass' => LogicException::class, 'expectedExceptionMsg' => 'Mews\Pos\Gateways\PayFlexV4Pos ödeme altyapıda [pay] işlem tipi [3d, regular] ödeme model(ler) desteklemektedir. Sağlanan ödeme model: [3d_pay].', ], 'non_payment_tx_type' => [ @@ -773,7 +754,7 @@ public static function threeDFormDataBadInputsProvider(): array 'paymentModel' => PosInterface::MODEL_3D_SECURE, 'txType' => PosInterface::TX_TYPE_STATUS, 'isWithCard' => false, - 'expectedExceptionClass' => \LogicException::class, + 'expectedExceptionClass' => LogicException::class, 'expectedExceptionMsg' => 'Hatalı işlem tipi! Desteklenen işlem tipleri: [pay, pre]', ], 'post_auth_tx_type' => [ @@ -781,48 +762,45 @@ public static function threeDFormDataBadInputsProvider(): array 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_PAY_POST_AUTH, 'isWithCard' => true, - 'expectedExceptionClass' => \LogicException::class, + 'expectedExceptionClass' => LogicException::class, 'expectedExceptionMsg' => 'Hatalı işlem tipi! Desteklenen işlem tipleri: [pay, pre]', ], ]; } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null, + ?string $clientTxType = null ): void { - $updatedRequestDataPreparedEvent = null; + $updatedRequestDataPreparedEvent = null; + $updatedRequestDataPreparedEventData = $requestData; + $updatedRequestDataPreparedEventData['test-update-request-data-with-event'] = true; - if ($requestData === $encodedRequestData) { - $this->serializerMock->expects(self::never()) - ->method('encode'); - $encodedRequestData['test-update-request-data-with-event'] = true; - } else { - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - } + $clientTxType ??= $txType; - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($clientTxType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'form_params' => is_string($encodedRequestData) ? ['prmstr' => $encodedRequestData] : $encodedRequestData - ] - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -840,10 +818,8 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, } ) )) - ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); - $updatedRequestData['test-update-request-data-with-event'] = true; - $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); + ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent, $updatedRequestDataPreparedEventData): ?RequestDataPreparedEvent { + $updatedRequestDataPreparedEvent->setRequestData($updatedRequestDataPreparedEventData); return $updatedRequestDataPreparedEvent; }); diff --git a/tests/Unit/Gateways/PayForTest.php b/tests/Unit/Gateways/PayForTest.php index 242b9bb3..74c7f761 100644 --- a/tests/Unit/Gateways/PayForTest.php +++ b/tests/Unit/Gateways/PayForTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\PayForPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PayForAccount; @@ -21,7 +23,6 @@ use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\PayForPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -34,8 +35,6 @@ */ class PayForTest extends TestCase { - use HttpClientTestTrait; - private PayForAccount $account; private array $config; @@ -52,7 +51,10 @@ class PayForTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -66,6 +68,8 @@ class PayForTest extends TestCase private CreditCardInterface $card; + private PayForPosRequestValueMapper $requestValueMapper; + protected function setUp(): void { parent::setUp(); @@ -74,7 +78,6 @@ protected function setUp(): void 'name' => 'QNBFinansbank-PayFor', 'class' => PayForPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', 'gateway_3d' => 'https://vpostest.qnbfinansbank.com/Gateway/Default.aspx', 'gateway_3d_host' => 'https://vpostest.qnbfinansbank.com/Gateway/3DHost.aspx', ], @@ -91,11 +94,13 @@ protected function setUp(): void PayForAccount::MBR_ID_ZIRAAT_KATILIM ); + $this->requestValueMapper = new PayForPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(RequestDataMapperInterface::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -121,11 +126,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new PayForPos( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -135,16 +141,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); $this->assertFalse($this->pos->isTestMode()); $this->assertSame($this->config['gateway_endpoints']['gateway_3d_host'], $this->pos->get3DGatewayURL(PosInterface::MODEL_3D_HOST)); $this->assertSame($this->config['gateway_endpoints']['gateway_3d'], $this->pos->get3DGatewayURL()); - $this->assertSame($this->config['gateway_endpoints']['payment_api'], $this->pos->getApiURL()); } /** @@ -163,12 +165,12 @@ public function testSetTestMode(): void * [false, "3d_host", "https://vpostest.qnbfinansbank.com/Gateway/3DHost.aspx"] */ public function testGet3DFormData( - bool $isWithCard, + bool $isWithCard, string $paymentModel, string $gatewayUrl ): void { - $card = $isWithCard ? $this->card : null; - $order = ['id' => '124']; + $card = $isWithCard ? $this->card : null; + $order = ['id' => '124']; $txType = PosInterface::TX_TYPE_PAY_AUTH; $this->requestMapperMock->expects(self::once()) @@ -250,10 +252,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -270,10 +269,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -332,10 +327,7 @@ public function testMake3DPaymentWithoutHashCheck( $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -369,7 +361,7 @@ public function testMake3DPaymentWithoutHashCheck( public function testMake3DPaymentHashMismatchException(): void { - $data = PayForPosResponseDataMapperTest::threeDPaymentDataProvider()['success1']['threeDResponseData']; + $data = PayForPosResponseDataMapperTest::threeDPaymentDataProvider()['success1']['threeDResponseData']; $request = Request::create('', 'POST', $data); $this->cryptMock->expects(self::once()) @@ -385,10 +377,6 @@ public function testMake3DPaymentHashMismatchException(): void ->method('map3DPaymentData'); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); @@ -405,9 +393,9 @@ public function testMake3DPayPayment(): void ->method('check3DHash'); $responseData = ['$responseData']; - $request = Request::create('', 'POST', $responseData); - $order = ['id' => '123']; - $txType = PosInterface::TX_TYPE_PAY_AUTH; + $request = Request::create('', 'POST', $responseData); + $order = ['id' => '123']; + $txType = PosInterface::TX_TYPE_PAY_AUTH; $this->responseMapperMock->expects(self::once()) ->method('map3DPayResponseData') @@ -432,9 +420,9 @@ public function testMake3DHostPayment(): void ->method('check3DHash'); $responseData = ['$responseData']; - $request = Request::create('', 'POST', $responseData); - $order = ['id' => '123']; - $txType = PosInterface::TX_TYPE_PAY_AUTH; + $request = Request::create('', 'POST', $responseData); + $order = ['id' => '123']; + $txType = PosInterface::TX_TYPE_PAY_AUTH; $this->responseMapperMock->expects(self::once()) ->method('map3DHostResponseData') @@ -453,7 +441,7 @@ public function testMake3DHostPayment(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -466,13 +454,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -486,7 +473,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -500,13 +487,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -521,7 +507,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -535,13 +521,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -555,7 +540,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -569,13 +554,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -589,7 +573,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; @@ -603,13 +587,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -623,7 +606,7 @@ public function testRefundRequest(array $order, string $apiUrl): void /** * @dataProvider historyRequestDataProvider */ - public function testHistoryRequest(array $order, string $apiUrl): void + public function testHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_HISTORY; @@ -637,13 +620,12 @@ public function testHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -657,7 +639,7 @@ public function testHistoryRequest(array $order, string $apiUrl): void /** * @dataProvider orderHistoryRequestDataProvider */ - public function testOrderHistoryRequest(array $order, string $apiUrl): void + public function testOrderHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_ORDER_HISTORY; @@ -671,13 +653,12 @@ public function testOrderHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -691,10 +672,10 @@ public function testOrderHistoryRequest(array $order, string $apiUrl): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; $updatedRequestData = $requestData + [ 'abc' => 'def', @@ -706,13 +687,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $account ); $this->pos->customQuery($requestData, $apiUrl); @@ -722,18 +702,16 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx/xxxx', - 'expected_api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx/xxxx', + 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx/xxxx', ], [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => null, - 'expected_api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + 'api_url' => null, ], ]; } @@ -806,18 +784,16 @@ public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', + 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], ]; } @@ -826,10 +802,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', ], ]; } @@ -838,10 +813,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', ], ]; } @@ -850,10 +824,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', ], ]; } @@ -862,10 +835,9 @@ public static function refundRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', ], ]; } @@ -874,10 +846,9 @@ public static function historyRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', ], ]; } @@ -886,10 +857,9 @@ public static function orderHistoryRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://vpostest.qnbfinansbank.com/Gateway/XMLGate.aspx', ], ]; } @@ -897,7 +867,7 @@ public static function orderHistoryRequestDataProvider(): array public static function threeDFormDataBadInputsProvider(): array { return [ - '3d_secure_without_card' => [ + '3d_secure_without_card' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_SECURE, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, @@ -906,7 +876,7 @@ public static function threeDFormDataBadInputsProvider(): array 'expectedExceptionClass' => \LogicException::class, 'expectedExceptionMsg' => 'Bu ödeme modeli için kart bilgileri zorunlu!', ], - '3d_pay_without_card' => [ + '3d_pay_without_card' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, @@ -924,7 +894,7 @@ public static function threeDFormDataBadInputsProvider(): array 'expectedExceptionClass' => \LogicException::class, 'expectedExceptionMsg' => 'Mews\Pos\Gateways\PayForPos ödeme altyapıda [pay] işlem tipi [3d, 3d_pay, 3d_host, regular] ödeme model(ler) desteklemektedir. Sağlanan ödeme model: [3d_pay_hosting].', ], - 'non_payment_tx_type' => [ + 'non_payment_tx_type' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_STATUS, @@ -933,7 +903,7 @@ public static function threeDFormDataBadInputsProvider(): array 'expectedExceptionClass' => \LogicException::class, 'expectedExceptionMsg' => 'Hatalı işlem tipi! Desteklenen işlem tipleri: [pay, pre]', ], - 'post_auth_tx_type' => [ + 'post_auth_tx_type' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_PAY_POST_AUTH, @@ -946,38 +916,33 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - ], - 'body' => $encodedRequestData, - ], - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -994,7 +959,7 @@ private function configureClientResponse( }) )) ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); $updatedRequestData['test-update-request-data-with-event'] = true; $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); diff --git a/tests/Unit/Gateways/PosNetTest.php b/tests/Unit/Gateways/PosNetTest.php index ba668cc3..a8ed0e18 100644 --- a/tests/Unit/Gateways/PosNetTest.php +++ b/tests/Unit/Gateways/PosNetTest.php @@ -7,10 +7,12 @@ namespace Mews\Pos\Tests\Unit\Gateways; use Exception; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\PosNetRequestDataMapper; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\EstPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PosNetResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; @@ -25,8 +27,8 @@ use Mews\Pos\Gateways\PosNet; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; +use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\PosNetRequestDataMapperTest; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\PosNetResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -39,8 +41,6 @@ */ class PosNetTest extends TestCase { - use HttpClientTestTrait; - private PosNetAccount $account; private array $config; @@ -61,7 +61,10 @@ class PosNetTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -70,6 +73,8 @@ class PosNetTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private MockObject $eventDispatcherMock; + private EstPosRequestValueMapper $requestValueMapper; + /** @var SerializerInterface & MockObject */ private MockObject $serializerMock; @@ -81,7 +86,6 @@ protected function setUp(): void 'name' => 'Yapıkredi', 'class' => PosNet::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://setmpos.ykb.com/PosnetWebService/XML', 'gateway_3d' => 'https://setmpos.ykb.com/3DSWebService/YKBPaymentService', ], ]; @@ -105,11 +109,13 @@ protected function setUp(): void 'lang' => PosInterface::LANG_TR, ]; + $this->requestValueMapper = new EstPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(PosNetRequestDataMapper::class); $this->responseMapperMock = $this->createMock(PosNetResponseDataMapper::class); $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -127,11 +133,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new PosNet( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -141,15 +148,54 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); } + public function testGet3DFormDataSuccess(): void + { + $txType = PosInterface::TX_TYPE_PAY_AUTH; + $paymentModel = PosInterface::MODEL_3D_SECURE; + $requestData = ['request-data']; + + $responseData = PosNetRequestDataMapperTest::threeDFormDataDataProvider()['success1']['enrollment_check_response']; + $formData = PosNetRequestDataMapperTest::threeDFormDataDataProvider()['success1']['expected']; + $order = PosNetRequestDataMapperTest::threeDFormDataDataProvider()['success1']['order']; + + $this->requestMapperMock->expects(self::once()) + ->method('create3DEnrollmentCheckRequestData') + ->with($this->pos->getAccount(), $order, $txType, $this->card) + ->willReturn($requestData); + + $this->configureClientResponse( + $txType, + $requestData, + $responseData, + $order, + $paymentModel, + ); + + $this->requestMapperMock->expects(self::once()) + ->method('create3DFormData') + ->with( + $this->pos->getAccount(), + $order, + $paymentModel, + $txType, + $this->config['gateway_endpoints']['gateway_3d'], + null, + $responseData['oosRequestDataResponse'] + ) + ->willReturn($formData); + + $result = $this->pos->get3DFormData($order, PosInterface::MODEL_3D_SECURE, $txType, $this->card); + + $this->assertSame($formData, $result); + } + + /** * @return void * @@ -174,13 +220,10 @@ public function testGet3DFormDataOosTransactionFail(): void $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $requestData, - 'request-body', - 'response-body', $responseData, $order, - PosInterface::MODEL_3D_SECURE + PosInterface::MODEL_3D_SECURE, ); $this->requestMapperMock->expects(self::never()) @@ -222,6 +265,8 @@ public function testMake3DPayment( bool $is3DSuccess, bool $isSuccess ): void { + $paymentModel = PosInterface::MODEL_3D_SECURE; + if ($is3DSuccess) { $this->cryptMock->expects(self::once()) ->method('check3DHash') @@ -251,87 +296,50 @@ public function testMake3DPayment( ->with($this->account, $order, $request->request->all()) ->willReturn($resolveMerchantRequestData); - if ($is3DSuccess) { $this->requestMapperMock->expects(self::once()) ->method('create3DPaymentRequestData') ->with($this->account, $order, $txType, $request->request->all()) ->willReturn($create3DPaymentRequestData); + $request1UpdatedData = $resolveMerchantRequestData + [ + 'test-update-request-data-with-event1' => true, + ]; + $request2UpdatedData = $create3DPaymentRequestData + [ + 'test-update-request-data-with-event2' => true, + ]; - $matcher = self::exactly(2); - $updatedRequestDataPreparedEvent1 = null; - $updatedRequestDataPreparedEvent2 = null; - - $this->serializerMock->expects($matcher) - ->method('encode') - ->with($this->callback(function ($requestData) use ($matcher, &$updatedRequestDataPreparedEvent1, &$updatedRequestDataPreparedEvent2): bool { - if ($matcher->getInvocationCount() === 1) { - return $updatedRequestDataPreparedEvent1->getRequestData() === $requestData; - } - - if ($matcher->getInvocationCount() === 2) { - return $updatedRequestDataPreparedEvent2->getRequestData() === $requestData; - } - - return true; - }), $this->callback(fn ($txT): bool => $txT === $txType)) - ->willReturnCallback(function () use ($matcher): ?string { - if ($matcher->getInvocationCount() === 1) { - return 'resolveMerchantRequestData-body'; - } - - if ($matcher->getInvocationCount() === 2) { - return 'payment-request-body'; - } - - return null; - }); + $this->httpClientStrategyMock->expects(self::exactly(2)) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->serializerMock->expects(self::exactly(2)) - ->method('decode') + $this->httpClientMock->expects(self::exactly(2)) + ->method('request') ->willReturnMap([ [ - 'resolveMerchantRequestData-body', $txType, + $paymentModel, + $request1UpdatedData, + $order, + null, + null, $resolveResponse, ], [ - 'response-body-2', $txType, + $paymentModel, + $request2UpdatedData, + $order, + null, + null, $paymentResponse, ], ]); - $this->prepareHttpClientRequestMulti( - $this->httpClientMock, - [ - 'resolveMerchantRequestData-body', - 'response-body-2', - ], - [ - $this->config['gateway_endpoints']['payment_api'], - $this->config['gateway_endpoints']['payment_api'], - ], - [ - [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => \sprintf('xmldata=%s', 'resolveMerchantRequestData-body'), - ], - [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => \sprintf('xmldata=%s', 'payment-request-body'), - ], - ] - ); - - $paymentModel = PosInterface::MODEL_3D_SECURE; - - $matcher2 = self::exactly(2); + $updatedRequestDataPreparedEvent1 = null; + $updatedRequestDataPreparedEvent2 = null; + $matcher2 = self::exactly(2); $this->eventDispatcherMock->expects($matcher2) ->method('dispatch') ->with($this->logicalAnd( @@ -371,16 +379,16 @@ public function testMake3DPayment( )) ->willReturnCallback(function () use ($matcher2, &$updatedRequestDataPreparedEvent1, &$updatedRequestDataPreparedEvent2) { if ($matcher2->getInvocationCount() === 1) { - $updatedRequestData = $updatedRequestDataPreparedEvent1->getRequestData(); - $updatedRequestData['test-update-request-data-with-event'] = true; + $updatedRequestData = $updatedRequestDataPreparedEvent1->getRequestData(); + $updatedRequestData['test-update-request-data-with-event1'] = true; $updatedRequestDataPreparedEvent1->setRequestData($updatedRequestData); return $updatedRequestDataPreparedEvent1; } if ($matcher2->getInvocationCount() === 2) { - $updatedRequestData = $updatedRequestDataPreparedEvent2->getRequestData(); - $updatedRequestData['test-update-request-data-with-event'] = true; + $updatedRequestData = $updatedRequestDataPreparedEvent2->getRequestData(); + $updatedRequestData['test-update-request-data-with-event2'] = true; $updatedRequestDataPreparedEvent2->setRequestData($updatedRequestData); return $updatedRequestDataPreparedEvent2; @@ -396,13 +404,10 @@ public function testMake3DPayment( } else { $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $resolveMerchantRequestData, - 'resolveMerchantRequestData-body', - 'resolveMerchantRequestData-body', $resolveResponse, $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); $this->responseMapperMock->expects(self::once()) @@ -434,6 +439,8 @@ public function testMake3DPaymentWithoutHashCheck( bool $is3DSuccess, bool $isSuccess ): void { + $paymentModel = PosInterface::MODEL_3D_SECURE; + $config = $this->config; $config += [ 'gateway_configs' => [ @@ -468,87 +475,50 @@ public function testMake3DPaymentWithoutHashCheck( ->with($this->account, $order, $request->request->all()) ->willReturn($resolveMerchantRequestData); - if ($is3DSuccess) { $this->requestMapperMock->expects(self::once()) ->method('create3DPaymentRequestData') ->with($this->account, $order, $txType, $request->request->all()) ->willReturn($create3DPaymentRequestData); + $request1UpdatedData = $resolveMerchantRequestData + [ + 'test-update-request-data-with-event1' => true, + ]; + $request2UpdatedData = $create3DPaymentRequestData + [ + 'test-update-request-data-with-event2' => true, + ]; - $matcher = self::exactly(2); - $updatedRequestDataPreparedEvent1 = null; - $updatedRequestDataPreparedEvent2 = null; - - $this->serializerMock->expects($matcher) - ->method('encode') - ->with($this->callback(function ($requestData) use ($matcher, &$updatedRequestDataPreparedEvent1, &$updatedRequestDataPreparedEvent2): bool { - if ($matcher->getInvocationCount() === 1) { - return $updatedRequestDataPreparedEvent1->getRequestData() === $requestData; - } - - if ($matcher->getInvocationCount() === 2) { - return $updatedRequestDataPreparedEvent2->getRequestData() === $requestData; - } - - return true; - }), $this->callback(fn ($txT): bool => $txT === $txType)) - ->willReturnCallback(function () use ($matcher): ?string { - if ($matcher->getInvocationCount() === 1) { - return 'resolveMerchantRequestData-body'; - } - - if ($matcher->getInvocationCount() === 2) { - return 'payment-request-body'; - } - - return null; - }); + $this->httpClientStrategyMock->expects(self::exactly(2)) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->serializerMock->expects(self::exactly(2)) - ->method('decode') + $this->httpClientMock->expects(self::exactly(2)) + ->method('request') ->willReturnMap([ [ - 'resolveMerchantRequestData-body', $txType, + $paymentModel, + $request1UpdatedData, + $order, + null, + null, $resolveResponse, ], [ - 'response-body-2', $txType, + $paymentModel, + $request2UpdatedData, + $order, + null, + null, $paymentResponse, ], ]); - $this->prepareHttpClientRequestMulti( - $this->httpClientMock, - [ - 'resolveMerchantRequestData-body', - 'response-body-2', - ], - [ - $this->config['gateway_endpoints']['payment_api'], - $this->config['gateway_endpoints']['payment_api'], - ], - [ - [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => \sprintf('xmldata=%s', 'resolveMerchantRequestData-body'), - ], - [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => \sprintf('xmldata=%s', 'payment-request-body'), - ], - ] - ); - - $paymentModel = PosInterface::MODEL_3D_SECURE; - - $matcher2 = self::exactly(2); + $updatedRequestDataPreparedEvent1 = null; + $updatedRequestDataPreparedEvent2 = null; + $matcher2 = self::exactly(2); $this->eventDispatcherMock->expects($matcher2) ->method('dispatch') ->with($this->logicalAnd( @@ -588,16 +558,16 @@ public function testMake3DPaymentWithoutHashCheck( )) ->willReturnCallback(function () use ($matcher2, &$updatedRequestDataPreparedEvent1, &$updatedRequestDataPreparedEvent2) { if ($matcher2->getInvocationCount() === 1) { - $updatedRequestData = $updatedRequestDataPreparedEvent1->getRequestData(); - $updatedRequestData['test-update-request-data-with-event'] = true; + $updatedRequestData = $updatedRequestDataPreparedEvent1->getRequestData(); + $updatedRequestData['test-update-request-data-with-event1'] = true; $updatedRequestDataPreparedEvent1->setRequestData($updatedRequestData); return $updatedRequestDataPreparedEvent1; } if ($matcher2->getInvocationCount() === 2) { - $updatedRequestData = $updatedRequestDataPreparedEvent2->getRequestData(); - $updatedRequestData['test-update-request-data-with-event'] = true; + $updatedRequestData = $updatedRequestDataPreparedEvent2->getRequestData(); + $updatedRequestData['test-update-request-data-with-event2'] = true; $updatedRequestDataPreparedEvent2->setRequestData($updatedRequestData); return $updatedRequestDataPreparedEvent2; @@ -613,13 +583,10 @@ public function testMake3DPaymentWithoutHashCheck( } else { $this->configureClientResponse( $txType, - $this->config['gateway_endpoints']['payment_api'], $resolveMerchantRequestData, - 'resolveMerchantRequestData-body', - 'resolveMerchantRequestData-body', $resolveResponse, $order, - PosInterface::MODEL_3D_SECURE + $paymentModel ); $this->responseMapperMock->expects(self::once()) @@ -641,7 +608,7 @@ public function testMake3DPaymentWithoutHashCheck( public function testMake3DPaymentHashMismatchException(): void { $resolveResponse = PosNetResponseDataMapperTest::threeDPaymentDataProvider()['success1']['threeDResponseData']; - $request = Request::create( + $request = Request::create( '', 'POST', $resolveResponse @@ -667,10 +634,7 @@ public function testMake3DPaymentHashMismatchException(): void $this->configureClientResponse( PosInterface::TX_TYPE_PAY_AUTH, - 'https://setmpos.ykb.com/PosnetWebService/XML', $resolveMerchantRequestData, - 'request-body', - 'response-body', $resolveResponse, [], PosInterface::MODEL_3D_SECURE @@ -699,7 +663,7 @@ public function testMake3DPayPayment(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -712,13 +676,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -732,7 +695,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -746,13 +709,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -767,7 +729,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -781,13 +743,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -801,7 +762,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -815,13 +776,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -835,7 +795,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; @@ -849,13 +809,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account, ); $this->responseMapperMock->expects(self::once()) @@ -881,10 +840,10 @@ public function testOrderHistoryRequest(): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, ?string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { - $account = $this->pos->getAccount(); - $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; + $account = $this->pos->getAccount(); + $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; $updatedRequestData = $requestData + [ 'abc' => 'def', @@ -896,13 +855,12 @@ public function testCustomQueryRequest(array $requestData, ?string $apiUrl, stri $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $this->account ); $this->pos->customQuery($requestData, $apiUrl); @@ -916,14 +874,12 @@ public static function customQueryRequestDataProvider(): array 'id' => '2020110828BC', ], 'api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML/xxxx', - 'expected_api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML/xxxx', ], [ 'requestData' => [ 'id' => '2020110828BC', ], 'api_url' => null, - 'expected_api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML', ], ]; } @@ -1000,14 +956,12 @@ public static function makeRegularPaymentDataProvider(): array 'id' => '2020110828BC', ], 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML', ], [ 'order' => [ 'id' => '2020110828BC', ], 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML', ], ]; } @@ -1019,7 +973,6 @@ public static function makeRegularPostAuthPaymentDataProvider(): array 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML', ], ]; } @@ -1031,7 +984,6 @@ public static function statusRequestDataProvider(): array 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML', ], ]; } @@ -1043,7 +995,6 @@ public static function cancelRequestDataProvider(): array 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML', ], ]; } @@ -1055,7 +1006,6 @@ public static function refundRequestDataProvider(): array 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://setmpos.ykb.com/PosnetWebService/XML', ], ]; } @@ -1063,7 +1013,7 @@ public static function refundRequestDataProvider(): array public static function threeDFormDataBadInputsProvider(): array { return [ - '3d_secure_without_card' => [ + '3d_secure_without_card' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_SECURE, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, @@ -1081,7 +1031,7 @@ public static function threeDFormDataBadInputsProvider(): array 'expectedExceptionClass' => \LogicException::class, 'expectedExceptionMsg' => 'Mews\Pos\Gateways\PosNet ödeme altyapıda [pay] işlem tipi [3d, regular] ödeme model(ler) desteklemektedir. Sağlanan ödeme model: [3d_pay].', ], - 'non_payment_tx_type' => [ + 'non_payment_tx_type' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_STATUS, @@ -1090,7 +1040,7 @@ public static function threeDFormDataBadInputsProvider(): array 'expectedExceptionClass' => \LogicException::class, 'expectedExceptionMsg' => 'Hatalı işlem tipi! Desteklenen işlem tipleri: [pay, pre]', ], - 'post_auth_tx_type' => [ + 'post_auth_tx_type' => [ 'order' => ['id' => '2020110828BC'], 'paymentModel' => PosInterface::MODEL_3D_PAY, 'txType' => PosInterface::TX_TYPE_PAY_POST_AUTH, @@ -1103,38 +1053,33 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'application/x-www-form-urlencoded', - ], - 'body' => \sprintf('xmldata=%s', $encodedRequestData), - ], - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -1153,7 +1098,7 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, ) )) ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); $updatedRequestData['test-update-request-data-with-event'] = true; $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); diff --git a/tests/Unit/Gateways/PosNetV1PosTest.php b/tests/Unit/Gateways/PosNetV1PosTest.php index 6af31e6f..67c0d3d0 100644 --- a/tests/Unit/Gateways/PosNetV1PosTest.php +++ b/tests/Unit/Gateways/PosNetV1PosTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\RequestDataMapperInterface; +use Mews\Pos\DataMapper\RequestValueMapper\PosNetV1PosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\PosNetAccount; @@ -23,7 +25,6 @@ use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\PosNetV1PosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -36,8 +37,6 @@ */ class PosNetV1PosTest extends TestCase { - use HttpClientTestTrait; - private PosNetAccount $account; private array $config; @@ -56,7 +55,10 @@ class PosNetV1PosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -65,6 +67,8 @@ class PosNetV1PosTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private MockObject $eventDispatcherMock; + private PosNetV1PosRequestValueMapper $requestValueMapper; + /** @var SerializerInterface & MockObject */ private MockObject $serializerMock; @@ -76,8 +80,7 @@ protected function setUp(): void 'name' => 'Albaraka', 'class' => PosNetV1Pos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc', - 'gateway_3d' => 'https://epostest.albarakaturk.com.tr/ALBSecurePaymentUI/SecureProcess/SecureVerification.aspx', + 'gateway_3d' => 'https://epostest.albarakaturk.com.tr/ALBSecurePaymentUI/SecureProcess/SecureVerification.aspx', ], ]; @@ -90,11 +93,13 @@ protected function setUp(): void '10,10,10,10,10,10,10,10' ); + $this->requestValueMapper = new PosNetV1PosRequestValueMapper(); $this->requestMapperMock = $this->createMock(RequestDataMapperInterface::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -112,11 +117,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new PosNetV1Pos( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -126,37 +132,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); } - /** - * @dataProvider getApiURLDataProvider - */ - public function testGetApiURL(string $txType, string $mappedTxType, string $expected): void - { - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn($mappedTxType); - - $this->assertSame($expected, $this->pos->getApiURL($txType)); - } - - public function testGetApiURLException(): void - { - $this->requestMapperMock->expects(self::never()) - ->method('mapTxType'); - - $this->expectException(\InvalidArgumentException::class); - $this->pos->getApiURL(); - } - /** * @testWith [true] */ @@ -175,7 +156,7 @@ public function testGet3DFormData( $order, $paymentModel, $txType, - 'https://epostest.albarakaturk.com.tr/ALBSecurePaymentUI/SecureProcess/SecureVerification.aspx', + $this->config['gateway_endpoints']['gateway_3d'], $card ) ->willReturn(['formData']); @@ -238,10 +219,6 @@ public function testMake3DPayment( 'create3DPaymentRequestData', ]; if ($is3DSuccess) { - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn('Sale'); $this->requestMapperMock->expects(self::once()) ->method('create3DPaymentRequestData') ->with($this->account, $order, $txType, $request->request->all()) @@ -249,10 +226,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Sale', $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -269,10 +243,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -322,10 +292,6 @@ public function testMake3DPaymentWithoutHashCheck( 'create3DPaymentRequestData', ]; if ($is3DSuccess) { - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn('Sale'); $this->requestMapperMock->expects(self::once()) ->method('create3DPaymentRequestData') ->with($this->account, $order, $txType, $request->request->all()) @@ -333,10 +299,7 @@ public function testMake3DPaymentWithoutHashCheck( $this->configureClientResponse( $txType, - 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Sale', $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -371,8 +334,8 @@ public function testMake3DPaymentWithoutHashCheck( public function testMake3DPaymentHashMismatchException(): void { $dataSamples = iterator_to_array(PosNetV1PosResponseDataMapperTest::threeDPaymentDataProvider()); - $data = $dataSamples['3d_auth_success_payment_fail']['threeDResponseData']; - $request = Request::create('', 'POST', $data); + $data = $dataSamples['3d_auth_success_payment_fail']['threeDResponseData']; + $request = Request::create('', 'POST', $data); $this->cryptMock->expects(self::once()) ->method('check3DHash') @@ -387,10 +350,6 @@ public function testMake3DPaymentHashMismatchException(): void ->method('map3DPaymentData'); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); @@ -417,17 +376,12 @@ public function testMake3DPayPayment(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $mappedTxType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; $requestData = ['createNonSecurePaymentRequestData']; - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn($mappedTxType); - $this->requestMapperMock->expects(self::once()) ->method('createNonSecurePaymentRequestData') ->with($account, $order, $txType, $card) @@ -436,13 +390,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $map $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -456,17 +409,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $map /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; $requestData = ['createNonSecurePostAuthPaymentRequestData']; - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn('Capture'); - $this->requestMapperMock->expects(self::once()) ->method('createNonSecurePostAuthPaymentRequestData') ->with($account, $order) @@ -475,13 +423,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -496,17 +443,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; $requestData = ['createStatusRequestData']; - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn('TransactionInquiry'); - $this->requestMapperMock->expects(self::once()) ->method('createStatusRequestData') ->with($account, $order) @@ -515,13 +457,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -535,17 +476,12 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; $requestData = ['createCancelRequestData']; - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn('Reverse'); - $this->requestMapperMock->expects(self::once()) ->method('createCancelRequestData') ->with($account, $order) @@ -554,13 +490,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -574,17 +509,12 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; $requestData = ['createRefundRequestData']; - $this->requestMapperMock->expects(self::once()) - ->method('mapTxType') - ->with($txType) - ->willReturn('Return'); - $this->requestMapperMock->expects(self::once()) ->method('createRefundRequestData') ->with($account, $order, $txType) @@ -593,13 +523,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->responseMapperMock->expects(self::once()) @@ -625,7 +554,7 @@ public function testOrderHistoryRequest(): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; @@ -640,51 +569,32 @@ public function testCustomQueryRequest(array $requestData, string $apiUrl, strin $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $this->account ); $this->pos->customQuery($requestData, $apiUrl); } - - public function testCustomQueryRequestWithoutAPIurl(): void - { - $this->expectException(\InvalidArgumentException::class); - - $this->pos->customQuery(['ac' => 'aas']); - } - public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/xxx', - 'expected_api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/xxx', + 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/xxx', + ], + [ + 'requestData' => [ + 'id' => '2020110828BC', + ], + 'api_url' => null, ], - ]; - } - - public static function getApiURLDataProvider(): iterable - { - yield [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'mappedTxType' => 'Sale', - 'expected' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Sale', - ]; - - yield [ - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'mappedTxType' => 'Reverse', - 'expected' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Reverse', ]; } @@ -769,16 +679,12 @@ public static function makeRegularPaymentDataProvider(): array 'id' => '2020110828BC', ], 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'mappedTxType' => 'Sale', - 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Sale', ], [ 'order' => [ 'id' => '2020110828BC', ], 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'mappedTxType' => 'Auth', - 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Auth', ], ]; } @@ -787,10 +693,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Capture', ], ]; } @@ -799,10 +704,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/TransactionInquiry', ], ]; } @@ -811,10 +715,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Reverse', ], ]; } @@ -823,10 +726,9 @@ public static function refundRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Return', ], ]; } @@ -874,38 +776,33 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); - - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'application/json', - ], - 'body' => $encodedRequestData, - ], - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -924,7 +821,7 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, ) )) ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); $updatedRequestData['test-update-request-data-with-event'] = true; $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); diff --git a/tests/Unit/Gateways/ToslaPosTest.php b/tests/Unit/Gateways/ToslaPosTest.php index f2e53c33..8ad68f48 100644 --- a/tests/Unit/Gateways/ToslaPosTest.php +++ b/tests/Unit/Gateways/ToslaPosTest.php @@ -6,9 +6,11 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\ToslaPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueMapper\ToslaPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\ToslaPosAccount; @@ -24,7 +26,6 @@ use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\ToslaPosRequestDataMapperTest; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\ToslaPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use Mews\Pos\Tests\Unit\Serializer\ToslaPosSerializerTest; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -38,8 +39,6 @@ */ class ToslaPosTest extends TestCase { - use HttpClientTestTrait; - public array $config; public CreditCardInterface $card; @@ -58,7 +57,10 @@ class ToslaPosTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -67,6 +69,8 @@ class ToslaPosTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private MockObject $eventDispatcherMock; + private ToslaPosRequestValueMapper $requestValueMapper; + /** @var SerializerInterface & MockObject */ private MockObject $serializerMock; @@ -78,7 +82,6 @@ protected function setUp(): void 'name' => 'AKBANK T.A.S.', 'class' => ToslaPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://ent.akodepos.com/api/Payment', 'gateway_3d' => 'https://ent.akodepos.com/api/Payment/ProcessCardForm', 'gateway_3d_host' => 'https://ent.akodepos.com/api/Payment/threeDSecure', ], @@ -91,11 +94,13 @@ protected function setUp(): void 'POS_ENT_Test_001!*!*', ); + $this->requestValueMapper = new ToslaPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(ToslaPosRequestDataMapper::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); $this->serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -113,11 +118,12 @@ private function createGateway(array $config, ?AbstractPosAccount $account = nul return new ToslaPos( $config, $account ?? $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, $this->serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); } @@ -129,31 +135,12 @@ public function testInit(): void $this->assertFalse($this->pos->isTestMode()); } - /** - * @dataProvider getApiUrlDataProvider - */ - public function testGetApiURL(string $txType, string $paymentModel, string $expected): void - { - $actual = $this->pos->getApiURL($txType, $paymentModel); - - $this->assertSame($expected, $actual); - } - - /** - * @dataProvider getApiUrlExceptionDataProvider - */ - public function testGetApiURLException(?string $txType, ?string $paymentModel, string $exceptionClass): void - { - $this->expectException($exceptionClass); - $this->pos->getApiURL($txType, $paymentModel); - } - public function testGet3DGatewayURL(): void { $actual = $this->pos->get3DGatewayURL(); $this->assertSame( - 'https://ent.akodepos.com/api/Payment/ProcessCardForm', + $this->config['gateway_endpoints']['gateway_3d'], $actual ); } @@ -164,7 +151,7 @@ public function testGet3DHostGatewayURL(): void $actual = $this->pos->get3DGatewayURL(PosInterface::MODEL_3D_HOST, $sessionId); $this->assertSame( - 'https://ent.akodepos.com/api/Payment/threeDSecure/A2A6E942BD2AE4A68BC42FE99D1BC917D67AFF54AB2BA44EBA675843744187708', + $this->config['gateway_endpoints']['gateway_3d_host'] . '/' . $sessionId, $actual ); } @@ -409,13 +396,10 @@ public function testGet3DFormData( $this->configureClientResponse( $txType, - 'https://ent.akodepos.com/api/Payment/threeDPayment', $requestData, - $encodedRequestData, - $responseData, $decodedResponseData, $order, - $paymentModel + $paymentModel, ); $this->requestMapperMock->expects(self::once()) @@ -470,10 +454,7 @@ public function testGet3DFormDataRegisterPaymentFail(array $response): void $this->configureClientResponse( $txType, - 'https://ent.akodepos.com/api/Payment/threeDPayment', $requestData, - 'encoded-request', - 'response-body', $response, $order, PosInterface::MODEL_3D_PAY @@ -513,13 +494,12 @@ public function testStatus( $this->configureClientResponse( $txType, - 'https://ent.akodepos.com/api/Payment/inquiry', $requestData, - $encodedRequest, - $responseContent, $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->pos->status($order); @@ -554,13 +534,12 @@ public function testCancel( $this->configureClientResponse( PosInterface::TX_TYPE_CANCEL, - 'https://ent.akodepos.com/api/Payment/void', $requestData, - $encodedRequest, - $responseContent, $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->pos->cancel($order); @@ -595,13 +574,12 @@ public function testRefund( $this->configureClientResponse( PosInterface::TX_TYPE_REFUND, - 'https://ent.akodepos.com/api/Payment/refund', $requestData, - $encodedRequest, - $responseContent, $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->pos->refund($order); @@ -644,13 +622,12 @@ public function testOrderHistory( $this->configureClientResponse( $txType, - 'https://ent.akodepos.com/api/Payment/history', $requestData, - $encodedRequest, - $responseContent, $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $this->account ); $this->pos->orderHistory($order); @@ -663,7 +640,7 @@ public function testOrderHistory( /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; @@ -678,35 +655,31 @@ public function testCustomQueryRequest(array $requestData, string $apiUrl, strin $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $account ); $this->pos->customQuery($requestData, $apiUrl); } - - public function testCustomQueryRequestWithoutAPIurl(): void - { - $this->expectException(\InvalidArgumentException::class); - - $this->pos->customQuery(['ac' => 'aas']); - } - public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ + 'id' => '2020110828BC', + ], + 'api_url' => 'https://prepentegrasyon.tosla.com/api/Payment/GetCommissionAndInstallmentInfo', + ], + [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://prepentegrasyon.tosla.com/api/Payment/GetCommissionAndInstallmentInfo', - 'expected_api_url' => 'https://prepentegrasyon.tosla.com/api/Payment/GetCommissionAndInstallmentInfo', + 'api_url' => null, ], ]; } @@ -846,7 +819,7 @@ public static function make3DPayPaymentWithoutHashCheckDataProvider(): array /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -860,13 +833,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -880,7 +852,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -894,13 +866,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -915,7 +886,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -929,13 +900,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -949,7 +919,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -963,13 +933,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -983,7 +952,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $apiUrl): void + public function testRefundRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; @@ -997,13 +966,12 @@ public function testRefundRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -1014,109 +982,14 @@ public function testRefundRequest(array $order, string $apiUrl): void $this->pos->refund($order); } - - public static function getApiUrlDataProvider(): array - { - return [ - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_PAY, - 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPayment', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_PAY, - 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPreAuth', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_HOST, - 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPayment', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_HOST, - 'expected' => 'https://ent.akodepos.com/api/Payment/threeDPreAuth', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://ent.akodepos.com/api/Payment/Payment', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_POST_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://ent.akodepos.com/api/Payment/postAuth', - ], - [ - 'txType' => PosInterface::TX_TYPE_STATUS, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://ent.akodepos.com/api/Payment/inquiry', - ], - [ - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://ent.akodepos.com/api/Payment/void', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://ent.akodepos.com/api/Payment/refund', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://ent.akodepos.com/api/Payment/refund', - ], - [ - 'txType' => PosInterface::TX_TYPE_ORDER_HISTORY, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://ent.akodepos.com/api/Payment/history', - ], - ]; - } - - public static function getApiUrlExceptionDataProvider(): array - { - return [ - [ - 'txType' => PosInterface::TX_TYPE_HISTORY, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'exception_class' => UnsupportedTransactionTypeException::class, - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_SECURE, - 'exception_class' => UnsupportedTransactionTypeException::class, - ], - [ - 'txType' => null, - 'paymentModel' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - [ - 'txType' => null, - 'paymentModel' => PosInterface::MODEL_3D_PAY, - 'exception_class' => \InvalidArgumentException::class, - ], - ]; - } - - public static function makeRegularPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://ent.akodepos.com/api/Payment/Payment', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, ], ]; } @@ -1125,10 +998,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://ent.akodepos.com/api/Payment/postAuth', ], ]; } @@ -1137,10 +1009,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://ent.akodepos.com/api/Payment/inquiry', ], ]; } @@ -1149,10 +1020,9 @@ public static function cancelRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://ent.akodepos.com/api/Payment/void', ], ]; } @@ -1161,10 +1031,9 @@ public static function refundRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://ent.akodepos.com/api/Payment/refund', ], ]; } @@ -1226,38 +1095,33 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + array $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); - - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($txType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'headers' => [ - 'Content-Type' => 'application/json', - ], - 'body' => $encodedRequestData, - ], - ); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') @@ -1276,7 +1140,7 @@ function (RequestDataPreparedEvent $dispatchedEvent) use ($requestData, $txType, ) )) ->willReturnCallback(function () use (&$updatedRequestDataPreparedEvent): ?\Mews\Pos\Event\RequestDataPreparedEvent { - $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); + $updatedRequestData = $updatedRequestDataPreparedEvent->getRequestData(); $updatedRequestData['test-update-request-data-with-event'] = true; $updatedRequestDataPreparedEvent->setRequestData($updatedRequestData); diff --git a/tests/Unit/Gateways/VakifKatilimTest.php b/tests/Unit/Gateways/VakifKatilimTest.php index 73710218..af556940 100644 --- a/tests/Unit/Gateways/VakifKatilimTest.php +++ b/tests/Unit/Gateways/VakifKatilimTest.php @@ -6,22 +6,23 @@ namespace Mews\Pos\Tests\Unit\Gateways; -use Mews\Pos\Client\HttpClient; +use Mews\Pos\Client\HttpClientInterface; +use Mews\Pos\Client\HttpClientStrategyInterface; use Mews\Pos\Crypt\CryptInterface; use Mews\Pos\DataMapper\RequestDataMapper\VakifKatilimPosRequestDataMapper; +use Mews\Pos\DataMapper\RequestValueMapper\VakifKatilimPosRequestValueMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\Entity\Account\AbstractPosAccount; use Mews\Pos\Entity\Account\KuveytPosAccount; use Mews\Pos\Entity\Card\CreditCardInterface; use Mews\Pos\Event\RequestDataPreparedEvent; use Mews\Pos\Exceptions\UnsupportedPaymentModelException; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Factory\AccountFactory; use Mews\Pos\Factory\CreditCardFactory; use Mews\Pos\Gateways\VakifKatilimPos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper\VakifKatilimPosResponseDataMapperTest; -use Mews\Pos\Tests\Unit\HttpClientTestTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\EventDispatcher\EventDispatcherInterface; @@ -34,8 +35,6 @@ */ class VakifKatilimTest extends TestCase { - use HttpClientTestTrait; - private KuveytPosAccount $account; private array $config; @@ -56,7 +55,10 @@ class VakifKatilimTest extends TestCase /** @var CryptInterface & MockObject */ private MockObject $cryptMock; - /** @var HttpClient & MockObject */ + /** @var HttpClientStrategyInterface & MockObject */ + private MockObject $httpClientStrategyMock; + + /** @var HttpClientInterface & MockObject */ private MockObject $httpClientMock; /** @var LoggerInterface & MockObject */ @@ -65,8 +67,7 @@ class VakifKatilimTest extends TestCase /** @var EventDispatcherInterface & MockObject */ private MockObject $eventDispatcherMock; - /** @var SerializerInterface & MockObject */ - private MockObject $serializerMock; + private VakifKatilimPosRequestValueMapper $requestValueMapper; /** * @return void @@ -81,8 +82,7 @@ protected function setUp(): void 'name' => 'Vakıf Katılım', 'class' => VakifKatilimPos::class, 'gateway_endpoints' => [ - 'payment_api' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home', - 'gateway_3d' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', + 'gateway_3d' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', ], ]; @@ -103,11 +103,13 @@ protected function setUp(): void 'fail_url' => 'http://localhost/finansbank-payfor/3d/response.php', ]; + $this->requestValueMapper = new VakifKatilimPosRequestValueMapper(); $this->requestMapperMock = $this->createMock(VakifKatilimPosRequestDataMapper::class); $this->responseMapperMock = $this->createMock(ResponseDataMapperInterface::class); - $this->serializerMock = $this->createMock(SerializerInterface::class); + $serializerMock = $this->createMock(SerializerInterface::class); $this->cryptMock = $this->createMock(CryptInterface::class); - $this->httpClientMock = $this->createMock(HttpClient::class); + $this->httpClientStrategyMock = $this->createMock(HttpClientStrategyInterface::class); + $this->httpClientMock = $this->createMock(HttpClientInterface::class); $this->loggerMock = $this->createMock(LoggerInterface::class); $this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class); @@ -118,11 +120,12 @@ protected function setUp(): void $this->pos = new VakifKatilimPos( $this->config, $this->account, + $this->requestValueMapper, $this->requestMapperMock, $this->responseMapperMock, - $this->serializerMock, + $serializerMock, $this->eventDispatcherMock, - $this->httpClientMock, + $this->httpClientStrategyMock, $this->loggerMock, ); @@ -142,56 +145,33 @@ protected function setUp(): void */ public function testInit(): void { - $this->requestMapperMock->expects(self::once()) - ->method('getCurrencyMappings') - ->willReturn([PosInterface::CURRENCY_TRY => '0949']); - $this->assertSame([PosInterface::CURRENCY_TRY], $this->pos->getCurrencies()); + $this->assertCount(count($this->requestValueMapper->getCurrencyMappings()), $this->pos->getCurrencies()); $this->assertSame($this->config, $this->pos->getConfig()); $this->assertSame($this->account, $this->pos->getAccount()); $this->assertFalse($this->pos->isTestMode()); } - /** - * @dataProvider getApiUrlDataProvider - */ - public function testGetApiURL(string $txType, ?string $orderTxType, string $paymentModel, string $expected): void - { - $actual = $this->pos->getApiURL($txType, $paymentModel, $orderTxType); - - $this->assertSame($expected, $actual); - } - - /** - * @dataProvider getApiUrlExceptionDataProvider - */ - public function testGetApiURLException(?string $txType, ?string $paymentModel, ?string $orderTxType, string $exceptionClass): void - { - $this->expectException($exceptionClass); - - $this->pos->getApiURL($txType, $paymentModel, $orderTxType); - } - /** * @return void */ - public function testGetCommon3DFormDataSuccessResponse(): void + public function testGet3DFormDataSuccessResponse(): void { + $response = 'bank-api-html-response'; $txType = PosInterface::TX_TYPE_PAY_AUTH; $paymentModel = PosInterface::MODEL_3D_SECURE; $card = $this->card; $requestData = ['form-data']; $order = $this->order; - $decodedResponse = ['form_inputs' => ['form-inputs'], 'gateway' => 'form-action-url']; $this->configureClientResponse( $txType, - 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', $requestData, - 'request-body', - 'bank-api-html-response', - $decodedResponse, + $response, $order, - $paymentModel + $paymentModel, + null, + null, + PosInterface::TX_TYPE_INTERNAL_3D_FORM_BUILD, ); $this->requestMapperMock->expects(self::once()) @@ -205,20 +185,12 @@ public function testGetCommon3DFormDataSuccessResponse(): void ) ->willReturn($requestData); - $this->requestMapperMock->expects(self::once()) - ->method('create3DFormData') - ->with( - $this->pos->getAccount(), - ['form-inputs'], - $paymentModel, - $txType, - 'form-action-url', - $card - ) - ->willReturn(['3d-form-data']); + $this->requestMapperMock->expects(self::never()) + ->method('create3DFormData'); + $result = $this->pos->get3DFormData($order, $paymentModel, $txType, $card); - $this->assertSame(['3d-form-data'], $result); + $this->assertSame($response, $result); } /** @@ -237,7 +209,7 @@ public function testGet3DHostFormData(): void $order, $paymentModel, $txType, - 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelPayGate', + $this->config['gateway_endpoints']['gateway_3d'], ) ->willReturn(['formData']); @@ -300,10 +272,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelProvisionGate', $create3DPaymentRequestData, - 'request-body', - 'response-body', $paymentResponse, $order, PosInterface::MODEL_3D_SECURE @@ -320,10 +289,6 @@ public function testMake3DPayment( ->willReturn($expectedResponse); $this->requestMapperMock->expects(self::never()) ->method('create3DPaymentRequestData'); - $this->serializerMock->expects(self::never()) - ->method('encode'); - $this->serializerMock->expects(self::never()) - ->method('decode'); $this->eventDispatcherMock->expects(self::never()) ->method('dispatch'); } @@ -370,7 +335,7 @@ public function testMake3DPayPayment(): void /** * @dataProvider makeRegularPaymentDataProvider */ - public function testMakeRegularPayment(array $order, string $txType, string $apiUrl): void + public function testMakeRegularPayment(array $order, string $txType): void { $account = $this->pos->getAccount(); $card = $this->card; @@ -383,13 +348,12 @@ public function testMakeRegularPayment(array $order, string $txType, string $api $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -403,7 +367,7 @@ public function testMakeRegularPayment(array $order, string $txType, string $api /** * @dataProvider makeRegularPostAuthPaymentDataProvider */ - public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): void + public function testMakeRegularPostAuthPayment(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; @@ -417,13 +381,12 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -438,7 +401,7 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo /** * @dataProvider statusRequestDataProvider */ - public function testStatusRequest(array $order, string $apiUrl): void + public function testStatusRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_STATUS; @@ -452,13 +415,12 @@ public function testStatusRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -472,7 +434,7 @@ public function testStatusRequest(array $order, string $apiUrl): void /** * @dataProvider cancelRequestDataProvider */ - public function testCancelRequest(array $order, string $apiUrl): void + public function testCancelRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CANCEL; @@ -486,13 +448,12 @@ public function testCancelRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -506,7 +467,7 @@ public function testCancelRequest(array $order, string $apiUrl): void /** * @dataProvider refundRequestDataProvider */ - public function testRefundRequest(array $order, string $txType, string $apiUrl): void + public function testRefundRequest(array $order, string $txType): void { $account = $this->pos->getAccount(); $requestData = ['createRefundRequestData']; @@ -519,13 +480,12 @@ public function testRefundRequest(array $order, string $txType, string $apiUrl): $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -540,7 +500,7 @@ public function testRefundRequest(array $order, string $txType, string $apiUrl): /** * @dataProvider historyRequestDataProvider */ - public function testHistoryRequest(array $order, string $apiUrl): void + public function testHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_HISTORY; @@ -554,13 +514,12 @@ public function testHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -574,7 +533,7 @@ public function testHistoryRequest(array $order, string $apiUrl): void /** * @dataProvider orderHistoryRequestDataProvider */ - public function testOrderHistoryRequest(array $order, string $apiUrl): void + public function testOrderHistoryRequest(array $order): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_ORDER_HISTORY; @@ -588,13 +547,12 @@ public function testOrderHistoryRequest(array $order, string $apiUrl): void $decodedResponse = ['decodedData']; $this->configureClientResponse( $txType, - $apiUrl, $requestData, - 'request-body', - 'response-body', $decodedResponse, $order, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + null, + $account ); $this->responseMapperMock->expects(self::once()) @@ -608,7 +566,7 @@ public function testOrderHistoryRequest(array $order, string $apiUrl): void /** * @dataProvider customQueryRequestDataProvider */ - public function testCustomQueryRequest(array $requestData, string $apiUrl, string $expectedApiUrl): void + public function testCustomQueryRequest(array $requestData, ?string $apiUrl): void { $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_CUSTOM_QUERY; @@ -623,13 +581,12 @@ public function testCustomQueryRequest(array $requestData, string $apiUrl, strin $this->configureClientResponse( $txType, - $expectedApiUrl, $updatedRequestData, - 'request-body', - 'response-body', ['decodedResponse'], $requestData, - PosInterface::MODEL_NON_SECURE + PosInterface::MODEL_NON_SECURE, + $apiUrl, + $account ); $this->pos->customQuery($requestData, $apiUrl); @@ -647,11 +604,10 @@ public static function customQueryRequestDataProvider(): array { return [ [ - 'requestData' => [ + 'requestData' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/MailOrderSale', - 'expected_api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/MailOrderSale', + 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/MailOrderSale', ], ]; } @@ -688,120 +644,6 @@ public static function make3DPaymentDataProvider(): array ]; } - public static function getApiUrlDataProvider(): array - { - return [ - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'orderTxType' => null, - 'paymentModel' => PosInterface::MODEL_3D_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/ThreeDModelProvisionGate', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'orderTxType' => null, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizaten', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'orderTxType' => null, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/Non3DPayGate', - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_POST_AUTH, - 'orderTxType' => null, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizatenClose', - ], - [ - 'txType' => PosInterface::TX_TYPE_STATUS, - 'orderTxType' => null, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SelectOrderByMerchantOrderId', - ], - [ - 'txType' => PosInterface::TX_TYPE_ORDER_HISTORY, - 'orderTxType' => null, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SelectOrder', - ], - [ - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'orderTxType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SaleReversal', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND, - 'orderTxType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/DrawBack', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'orderTxType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PartialDrawBack', - ], - [ - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'orderTxType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizationReversal', - ], - [ - 'txType' => PosInterface::TX_TYPE_REFUND, - 'orderTxType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'expected' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizationDrawBack', - ], - ]; - } - - public static function getApiUrlExceptionDataProvider(): array - { - return [ - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => PosInterface::MODEL_3D_PAY, - 'orderTxType' => null, - 'exception_class' => UnsupportedTransactionTypeException::class, - ], - [ - 'txType' => null, - 'paymentModel' => null, - 'orderTxType' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - [ - 'txType' => PosInterface::TX_TYPE_CUSTOM_QUERY, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'orderTxType' => null, - 'exception_class' => UnsupportedTransactionTypeException::class, - ], - [ - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'paymentModel' => null, - 'orderTxType' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - [ - 'txType' => null, - 'paymentModel' => PosInterface::MODEL_3D_PAY, - 'orderTxType' => null, - 'exception_class' => \InvalidArgumentException::class, - ], - [ - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'paymentModel' => PosInterface::MODEL_NON_SECURE, - 'orderTxType' => PosInterface::TX_TYPE_PAY_POST_AUTH, - 'exception_class' => UnsupportedTransactionTypeException::class, - ], - ]; - } - public static function makeRegularPaymentDataProvider(): array { return [ @@ -810,14 +652,12 @@ public static function makeRegularPaymentDataProvider(): array 'id' => '2020110828BC', ], 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/Non3DPayGate', ], [ 'order' => [ 'id' => '2020110828BC', ], 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizaten', ], ]; } @@ -826,10 +666,9 @@ public static function makeRegularPostAuthPaymentDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizatenClose', ], ]; } @@ -838,10 +677,9 @@ public static function statusRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SelectOrderByMerchantOrderId', ], ]; } @@ -850,18 +688,16 @@ public static function cancelRequestDataProvider(): array { return [ 'pay_order' => [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', 'transaction_type' => PosInterface::TX_TYPE_PAY_AUTH, ], - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SaleReversal', ], 'pay_auth_order' => [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', 'transaction_type' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizationReversal', ], ]; } @@ -870,30 +706,27 @@ public static function refundRequestDataProvider(): array { return [ 'pay_order' => [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', 'transaction_type' => PosInterface::TX_TYPE_PAY_AUTH, ], - 'txType' => PosInterface::TX_TYPE_REFUND, - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/DrawBack', + 'txType' => PosInterface::TX_TYPE_REFUND, ], 'pay_auth_order' => [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', 'transaction_type' => PosInterface::TX_TYPE_PAY_PRE_AUTH, ], - 'txType' => PosInterface::TX_TYPE_REFUND, - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PreAuthorizationDrawBack', + 'txType' => PosInterface::TX_TYPE_REFUND, ], 'pay_order_partial_refund' => [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', 'order_amount' => 10, 'amount' => 5, 'transaction_type' => PosInterface::TX_TYPE_PAY_AUTH, ], - 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/PartialDrawBack', + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, ], ]; } @@ -902,10 +735,9 @@ public static function historyRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SelectOrder', ], ]; } @@ -914,10 +746,9 @@ public static function orderHistoryRequestDataProvider(): array { return [ [ - 'order' => [ + 'order' => [ 'id' => '2020110828BC', ], - 'api_url' => 'https://boa.vakifkatilim.com.tr/VirtualPOS.Gateway/Home/SelectOrder', ], ]; } @@ -983,38 +814,36 @@ public static function threeDFormDataBadInputsProvider(): array } private function configureClientResponse( - string $txType, - string $apiUrl, - array $requestData, - string $encodedRequestData, - string $responseContent, - array $decodedResponse, - array $order, - string $paymentModel + string $txType, + array $requestData, + $decodedResponse, + array $order, + string $paymentModel, + ?string $apiUrl = null, + ?AbstractPosAccount $account = null, + ?string $clientTxType = null ): void { $updatedRequestDataPreparedEvent = null; - $this->serializerMock->expects(self::once()) - ->method('encode') - ->with($this->logicalAnd($this->arrayHasKey('test-update-request-data-with-event')), $txType) - ->willReturn($encodedRequestData); + $clientTxType ??= $txType; + $this->httpClientStrategyMock->expects(self::once()) + ->method('getClient') + ->with($clientTxType, $paymentModel) + ->willReturn($this->httpClientMock); - $this->serializerMock->expects(self::once()) - ->method('decode') - ->with($responseContent, $txType) - ->willReturn($decodedResponse); + $this->httpClientMock->expects(self::once()) + ->method('request') + ->with( + $txType, + $paymentModel, + $this->callback(function (array $requestData) { + return $requestData['test-update-request-data-with-event'] === true; + }), + $order, + $apiUrl, + $account + )->willReturn($decodedResponse); - $this->prepareClient( - $this->httpClientMock, - $responseContent, - $apiUrl, - [ - 'body' => $encodedRequestData, - 'headers' => [ - 'Content-Type' => 'text/xml; charset=UTF-8', - ], - ], - ); $this->eventDispatcherMock->expects(self::once()) ->method('dispatch') diff --git a/tests/Unit/HttpClientTestTrait.php b/tests/Unit/HttpClientTestTrait.php deleted file mode 100644 index da0eef42..00000000 --- a/tests/Unit/HttpClientTestTrait.php +++ /dev/null @@ -1,78 +0,0 @@ -prepareHttpResponse($responseContent, $statusCode); - - $httpClient->expects(self::once()) - ->method('post') - ->with($apiUrl, $requestData) - ->willReturn($responseMock); - } - - /** - * @param HttpClient|MockObject $httpClient - */ - private function prepareHttpClientRequestMulti( - HttpClient $httpClient, - array $responseContents, - array $apiUrls, - array $requestData - ): void { - $returnMap = []; - - foreach ($responseContents as $index => $item) { - $returnMap[] = [ - $apiUrls[$index], - $requestData[$index], - $this->prepareHttpResponse($item), - ]; - } - - $httpClient->expects(self::exactly(\count($returnMap))) - ->method('post') - ->willReturnMap($returnMap); - } - - private function prepareHttpResponse(string $responseContent, ?int $statusCode = null): ResponseInterface - { - $responseMock = $this->createMock(ResponseInterface::class); - $streamMock = $this->createMock(StreamInterface::class); - - $streamMock->expects(self::once()) - ->method('getContents') - ->willReturn($responseContent); - $responseMock->expects(self::once()) - ->method('getBody') - ->willReturn($streamMock); - - if (null !== $statusCode) { - $responseMock->expects(self::atLeastOnce()) - ->method('getStatusCode') - ->willReturn($statusCode); - } - - return $responseMock; - } -} diff --git a/tests/Unit/Serializer/AkbankPosSerializerTest.php b/tests/Unit/Serializer/AkbankPosSerializerTest.php index ef30ca37..528cb6bf 100644 --- a/tests/Unit/Serializer/AkbankPosSerializerTest.php +++ b/tests/Unit/Serializer/AkbankPosSerializerTest.php @@ -10,6 +10,7 @@ use Mews\Pos\Gateways\AkbankPos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\AkbankPosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -28,21 +29,33 @@ protected function setUp(): void public function testSupports(): void { - $supports = $this->serializer::supports(AkbankPos::class); + $this->assertTrue(AkbankPosSerializer::supports(AkbankPos::class)); + $this->assertTrue(AkbankPosSerializer::supports(AkbankPos::class, 'payment_api')); + $this->assertFalse(AkbankPosSerializer::supports(AkbankPos::class, 'query_api')); + $this->assertFalse(AkbankPosSerializer::supports(\Mews\Pos\Gateways\EstPos::class)); + } - $this->assertTrue($supports); + public function testDecodeEmpty(): void + { + $this->assertSame([], $this->serializer->decode('')); + } + + public function testDecodeWithInvalidBase64HistoryData(): void + { + $input = '{"data": "INVALID_BASE64_!!!!"}'; + $this->assertSame(['data' => null], $this->serializer->decode($input, PosInterface::TX_TYPE_HISTORY)); } /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, string $expected): void { - $result = $this->serializer->encode($data); - $expected = str_replace(["\r"], '', $expected); + $result = $this->serializer->encode($data, null, $format); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -89,8 +102,17 @@ public function testInvalidHistoryData(): void public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => ['abc' => 1], - 'expected' => '{"abc":1}', + 'input' => ['abc' => 1], + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_JSON, + 'expected' => '{"abc":1}', + ]; + + yield 'test2' => [ + 'input' => ['abc' => 1], + 'format' => SerializerInterface::FORMAT_JSON, + 'expected_format' => SerializerInterface::FORMAT_JSON, + 'expected' => '{"abc":1}', ]; } diff --git a/tests/Unit/Serializer/EncodedDataTest.php b/tests/Unit/Serializer/EncodedDataTest.php new file mode 100644 index 00000000..10ff84f2 --- /dev/null +++ b/tests/Unit/Serializer/EncodedDataTest.php @@ -0,0 +1,25 @@ +assertSame('abc', $object->getData()); + $this->assertSame(SerializerInterface::FORMAT_FORM, $object->getFormat()); + } +} diff --git a/tests/Unit/Serializer/EstPosSerializerTest.php b/tests/Unit/Serializer/EstPosSerializerTest.php index 8a1baadd..4d4e5fe3 100644 --- a/tests/Unit/Serializer/EstPosSerializerTest.php +++ b/tests/Unit/Serializer/EstPosSerializerTest.php @@ -11,6 +11,7 @@ use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\EstPosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -42,12 +43,13 @@ public function testSupports(): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, string $expected): void { - $result = $this->serializer->encode($data); + $result = $this->serializer->encode($data, null, $format); $expected = str_replace(["\r"], '', $expected); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } @@ -81,6 +83,33 @@ public static function encodeDataProvider(): Generator 'Cvv2Val' => '122', 'Mode' => 'P', ], + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +ISBANKAPIISBANK07700655000200Authtest@test.comorder222100.25949555544443333222212/21122P +', + ]; + + yield 'test2' => [ + 'input' => [ + 'Name' => 'ISBANKAPI', + 'Password' => 'ISBANK07', + 'ClientId' => '700655000200', + 'Type' => 'Auth', + 'IPAddress' => '', + 'Email' => 'test@test.com', + 'OrderId' => 'order222', + 'UserId' => '', + 'Total' => '100.25', + 'Currency' => '949', + 'Taksit' => '', + 'Number' => '5555444433332222', + 'Expires' => '12/21', + 'Cvv2Val' => '122', + 'Mode' => 'P', + ], + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, 'expected' => ' ISBANKAPIISBANK07700655000200Authtest@test.comorder222100.25949555544443333222212/21122P ', diff --git a/tests/Unit/Serializer/GarantiPosSerializerTest.php b/tests/Unit/Serializer/GarantiPosSerializerTest.php index 4f453cd9..12ee51de 100644 --- a/tests/Unit/Serializer/GarantiPosSerializerTest.php +++ b/tests/Unit/Serializer/GarantiPosSerializerTest.php @@ -10,6 +10,7 @@ use Mews\Pos\Gateways\GarantiPos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\GarantiPosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -36,12 +37,13 @@ public function testSupports(): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, string $expected): void { - $result = $this->serializer->encode($data); + $result = $this->serializer->encode($data, null, $format); $expected = str_replace(["\r"], '', $expected); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -57,7 +59,7 @@ public function testDecode(string $input, string $txType, array $expected): void public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => [ + 'input' => [ 'Mode' => 'TEST', 'Version' => 'v0.01', 'Terminal' => [ @@ -77,7 +79,7 @@ public static function encodeDataProvider(): Generator 'CVV2' => '122', ], 'Order' => [ - 'OrderID' => 'order222', + 'OrderID' => 'order222', ], 'Transaction' => [ 'Type' => 'sales', @@ -88,7 +90,48 @@ public static function encodeDataProvider(): Generator 'MotoInd' => 'N', ], ], - 'expected' => ' + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +TESTv0.01PROVAUTPROVAUT3732634F78053D42304B0966E263629FE44E258B306912987000679test@test.com55554444333322221221122order222sales100259490N +', + ]; + + yield 'test2' => [ + 'input' => [ + 'Mode' => 'TEST', + 'Version' => 'v0.01', + 'Terminal' => [ + 'ProvUserID' => 'PROVAUT', + 'UserID' => 'PROVAUT', + 'HashData' => '3732634F78053D42304B0966E263629FE44E258B', + 'ID' => '30691298', + 'MerchantID' => '7000679', + ], + 'Customer' => [ + 'IPAddress' => '', + 'EmailAddress' => 'test@test.com', + ], + 'Card' => [ + 'Number' => '5555444433332222', + 'ExpireDate' => '1221', + 'CVV2' => '122', + ], + 'Order' => [ + 'OrderID' => 'order222', + ], + 'Transaction' => [ + 'Type' => 'sales', + 'InstallmentCnt' => '', + 'Amount' => 10025, + 'CurrencyCode' => '949', + 'CardholderPresentCode' => '0', + 'MotoInd' => 'N', + ], + ], + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' TESTv0.01PROVAUTPROVAUT3732634F78053D42304B0966E263629FE44E258B306912987000679test@test.com55554444333322221221122order222sales100259490N ', ]; diff --git a/tests/Unit/Serializer/InterPosSerializerTest.php b/tests/Unit/Serializer/InterPosSerializerTest.php index 715a88e6..16aad3f1 100644 --- a/tests/Unit/Serializer/InterPosSerializerTest.php +++ b/tests/Unit/Serializer/InterPosSerializerTest.php @@ -6,8 +6,10 @@ namespace Mews\Pos\Tests\Unit\Serializer; +use Generator; use Mews\Pos\Gateways\InterPos; use Mews\Pos\Serializer\InterPosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -26,20 +28,20 @@ protected function setUp(): void public function testSupports(): void { - $supports = $this->serializer::supports(InterPos::class); - - $this->assertTrue($supports); + $this->assertTrue(InterPosSerializer::supports(InterPos::class)); + $this->assertTrue(InterPosSerializer::supports(InterPos::class, 'payment_api')); + $this->assertFalse(InterPosSerializer::supports(\Mews\Pos\Gateways\AkbankPos::class)); } - public function testEncode(): void + /** + * @dataProvider encodeDataProvider + */ + public function testEncode(array $data, ?string $format, string $expectedFormat, string $expected): void { - $data = [ - 'abc' => '1', - 'sa' => 'aa', - ]; - $result = $this->serializer->encode($data); + $result = $this->serializer->encode($data, null, $format); - $this->assertSame('abc=1&sa=aa', $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -52,6 +54,29 @@ public function testDecode(string $input, array $expected): void $this->assertSame($expected, $result); } + public static function encodeDataProvider(): Generator + { + yield 'test1' => [ + 'input' => [ + 'abc' => '1', + 'sa' => 'aa', + ], + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_FORM, + 'expected' => 'abc=1&sa=aa', + ]; + + yield 'test2' => [ + 'input' => [ + 'abc' => '1', + 'sa' => 'aa', + ], + 'format' => SerializerInterface::FORMAT_FORM, + 'expected_format' => SerializerInterface::FORMAT_FORM, + 'expected' => 'abc=1&sa=aa', + ]; + } + public static function decodeDataProvider(): array { return [ diff --git a/tests/Unit/Serializer/KuveytPosSerializerTest.php b/tests/Unit/Serializer/KuveytPosSerializerTest.php index c3440ebc..30ab505f 100644 --- a/tests/Unit/Serializer/KuveytPosSerializerTest.php +++ b/tests/Unit/Serializer/KuveytPosSerializerTest.php @@ -7,12 +7,12 @@ namespace Mews\Pos\Tests\Unit\Serializer; use Generator; -use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Gateways\KuveytPos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\KuveytPosSerializer; -use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\KuveytPosRequestDataMapperTest; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; +use Symfony\Component\Serializer\Exception\NotEncodableValueException; /** * @covers \Mews\Pos\Serializer\KuveytPosSerializer @@ -38,43 +38,15 @@ public function testSupports(): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $txType, $expected): void + public function testEncode(array $data, string $txType, ?string $format, string $expectedFormat, $expected): void { - $result = $this->serializer->encode($data, $txType); + $result = $this->serializer->encode($data, $txType, $format); if (is_string($expected)) { $expected = str_replace(["\r"], '', $expected); } - $this->assertSame($expected, $result); - } - - public function testEncodeException(): void - { - $this->expectException(UnsupportedTransactionTypeException::class); - $this->serializer->encode(['abc' => 1], PosInterface::TX_TYPE_HISTORY); - - $this->expectException(UnsupportedTransactionTypeException::class); - $this->serializer->encode(['abc' => 1], PosInterface::TX_TYPE_ORDER_HISTORY); - } - - /** - * @dataProvider decodeHtmlDataProvider - */ - public function testDecodeHtml(string $input, array $expected): void - { - $actual = $this->serializer->decode($input, PosInterface::TX_TYPE_PAY_AUTH); - - $this->assertSame($expected, $actual); - } - - /** - * @dataProvider decodeJsonDataProvider - */ - public function testDecodeJson(string $input, string $txType, array $expected): void - { - $actual = $this->serializer->decode($input, $txType); - - $this->assertSame($expected, $actual); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -99,120 +71,24 @@ public function testDecodeException(string $input, string $txType, string $excep public static function encodeDataProvider(): Generator { - $refundTests = iterator_to_array(KuveytPosRequestDataMapperTest::createRefundRequestDataProvider()); - yield 'test_refund' => [ - 'input' => $refundTests[0]['expected'], - 'txType' => PosInterface::TX_TYPE_REFUND, - 'expected' => '10000400235110180114293600318923298433298433241839TDV2.0.00request-hash800400235apiuserVisa0DrawBack010101012023070849CD0094900001', - ]; - - yield 'test_partial_refund' => [ - 'input' => $refundTests[1]['expected'], - 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, - 'expected' => '10000400235190180114293600318923298433298433241839TDV2.0.00request-hash800400235apiuserVisa0PartialDrawback090109012023070849CD0094900001', - ]; - - yield 'test_cancel' => [ - 'input' => ['abc' => 1, 'abc2' => ['abc3' => '3']], - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'expected' => '13', - ]; - - yield 'test_status' => [ - 'input' => ['abc' => 1, 'abc2' => ['abc3' => '3']], - 'txType' => PosInterface::TX_TYPE_STATUS, - 'expected' => '13', - ]; - yield 'test_pay' => [ - 'input' => ['abc' => 1, 'abc2' => ['abc3' => '3']], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'expected' => ' -13 + 'input' => ['abc' => 1], + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +1 ', ]; - } - - public static function decodeHtmlDataProvider(): array - { - $htmlWithCustomHtmlElement = << - - - - - - - - - -
- - -
- - - -HTML; - - return [ - [ - 'html' => '
', - 'expected' => [ - 'gateway' => 'https://boa.kuveytturk.com.tr/sanalposservice/Home/ThreeDModelPayGate', - 'form_inputs' => [ - 'AuthenticationResponse' => '%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3CVPosTransactionResponseContract%3E%3CVPosMessage%3E%3CAPIVersion%3E1.0.0%3C%2FAPIVersion%3E%3COkUrl%3Ehttp%3A%2F%2Flocalhost%3A44785%2FHome%2FSuccess%3C%2FOkUrl%3E%3CFailUrl%3Ehttp%3A%2F%2Flocalhost%3A44785%2FHome%2FFail%3C%2FFailUrl%3E%3CHashData%3ElYJYMi%2FgVO9MWr32Pshaa%2FzAbSHY%3D%3C%2FHashData%3E%3CMerchantId%3E80%3C%2FMerchantId%3E%3CSubMerchantId%3E0%3C%2FSubMerchantId%3E%3CCustomerId%3E400235%3C%2FCustomerId%3E%3CUserName%3Eapiuser%3C%2FUserName%3E%3CCardNumber%3E4025502306586032%3C%2FCardNumber%3E%3CCardHolderName%3Eafafa%3C%2FCardHolderName%3E%3CCardType%3EMasterCard%3C%2FCardType%3E%3CBatchID%3E0%3C%2FBatchID%3E%3CTransactionType%3ESale%3C%2FTransactionType%3E%3CInstallmentCount%3E0%3C%2FInstallmentCount%3E%3CAmount%3E100%3C%2FAmount%3E%3CDisplayAmount%3E100%3C%2FDisplayAmount%3E%3CMerchantOrderId%3EOrder+123%3C%2FMerchantOrderId%3E%3CFECAmount%3E0%3C%2FFECAmount%3E%3CCurrencyCode%3E0949%3C%2FCurrencyCode%3E%3CQeryId%3E0%3C%2FQeryId%3E%3CDebtId%3E0%3C%2FDebtId%3E%3CSurchargeAmount%3E0%3C%2FSurchargeAmount%3E%3CSGKDebtAmount%3E0%3C%2FSGKDebtAmount%3E%3CTransactionSecurity%3E3%3C%2FTransactionSecurity%3E%3CTransactionSide%3EAuto%3C%2FTransactionSide%3E%3CEntryGateMethod%3EVPOS_ThreeDModelPayGate%3C%2FEntryGateMethod%3E%3C%2FVPosMessage%3E%3CIsEnrolled%3Etrue%3C%2FIsEnrolled%3E%3CIsVirtual%3Efalse%3C%2FIsVirtual%3E%3COrderId%3E0%3C%2FOrderId%3E%3CTransactionTime%3E0001-01-01T00%3A00%3A00%3C%2FTransactionTime%3E%3CMD%3E67YtBfBRTZ0XBKnAHi8c%2FA%3D%3D%3C%2FMD%3E%3CAuthenticationPacket%3EWYGDgSIrSHDtYwF%2FWEN%2BnfwX63sppA%3D%3C%2FAuthenticationPacket%3E%3CACSURL%3Ehttps%3A%2F%2Facs.bkm.com.tr%2Fmdpayacs%2Fpareq%3C%2FACSURL%3E%3C%2FVPosTransactionResponseContract%3E', - ], - ], - ], - '3d_auth_success_1' => [ - // bazi kredi kartlarda bu sekilde HTML response donuyor - 'html' => "\n\n\n\n\n3D Secure Processing\n\n\n
\n
\n
\n

3D Secure Processing

\nPlease wait..\n
\n\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n
\n
\n
\n
\n\n
\n
\n\n\n", - 'expected' => [ - 'gateway' => 'https://certemvtds.bkm.com.tr/tds/resultFlow', - 'form_inputs' => [ - 'threeDSServerWebFlowStart' => 'eyJhbGciOiJIUzI1NiJ9.ewogICJ0aHJlZURTU2VydmVyV2ViRmxvd1N0YXJ0IiA6IHsKICAgICJhY3F1aXJlcklEIiA6ICIyMDUiLAogICAgInRocmVlRFNTZXJ2ZXJUcmFuc0lEIiA6ICJhN2QyMjQ4Mi1jMjI2LTRkZjUtODkwNC00M2RmOTZmOTJmNDAiLAogICAgInRocmVlRFNSZXF1ZXN0b3JUcmFuc0lEIiA6ICI4ZGVhOGIwYi1mZTg0LTRhZGQtOWI4Mi05MzM2ZWYyMWM1MjciLAogICAgInRpbWVab25lIiA6ICJVVEMrMDM6MDAiLAogICAgInRpbWVTdGFtcCIgOiAiMjAyMjEyMjgxMjU2NDAiLAogICAgInZlcnNpb24iIDogIjEuMC4wIgogIH0KfQ.w7KQvGhrujSZmzyqEBsqJJKb19vJo16pq_PssXcGc6k', - 'browserColorDepth' => '', - 'browserScreenHeight' => '', - 'browserScreenWidth' => '', - 'browserTZ' => '', - 'browserJavascriptEnabled' => '', - 'browserJavaEnabled' => '', - ], - ], - ], - '3d_auth_fail' => [ - // fail durum testi - 'html' => '
', - 'expected' => [ - // 3d form data olusturulmasi icin gonderilen istek banka tarafindan reddedillirse, bankadan fail URL'a yonlendirilecek bir response (html) doner. - 'gateway' => 'http://localhost/finansbank-payfor/3d/response.php', - 'form_inputs' => [ - 'AuthenticationResponse' => '%3c%3fxml+version%3d%221.0%22+encoding%3d%22utf-8%22%3f%3e%3cVPosTransactionResponseContract+xmlns%3axsd%3d%22http%3a%2f%2fwww.w3.org%2f2001%2fXMLSchema%22+xmlns%3axsi%3d%22http%3a%2f%2fwww.w3.org%2f2001%2fXMLSchema-instance%22%3e%3cIsEnrolled%3etrue%3c%2fIsEnrolled%3e%3cIsVirtual%3efalse%3c%2fIsVirtual%3e%3cResponseCode%3eHashDataError%3c%2fResponseCode%3e%3cResponseMessage%3e%c5%9eifrelenen+veriler+(Hashdata)+uyu%c5%9fmamaktad%c4%b1r.%3c%2fResponseMessage%3e%3cOrderId%3e0%3c%2fOrderId%3e%3cTransactionTime%3e0001-01-01T00%3a00%3a00%3c%2fTransactionTime%3e%3cMerchantOrderId%3e2020110828BC%3c%2fMerchantOrderId%3e%3cReferenceId%3efbab348b4c074d1b9a5247471d91f5d1%3c%2fReferenceId%3e%3cMerchantId%3e496%3c%2fMerchantId%3e%3cBusinessKey%3e0%3c%2fBusinessKey%3e%3c%2fVPosTransactionResponseContract%3e', - ], - ], - ], - [ - // test with custom APM_DO_NOT_TOUCH element - 'html' => $htmlWithCustomHtmlElement, - 'expected' => [ - 'gateway' => 'https://site/gateway/3d/fail?uuid=BR7z5PDu6c', - 'form_inputs' => [ - 'AuthenticationResponse' => '%3c%3fxml+version%3d%221.0%22+encoding%3d%22utf-8%22%3f%3e%3cVPosTransactionResponseContract+xmlns%3axsd%3d%22http%3a%2f%2fwww.w3.org%2f2001%2fXMLSchema%22+xmlns%3axsi%3d%22http%3a%2f%2fwww.w3.org%2f2001%2fXMLSchema-instance%22%3e%3cIsEnrolled%3etrue%3c%2fIsEnrolled%3e%3cIsVirtual%3efalse%3c%2fIsVirtual%3e%3cResponseCode%3ePosMerchantIPError%3c%2fResponseCode%3e%3cResponseMessage%3eIP+adresi+tan%c4%b1ml%c4%b1+de%c4%9fildir.%3c%2fResponseMessage%3e%3cOrderId%3e0%3c%2fOrderId%3e%3cTransactionTime%3e0001-01-01T00%3a00%3a00%3c%2fTransactionTime%3e%3cMerchantOrderId%3eEak3mC1eW5%3c%2fMerchantOrderId%3e%3cReferenceId%3ea92e57f52ac443538bdb71b10a6c6fe7%3c%2fReferenceId%3e%3cMerchantId%3e80123%3c%2fMerchantId%3e%3cBusinessKey%3e0%3c%2fBusinessKey%3e%3c%2fVPosTransactionResponseContract%3e', - ], - ], - ], + yield 'test_pay_2' => [ + 'input' => ['abc' => 1], + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +1 +', ]; } @@ -263,160 +139,12 @@ public static function decodeXmlDataProvider(): iterable ]; } - public static function decodeJsonDataProvider(): Generator - { - yield 'test_cancel' => [ - 'input' => 'İptal işlemi satışla aynı gün yapılmalıdır. Geçmiş tarihli işlem için iade yapınız.InvalidRequestErrortrueBusinessErrorfalsefalsefalseDbLayerError00001-01-01T00:00:000', - 'txType' => PosInterface::TX_TYPE_CANCEL, - 'expected' => [ - 'SaleReversalResponse' => [ - 'SaleReversalResult' => [ - 'Results' => [ - 'Result' => [ - 'ErrorMessage' => 'İptal işlemi satışla aynı gün yapılmalıdır. Geçmiş tarihli işlem için iade yapınız.', - 'ErrorCode' => 'InvalidRequestError', - 'IsFriendly' => 'true', - 'Severity' => 'BusinessError', - ], - ], - 'Success' => 'false', - 'Value' => [ - 'IsEnrolled' => 'false', - 'IsVirtual' => 'false', - 'ResponseCode' => 'DbLayerError', - 'OrderId' => '0', - 'TransactionTime' => '0001-01-01T00:00:00', - 'MerchantId' => [ - '@xsi:nil' => 'true', - '#' => '', - ], - 'BusinessKey' => '0', - ], - ], - ], - ], - ]; - yield 'test_refund' => [ - 'input' => 'IsoProxyFactoryServiceResponseWasNullServiceUnavailabletrueBusinessErrorfalsefalsefalseDbLayerError00001-01-01T00:00:000', - 'txType' => PosInterface::TX_TYPE_REFUND, - 'expected' => [ - "PartialDrawbackResponse" => [ - "PartialDrawbackResult" => [ - "Results" => [ - "Result" => [ - "ErrorMessage" => "IsoProxyFactoryServiceResponseWasNull", - "ErrorCode" => "ServiceUnavailable", - "IsFriendly" => "true", - "Severity" => "BusinessError", - ], - ], - "Success" => "false", - "Value" => [ - "IsEnrolled" => "false", - "IsVirtual" => "false", - "ResponseCode" => "DbLayerError", - "OrderId" => "0", - "TransactionTime" => "0001-01-01T00:00:00", - "MerchantId" => [ - "@xsi:nil" => "true", - "#" => "", - ], - "BusinessKey" => "0", - ], - ], - ], - ], - ]; - yield 'test_status' => [ - 'input' => 'truefalsetrue30270415620260209089B496John DoeMasterCard518896******25442026-02-09T19:10:09.097161110.0110.010.000.000949ECOM0300İşlem gerçekleştirildi.2Auto207.211.215.148apitest0042126232906VP008759604019659177659177vposuser2STD8BOATEST12026-02-09T19:10:09.087webgate2STD8BOATEST12026-02-09T19:10:20.703172.20.8.8400000', - 'txType' => PosInterface::TX_TYPE_STATUS, - 'expected' => [ - 'GetMerchantOrderDetailResponse' => [ - 'GetMerchantOrderDetailResult' => [ - 'Results' => '', - 'Success' => 'true', - 'Value' => [ - 'OrderContract' => [ - 'IsSelected' => 'false', - 'IsSelectable' => 'true', - 'OrderId' => '302704156', - 'MerchantOrderId' => '20260209089B', - 'MerchantId' => '496', - 'CardHolderName' => 'John Doe', - 'CardType' => 'MasterCard', - 'CardNumber' => '518896******2544', - 'OrderDate' => '2026-02-09T19:10:09.097', - 'OrderStatus' => '1', - 'LastOrderStatus' => '6', - 'OrderType' => '1', - 'TransactionStatus' => '1', - 'FirstAmount' => '10.01', - 'CancelAmount' => '10.01', - 'DrawbackAmount' => '0.00', - 'ClosedAmount' => '0.00', - 'FEC' => '0949', - 'VPSEntryMode' => 'ECOM', - 'InstallmentCount' => '0', - 'TransactionSecurity' => '3', - 'ResponseCode' => '00', - 'ResponseExplain' => 'İşlem gerçekleştirildi.', - 'EndOfDayStatus' => '2', - 'TransactionSide' => 'Auto', - 'CardHolderIPAddress' => '', - 'MerchantIPAddress' => '207.211.215.148', - 'MerchantUserName' => 'apitest', - 'ProvNumber' => '004212', - 'BatchId' => '623', - 'CardExpireDate' => '2906', - 'PosTerminalId' => 'VP008759', - 'Explain' => '', - 'Explain2' => '', - 'Explain3' => '', - 'RRN' => '604019659177', - 'Stan' => '659177', - 'UserName' => 'vposuser2', - 'HostName' => 'STD8BOATEST1', - 'SystemDate' => '2026-02-09T19:10:09.087', - 'UpdateUserName' => 'webgate2', - 'UpdateHostName' => 'STD8BOATEST1', - 'UpdateSystemDate' => '2026-02-09T19:10:20.703', - 'EndOfDayDate' => [ - '@xsi:nil' => 'true', - '#' => '', - ], - - 'HostIP' => '172.20.8.84', - 'FECAmount' => '0', - 'IdentityTaxNumber' => '', - 'QueryId' => '0', - 'DebtId' => '0', - 'DebtorName' => '', - 'Period' => '', - 'SurchargeAmount' => '0', - 'SGKDebtAmount' => '0', - 'DeferringCount' => [ - '@xsi:nil' => 'true', - '#' => '', - ], - - ], - - ], - - ], - - ], - - ], - ]; - } - public static function decodeExceptionDataProvider(): Generator { yield 'test1' => [ 'input' => '', 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'expected_exception_class' => \Exception::class, + 'expected_exception_class' => NotEncodableValueException::class, ]; } } diff --git a/tests/Unit/Serializer/KuveytSoapApiPosSerializerTest.php b/tests/Unit/Serializer/KuveytSoapApiPosSerializerTest.php new file mode 100644 index 00000000..58cc2b0f --- /dev/null +++ b/tests/Unit/Serializer/KuveytSoapApiPosSerializerTest.php @@ -0,0 +1,246 @@ +serializer = new KuveytSoapApiPosSerializer(); + } + + public function testSupports(): void + { + $supports = $this->serializer::supports(KuveytSoapApiPos::class); + + $this->assertTrue($supports); + } + + /** + * @dataProvider encodeDataProvider + */ + public function testEncode(array $data, string $txType, ?string $format, string $expectedFormat, $expected): void + { + $result = $this->serializer->encode($data, $txType, $format); + if (is_string($expected)) { + $expected = str_replace(["\r"], '', $expected); + } + + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); + } + + /** + * @dataProvider decodeXmlDataProvider + */ + public function testDecodeXML(string $input, string $txType, array $expected): void + { + $actual = $this->serializer->decode($input, $txType); + + $this->assertSame($expected, $actual); + } + + public static function encodeDataProvider(): Generator + { + $refundTests = iterator_to_array(KuveytSoapApiPosRequestDataMapperTest::createRefundRequestDataProvider()); + + yield 'test_refund' => [ + 'input' => $refundTests[0]['expected'], + 'txType' => PosInterface::TX_TYPE_REFUND, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => '10000400235110180114293600318923298433298433241839TDV2.0.00request-hash800400235apiuserVisa0DrawBack010101012023070849CD0094900001', + ]; + + yield 'test_partial_refund' => [ + 'input' => $refundTests[1]['expected'], + 'txType' => PosInterface::TX_TYPE_REFUND_PARTIAL, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => '10000400235190180114293600318923298433298433241839TDV2.0.00request-hash800400235apiuserVisa0PartialDrawback090109012023070849CD0094900001', + ]; + + yield 'test_cancel' => [ + 'input' => ['abc' => 1, 'abc2' => ['abc3' => '3']], + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => '13', + ]; + + yield 'test_status' => [ + 'input' => ['abc' => 1, 'abc2' => ['abc3' => '3']], + 'txType' => PosInterface::TX_TYPE_STATUS, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => '13', + ]; + } + + public static function decodeXmlDataProvider(): iterable + { + yield 'test_cancel' => [ + 'input' => 'İptal işlemi satışla aynı gün yapılmalıdır. Geçmiş tarihli işlem için iade yapınız.InvalidRequestErrortrueBusinessErrorfalsefalsefalseDbLayerError00001-01-01T00:00:000', + 'txType' => PosInterface::TX_TYPE_CANCEL, + 'expected' => [ + 'SaleReversalResponse' => [ + 'SaleReversalResult' => [ + 'Results' => [ + 'Result' => [ + 'ErrorMessage' => 'İptal işlemi satışla aynı gün yapılmalıdır. Geçmiş tarihli işlem için iade yapınız.', + 'ErrorCode' => 'InvalidRequestError', + 'IsFriendly' => 'true', + 'Severity' => 'BusinessError', + ], + ], + 'Success' => 'false', + 'Value' => [ + 'IsEnrolled' => 'false', + 'IsVirtual' => 'false', + 'ResponseCode' => 'DbLayerError', + 'OrderId' => '0', + 'TransactionTime' => '0001-01-01T00:00:00', + 'MerchantId' => [ + '@xsi:nil' => 'true', + '#' => '', + ], + 'BusinessKey' => '0', + ], + ], + ], + ], + ]; + yield 'test_refund' => [ + 'input' => 'IsoProxyFactoryServiceResponseWasNullServiceUnavailabletrueBusinessErrorfalsefalsefalseDbLayerError00001-01-01T00:00:000', + 'txType' => PosInterface::TX_TYPE_REFUND, + 'expected' => [ + "PartialDrawbackResponse" => [ + "PartialDrawbackResult" => [ + "Results" => [ + "Result" => [ + "ErrorMessage" => "IsoProxyFactoryServiceResponseWasNull", + "ErrorCode" => "ServiceUnavailable", + "IsFriendly" => "true", + "Severity" => "BusinessError", + ], + ], + "Success" => "false", + "Value" => [ + "IsEnrolled" => "false", + "IsVirtual" => "false", + "ResponseCode" => "DbLayerError", + "OrderId" => "0", + "TransactionTime" => "0001-01-01T00:00:00", + "MerchantId" => [ + "@xsi:nil" => "true", + "#" => "", + ], + "BusinessKey" => "0", + ], + ], + ], + ], + ]; + yield 'test_status' => [ + 'input' => 'truefalsetrue30270415620260209089B496John DoeMasterCard518896******25442026-02-09T19:10:09.097161110.0110.010.000.000949ECOM0300İşlem gerçekleştirildi.2Auto207.211.215.148apitest0042126232906VP008759604019659177659177vposuser2STD8BOATEST12026-02-09T19:10:09.087webgate2STD8BOATEST12026-02-09T19:10:20.703172.20.8.8400000', + 'txType' => PosInterface::TX_TYPE_STATUS, + 'expected' => [ + 'GetMerchantOrderDetailResponse' => [ + 'GetMerchantOrderDetailResult' => [ + 'Results' => '', + 'Success' => 'true', + 'Value' => [ + 'OrderContract' => [ + 'IsSelected' => 'false', + 'IsSelectable' => 'true', + 'OrderId' => '302704156', + 'MerchantOrderId' => '20260209089B', + 'MerchantId' => '496', + 'CardHolderName' => 'John Doe', + 'CardType' => 'MasterCard', + 'CardNumber' => '518896******2544', + 'OrderDate' => '2026-02-09T19:10:09.097', + 'OrderStatus' => '1', + 'LastOrderStatus' => '6', + 'OrderType' => '1', + 'TransactionStatus' => '1', + 'FirstAmount' => '10.01', + 'CancelAmount' => '10.01', + 'DrawbackAmount' => '0.00', + 'ClosedAmount' => '0.00', + 'FEC' => '0949', + 'VPSEntryMode' => 'ECOM', + 'InstallmentCount' => '0', + 'TransactionSecurity' => '3', + 'ResponseCode' => '00', + 'ResponseExplain' => 'İşlem gerçekleştirildi.', + 'EndOfDayStatus' => '2', + 'TransactionSide' => 'Auto', + 'CardHolderIPAddress' => '', + 'MerchantIPAddress' => '207.211.215.148', + 'MerchantUserName' => 'apitest', + 'ProvNumber' => '004212', + 'BatchId' => '623', + 'CardExpireDate' => '2906', + 'PosTerminalId' => 'VP008759', + 'Explain' => '', + 'Explain2' => '', + 'Explain3' => '', + 'RRN' => '604019659177', + 'Stan' => '659177', + 'UserName' => 'vposuser2', + 'HostName' => 'STD8BOATEST1', + 'SystemDate' => '2026-02-09T19:10:09.087', + 'UpdateUserName' => 'webgate2', + 'UpdateHostName' => 'STD8BOATEST1', + 'UpdateSystemDate' => '2026-02-09T19:10:20.703', + 'EndOfDayDate' => [ + '@xsi:nil' => 'true', + '#' => '', + ], + + 'HostIP' => '172.20.8.84', + 'FECAmount' => '0', + 'IdentityTaxNumber' => '', + 'QueryId' => '0', + 'DebtId' => '0', + 'DebtorName' => '', + 'Period' => '', + 'SurchargeAmount' => '0', + 'SGKDebtAmount' => '0', + 'DeferringCount' => [ + '@xsi:nil' => 'true', + '#' => '', + ], + + ], + + ], + + ], + + ], + + ], + ]; + } +} diff --git a/tests/Unit/Serializer/ParamPosSerializerTest.php b/tests/Unit/Serializer/ParamPosSerializerTest.php index 889e6307..6f81c6f6 100644 --- a/tests/Unit/Serializer/ParamPosSerializerTest.php +++ b/tests/Unit/Serializer/ParamPosSerializerTest.php @@ -7,9 +7,12 @@ namespace Mews\Pos\Tests\Unit\Serializer; use Generator; +use Mews\Pos\Gateways\EstV3Pos; +use Mews\Pos\Gateways\Param3DHostPos; use Mews\Pos\Gateways\ParamPos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\ParamPosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -29,19 +32,24 @@ protected function setUp(): void public function testSupports(): void { $supports = $this->serializer::supports(ParamPos::class); - $this->assertTrue($supports); + $supports = $this->serializer::supports(Param3DHostPos::class); + $this->assertTrue($supports); + + $supports = $this->serializer::supports(EstV3Pos::class); + $this->assertFalse($supports); } /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, ?string $txType, string $expected): void + public function testEncode(array $data, ?string $txType, ?string $format, string $expectedFormat, string $expected): void { - $result = $this->serializer->encode($data, $txType); + $result = $this->serializer->encode($data, $txType, $format); $expected = str_replace(["\r"], '', $expected); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } @@ -61,7 +69,31 @@ public function testDecode(string $data, string $txType, array $expected): void public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => [ + 'input' => [ + 'soap:Body' => [ + 'TP_WMD_UCD' => [ + 'Islem_ID' => 'rand', + 'Islem_Hash' => 'jsLYSB3lJ81leFgDLw4D8PbXURs=', + 'G' => [ + 'CLIENT_CODE' => '10738', + 'CLIENT_USERNAME' => 'Test1', + 'CLIENT_PASSWORD' => 'Test2', + ], + 'GUID' => '0c13d406-873b-403b-9c09-a5766840d98c', + 'Islem_Guvenlik_Tip' => '3D', + ], + ], + ], + 'txType' => null, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +randjsLYSB3lJ81leFgDLw4D8PbXURs=10738Test1Test20c13d406-873b-403b-9c09-a5766840d98c3D +', + ]; + + yield 'test2' => [ + 'input' => [ 'soap:Body' => [ 'TP_WMD_UCD' => [ 'Islem_ID' => 'rand', @@ -76,8 +108,10 @@ public static function encodeDataProvider(): Generator ], ], ], - 'txType' => null, - 'expected' => ' + 'txType' => null, + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' randjsLYSB3lJ81leFgDLw4D8PbXURs=10738Test1Test20c13d406-873b-403b-9c09-a5766840d98c3D ', ]; diff --git a/tests/Unit/Serializer/PayFlexCPV4PosSerializerTest.php b/tests/Unit/Serializer/PayFlexCPV4PosSerializerTest.php index a298e7a4..3f52dca5 100644 --- a/tests/Unit/Serializer/PayFlexCPV4PosSerializerTest.php +++ b/tests/Unit/Serializer/PayFlexCPV4PosSerializerTest.php @@ -10,6 +10,7 @@ use Mews\Pos\Gateways\PayFlexCPV4Pos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\PayFlexCPV4PosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\NotEncodableValueException; @@ -47,17 +48,18 @@ public function testDecodeException(string $input, string $exceptionClass): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $txType, string $expected): void + public function testEncode(array $data, string $txType, ?string $format, string $expectedFormat, string $expected): void { - $result = $this->serializer->encode($data, $txType); + $result = $this->serializer->encode($data, $txType, $format); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => [ + 'input' => [ 'MerchantId' => '000000000111111', 'Password' => '3XTgER89as', 'TransactionType' => 'Sale', @@ -70,18 +72,34 @@ public static function encodeDataProvider(): Generator 'Expiry' => '202112', 'Cvv' => '122', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'expected' => 'MerchantId=000000000111111&Password=3XTgER89as&TransactionType=Sale&OrderId=order222&CurrencyAmount=100.00&CurrencyCode=949&ClientIp=127.0.0.1&TransactionDeviceSource=0&Pan=5555444433332222&Expiry=202112&Cvv=122', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_FORM, + 'expected' => 'MerchantId=000000000111111&Password=3XTgER89as&TransactionType=Sale&OrderId=order222&CurrencyAmount=100.00&CurrencyCode=949&ClientIp=127.0.0.1&TransactionDeviceSource=0&Pan=5555444433332222&Expiry=202112&Cvv=122', + ]; + + yield 'test2' => [ + 'input' => [ + 'MerchantId' => '000000000111111', + 'Password' => '3XTgER89as', + 'TransactionType' => 'Sale', + ], + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'format' => SerializerInterface::FORMAT_FORM, + 'expected_format' => SerializerInterface::FORMAT_FORM, + 'expected' => 'MerchantId=000000000111111&Password=3XTgER89as&TransactionType=Sale', ]; yield 'custom_query' => [ - 'input' => [ + 'input' => [ 'MerchantId' => '000000000111111', 'Password' => '3XTgER89as', 'abc' => 'abc', ], - 'txType' => PosInterface::TX_TYPE_CUSTOM_QUERY, - 'expected' => 'MerchantId=000000000111111&Password=3XTgER89as&abc=abc', + 'txType' => PosInterface::TX_TYPE_CUSTOM_QUERY, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_FORM, + 'expected' => 'MerchantId=000000000111111&Password=3XTgER89as&abc=abc', ]; } diff --git a/tests/Unit/Serializer/PayFlexV4PosSearchApiSerializerTest.php b/tests/Unit/Serializer/PayFlexV4PosSearchApiSerializerTest.php new file mode 100644 index 00000000..a3b40378 --- /dev/null +++ b/tests/Unit/Serializer/PayFlexV4PosSearchApiSerializerTest.php @@ -0,0 +1,134 @@ +serializer = new PayFlexV4PosSearchApiSerializer(); + } + + public function testSupports(): void + { + $supports = $this->serializer::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_QUERY_API); + $this->assertTrue($supports); + + $supports = $this->serializer::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_PAYMENT_API); + $this->assertFalse($supports); + } + + /** + * @dataProvider encodeDataProvider + */ + public function testEncode(array $data, string $txType, ?string $format, string $expectedFormat, $expected): void + { + $result = $this->serializer->encode($data, $txType, $format); + $expected = str_replace(["\r"], '', $expected); + + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); + } + + /** + * @testWith ["pay"] + * @testWith ["pre"] + * @testWith ["post"] + */ + public function testEncodeException(string $txType): void + { + $data = ['abc' => 1]; + + $this->expectException(UnsupportedTransactionTypeException::class); + $this->serializer->encode($data, $txType); + } + + /** + * @dataProvider decodeDataProvider + */ + public function testDecode(string $input, array $expected): void + { + $actual = $this->serializer->decode($input); + + $this->assertSame($expected, $actual); + } + + /** + * @dataProvider decodeExceptionDataProvider + */ + public function testDecodeException(string $input, string $exceptionClass): void + { + $this->expectException($exceptionClass); + + $this->serializer->decode($input); + } + + public static function decodeDataProvider(): Generator + { + yield 'test1' => [ + 'input' => '9039Üye işyeri bulunamadı.', + 'expected' => [ + 'ResultCode' => '9039', + 'ResultDetail' => 'Üye işyeri bulunamadı.', + 'InstallmentTable' => '', + ], + ]; + } + + public static function decodeExceptionDataProvider(): Generator + { + yield 'test1' => [ + 'input' => "Request RejectedThe requested URL was rejected. Please consult with your administrator.

Your support ID is: 11795445874629392419

[Go Back]", + 'expected_exception_class' => \Exception::class, + ]; + yield 'test2' => [ + 'input' => '', + 'expected_exception_class' => NotEncodableValueException::class, + ]; + } + + public static function encodeDataProvider(): Generator + { + yield 'test_status' => [ + 'input' => [ + 'MerchantCriteria' => [ + 'HostMerchantId' => '000000000111111', + 'MerchantPassword' => '3XTgER89as', + ], + 'TransactionCriteria' => [ + 'TransactionId' => '', + 'OrderId' => 'order222', + 'AuthCode' => '', + ], + ], + 'txType' => PosInterface::TX_TYPE_STATUS, + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +0000000001111113XTgER89asorder222 +', + ]; + } + +} diff --git a/tests/Unit/Serializer/PayFlexV4PosSerializerTest.php b/tests/Unit/Serializer/PayFlexV4PosSerializerTest.php index 85df4d39..30a7fc88 100644 --- a/tests/Unit/Serializer/PayFlexV4PosSerializerTest.php +++ b/tests/Unit/Serializer/PayFlexV4PosSerializerTest.php @@ -7,10 +7,12 @@ namespace Mews\Pos\Tests\Unit\Serializer; use Generator; +use Mews\Pos\Client\HttpClientInterface; use Mews\Pos\Exceptions\UnsupportedTransactionTypeException; use Mews\Pos\Gateways\PayFlexV4Pos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\PayFlexV4PosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Exception\NotEncodableValueException; @@ -30,20 +32,23 @@ protected function setUp(): void public function testSupports(): void { - $supports = $this->serializer::supports(PayFlexV4Pos::class); - + $supports = $this->serializer::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_PAYMENT_API); $this->assertTrue($supports); + + $supports = $this->serializer::supports(PayFlexV4Pos::class, HttpClientInterface::API_NAME_QUERY_API); + $this->assertFalse($supports); } /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $txType, string $expected): void + public function testEncode(array $data, string $txType, ?string $format, string $expectedFormat, $expected): void { - $result = $this->serializer->encode($data, $txType); + $result = $this->serializer->encode($data, $txType, $format); $expected = str_replace(["\r"], '', $expected); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -93,11 +98,11 @@ public static function decodeDataProvider(): Generator public static function decodeExceptionDataProvider(): Generator { yield 'test1' => [ - 'input' => "Request RejectedThe requested URL was rejected. Please consult with your administrator.

Your support ID is: 11795445874629392419

[Go Back]", + 'input' => "Request RejectedThe requested URL was rejected. Please consult with your administrator.

Your support ID is: 11795445874629392419

[Go Back]", 'expected_exception_class' => \Exception::class, ]; yield 'test2' => [ - 'input' => '', + 'input' => '', 'expected_exception_class' => NotEncodableValueException::class, ]; } @@ -105,7 +110,7 @@ public static function decodeExceptionDataProvider(): Generator public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => [ + 'input' => [ 'MerchantId' => '000000000111111', 'Password' => '3XTgER89as', 'TerminalNo' => 'VP999999', @@ -119,26 +124,10 @@ public static function encodeDataProvider(): Generator 'Expiry' => '202112', 'Cvv' => '122', ], - 'txType' => PosInterface::TX_TYPE_PAY_AUTH, - 'expected' => '0000000001111113XTgER89asVP999999Saleorder222100.00949127.0.0.105555444433332222202112122', - ]; - - yield 'test_status' => [ - 'input' => [ - 'MerchantCriteria' => [ - 'HostMerchantId' => '000000000111111', - 'MerchantPassword' => '3XTgER89as', - ], - 'TransactionCriteria' => [ - 'TransactionId' => '', - 'OrderId' => 'order222', - 'AuthCode' => '', - ], - ], - 'txType' => PosInterface::TX_TYPE_STATUS, - 'expected' => ' -0000000001111113XTgER89asorder222 -', + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => '0000000001111113XTgER89asVP999999Saleorder222100.00949127.0.0.105555444433332222202112122', ]; } diff --git a/tests/Unit/Serializer/PayForPosSerializerTest.php b/tests/Unit/Serializer/PayForPosSerializerTest.php index cba8c038..2c388d84 100644 --- a/tests/Unit/Serializer/PayForPosSerializerTest.php +++ b/tests/Unit/Serializer/PayForPosSerializerTest.php @@ -10,6 +10,7 @@ use Mews\Pos\Gateways\PayForPos; use Mews\Pos\PosInterface; use Mews\Pos\Serializer\PayForPosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -28,20 +29,21 @@ protected function setUp(): void public function testSupports(): void { - $supports = $this->serializer::supports(PayForPos::class); - - $this->assertTrue($supports); + $this->assertTrue(PayForPosSerializer::supports(PayForPos::class)); + $this->assertTrue(PayForPosSerializer::supports(PayForPos::class, 'payment_api')); + $this->assertFalse(PayForPosSerializer::supports(\Mews\Pos\Gateways\AkbankPos::class)); } /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, $expected): void { - $result = $this->serializer->encode($data); + $result = $this->serializer->encode($data, null, $format); $expected = str_replace(["\r"], '', $expected); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } @@ -58,7 +60,7 @@ public function testDecode(string $data, string $txType, array $expected): void public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => [ + 'input' => [ 'MerchantId' => '085300000009704', 'UserCode' => 'QNB_API_KULLANICI_3DPAY', 'UserPass' => 'UcBN0', @@ -76,7 +78,36 @@ public static function encodeDataProvider(): Generator 'Expiry' => '1221', 'Cvv2' => '122', ], - 'expected' => ' + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +085300000009704QNB_API_KULLANICI_3DPAYUcBN050order222NonSecureAuth100.259490trahmet55554444333322221221122 +', + ]; + + + yield 'test2' => [ + 'input' => [ + 'MerchantId' => '085300000009704', + 'UserCode' => 'QNB_API_KULLANICI_3DPAY', + 'UserPass' => 'UcBN0', + 'MbrId' => '5', + 'MOTO' => '0', + 'OrderId' => 'order222', + 'SecureType' => 'NonSecure', + 'TxnType' => 'Auth', + 'PurchAmount' => '100.25', + 'Currency' => '949', + 'InstallmentCount' => '0', + 'Lang' => 'tr', + 'CardHolderName' => 'ahmet', + 'Pan' => '5555444433332222', + 'Expiry' => '1221', + 'Cvv2' => '122', + ], + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' 085300000009704QNB_API_KULLANICI_3DPAYUcBN050order222NonSecureAuth100.259490trahmet55554444333322221221122 ', ]; @@ -744,151 +775,151 @@ public static function decodeDataProvider(): Generator 'txType' => PosInterface::TX_TYPE_ORDER_HISTORY, 'expected' => [ '@xsi:noNamespaceSchemaLocation' => 'TxnHistoryReport.xsd', - 'PaymentRequestExtended' => [ + 'PaymentRequestExtended' => [ [ 'PaymentRequest' => [ - 'UseExistingDataWhenInserting' => 'false', - 'RequestGuid' => '1000000093565640', - 'status' => '1', - 'InsertDatetime' => '2023-12-29T01:09:03', - 'lastUpdated' => '2023122901090396', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '20231228C01D', - 'PaymentSeq' => '0', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'RequestStartDatetime' => '20231229010903935', - 'MpiStartDatetime' => '0', - 'MpiEndDatetime' => '0', - 'PaymentStartDatetime' => '20231229010903951', - 'PaymentEndDatetime' => '20231229010903967', - 'RequestEndDatetime' => '20231229010903967', - 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', - 'Expiry' => '2501', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'TxnAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'UserCode' => 'QNB_API_KULLANICI_3DPAY', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PreAuth', - 'TerminalTxnType' => '2', - 'MOTO' => '0', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'Expsign' => '', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'Accept' => '*/*', - 'Agent' => 'Symfony HttpClient/Curl', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Stat' => '', - 'TxnResult' => 'Success', - 'AuthCode' => 'S74418', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '3322', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '96705411', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20231229', - 'SysDate' => '20231229', - 'F11' => '20764', - 'F37' => '336301020764', - 'F37_ORG' => '', - 'Mti' => '0', - 'Pcode' => '0', - 'F12' => '10903', - 'F13' => '1229', - 'F22' => '812', - 'F25' => '59', - 'F32' => '', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '32', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '6', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'false', - 'TemplateType' => '0', - 'HasAddressCount' => 'false', - 'IsPaymentFacilitator' => 'false', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankSpecificRequest' => '0', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', + 'UseExistingDataWhenInserting' => 'false', + 'RequestGuid' => '1000000093565640', + 'status' => '1', + 'InsertDatetime' => '2023-12-29T01:09:03', + 'lastUpdated' => '2023122901090396', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '20231228C01D', + 'PaymentSeq' => '0', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'RequestStartDatetime' => '20231229010903935', + 'MpiStartDatetime' => '0', + 'MpiEndDatetime' => '0', + 'PaymentStartDatetime' => '20231229010903951', + 'PaymentEndDatetime' => '20231229010903967', + 'RequestEndDatetime' => '20231229010903967', + 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', + 'Expiry' => '2501', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'TxnAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'UserCode' => 'QNB_API_KULLANICI_3DPAY', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PreAuth', + 'TerminalTxnType' => '2', + 'MOTO' => '0', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'Expsign' => '', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'Accept' => '*/*', + 'Agent' => 'Symfony HttpClient/Curl', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Stat' => '', + 'TxnResult' => 'Success', + 'AuthCode' => 'S74418', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '3322', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '96705411', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20231229', + 'SysDate' => '20231229', + 'F11' => '20764', + 'F37' => '336301020764', + 'F37_ORG' => '', + 'Mti' => '0', + 'Pcode' => '0', + 'F12' => '10903', + 'F13' => '1229', + 'F22' => '812', + 'F25' => '59', + 'F32' => '', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '32', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '6', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'false', + 'TemplateType' => '0', + 'HasAddressCount' => 'false', + 'IsPaymentFacilitator' => 'false', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankSpecificRequest' => '0', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', ], 'ExtraParameters' => [ @@ -917,148 +948,148 @@ public static function decodeDataProvider(): Generator 1 => [ 'PaymentRequest' => [ - 'UseExistingDataWhenInserting' => 'false', - 'RequestGuid' => '1000000093565641', - 'status' => '1', - 'InsertDatetime' => '2023-12-29T01:09:09', - 'lastUpdated' => '2023122901100152', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '20231228C01D', - 'PaymentSeq' => '0', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'RequestStartDatetime' => '20231229010909055', - 'MpiStartDatetime' => '0', - 'MpiEndDatetime' => '0', - 'PaymentStartDatetime' => '20231229010909055', - 'PaymentEndDatetime' => '20231229010909086', - 'RequestEndDatetime' => '20231229010909086', - 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', - 'Expiry' => '2501', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'TxnAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'UserCode' => 'QNB_API_KULLANICI_3DPAY', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PostAuth', - 'TerminalTxnType' => '2', - 'MOTO' => '', - 'OrgOrderId' => '20231228C01D', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'Expsign' => '', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'Accept' => '*/*', - 'Agent' => 'Symfony HttpClient/Curl', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => '', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'V', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Stat' => '', - 'TxnResult' => 'Success', - 'AuthCode' => 'S47983', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '3322', - 'VoidDate' => '20231229', - 'CardMask' => '415565******6111', - 'ReqId' => '96705416', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20231229', - 'SysDate' => '20231229', - 'F11' => '20769', - 'F37' => '336301020769', - 'F37_ORG' => '336301020764', - 'Mti' => '0', - 'Pcode' => '0', - 'F12' => '10909', - 'F13' => '1229', - 'F22' => '812', - 'F25' => '59', - 'F32' => '', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '31', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '5', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'false', - 'TemplateType' => '0', - 'HasAddressCount' => 'false', - 'IsPaymentFacilitator' => 'false', - 'OrgTxnType' => '', - 'F11_ORG' => '20764', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankSpecificRequest' => '0', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', + 'UseExistingDataWhenInserting' => 'false', + 'RequestGuid' => '1000000093565641', + 'status' => '1', + 'InsertDatetime' => '2023-12-29T01:09:09', + 'lastUpdated' => '2023122901100152', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '20231228C01D', + 'PaymentSeq' => '0', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'RequestStartDatetime' => '20231229010909055', + 'MpiStartDatetime' => '0', + 'MpiEndDatetime' => '0', + 'PaymentStartDatetime' => '20231229010909055', + 'PaymentEndDatetime' => '20231229010909086', + 'RequestEndDatetime' => '20231229010909086', + 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', + 'Expiry' => '2501', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'TxnAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'UserCode' => 'QNB_API_KULLANICI_3DPAY', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PostAuth', + 'TerminalTxnType' => '2', + 'MOTO' => '', + 'OrgOrderId' => '20231228C01D', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'Expsign' => '', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'Accept' => '*/*', + 'Agent' => 'Symfony HttpClient/Curl', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => '', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'V', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Stat' => '', + 'TxnResult' => 'Success', + 'AuthCode' => 'S47983', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '3322', + 'VoidDate' => '20231229', + 'CardMask' => '415565******6111', + 'ReqId' => '96705416', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20231229', + 'SysDate' => '20231229', + 'F11' => '20769', + 'F37' => '336301020769', + 'F37_ORG' => '336301020764', + 'Mti' => '0', + 'Pcode' => '0', + 'F12' => '10909', + 'F13' => '1229', + 'F22' => '812', + 'F25' => '59', + 'F32' => '', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '31', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '5', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'false', + 'TemplateType' => '0', + 'HasAddressCount' => 'false', + 'IsPaymentFacilitator' => 'false', + 'OrgTxnType' => '', + 'F11_ORG' => '20764', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankSpecificRequest' => '0', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '11001', - 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', + 'BayiKodu' => '', + 'VoidTime' => '11001', + 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', ], 'ExtraParameters' => [ @@ -1087,148 +1118,148 @@ public static function decodeDataProvider(): Generator 2 => [ 'PaymentRequest' => [ - 'UseExistingDataWhenInserting' => 'false', - 'RequestGuid' => '1000000093565642', - 'status' => '1', - 'InsertDatetime' => '2023-12-29T01:09:27', - 'lastUpdated' => '2023122901092726', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '20231228C01D', - 'PaymentSeq' => '96677647', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'RequestStartDatetime' => '20231229010927230', - 'MpiStartDatetime' => '0', - 'MpiEndDatetime' => '0', - 'PaymentStartDatetime' => '20231229010927246', - 'PaymentEndDatetime' => '20231229010927261', - 'RequestEndDatetime' => '20231229010927261', - 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', - 'Expiry' => '2501', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'TxnAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'UserCode' => 'QNB_API_KULLANICI_3DPAY', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'Refund', - 'TerminalTxnType' => '2', - 'MOTO' => '', - 'OrgOrderId' => '20231228C01D', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'Expsign' => '', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'Accept' => '*/*', - 'Agent' => 'Symfony HttpClient/Curl', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => '', - 'IrcDet' => 'Bu işlem geri alınamaz, lüften asıl işlemi iptal edin.', - 'IrcCode' => '99962', - 'Version' => '', - 'TxnStatus' => 'N', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Bu işlem geri alınamaz, lüften asıl işlemi iptal edin.', - 'VendorDet' => '', - 'D3Stat' => '', - 'TxnResult' => 'Failed', - 'AuthCode' => 'S47983', - 'HostRefNum' => '', - 'ProcReturnCode' => 'V014', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '3322', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '96705431', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '1.01', - 'RefundedPoint' => '0', - 'ReqDate' => '20231229', - 'SysDate' => '20231229', - 'F11' => '20784', - 'F37' => '336301020784', - 'F37_ORG' => '336301020769', - 'Mti' => '0', - 'Pcode' => '0', - 'F12' => '10927', - 'F13' => '1229', - 'F22' => '812', - 'F25' => '59', - 'F32' => '', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '31', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '6', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'false', - 'TemplateType' => '0', - 'HasAddressCount' => 'false', - 'IsPaymentFacilitator' => 'false', - 'OrgTxnType' => 'PostAuth', - 'F11_ORG' => '20769', - 'F12_ORG' => '10909', - 'F13_ORG' => '1229', - 'F22_ORG' => '812', - 'F25_ORG' => '59', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankSpecificRequest' => '0', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', + 'UseExistingDataWhenInserting' => 'false', + 'RequestGuid' => '1000000093565642', + 'status' => '1', + 'InsertDatetime' => '2023-12-29T01:09:27', + 'lastUpdated' => '2023122901092726', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '20231228C01D', + 'PaymentSeq' => '96677647', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'RequestStartDatetime' => '20231229010927230', + 'MpiStartDatetime' => '0', + 'MpiEndDatetime' => '0', + 'PaymentStartDatetime' => '20231229010927246', + 'PaymentEndDatetime' => '20231229010927261', + 'RequestEndDatetime' => '20231229010927261', + 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', + 'Expiry' => '2501', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'TxnAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'UserCode' => 'QNB_API_KULLANICI_3DPAY', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'Refund', + 'TerminalTxnType' => '2', + 'MOTO' => '', + 'OrgOrderId' => '20231228C01D', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'Expsign' => '', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'Accept' => '*/*', + 'Agent' => 'Symfony HttpClient/Curl', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => '', + 'IrcDet' => 'Bu işlem geri alınamaz, lüften asıl işlemi iptal edin.', + 'IrcCode' => '99962', + 'Version' => '', + 'TxnStatus' => 'N', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Bu işlem geri alınamaz, lüften asıl işlemi iptal edin.', + 'VendorDet' => '', + 'D3Stat' => '', + 'TxnResult' => 'Failed', + 'AuthCode' => 'S47983', + 'HostRefNum' => '', + 'ProcReturnCode' => 'V014', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '3322', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '96705431', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '1.01', + 'RefundedPoint' => '0', + 'ReqDate' => '20231229', + 'SysDate' => '20231229', + 'F11' => '20784', + 'F37' => '336301020784', + 'F37_ORG' => '336301020769', + 'Mti' => '0', + 'Pcode' => '0', + 'F12' => '10927', + 'F13' => '1229', + 'F22' => '812', + 'F25' => '59', + 'F32' => '', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '31', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '6', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'false', + 'TemplateType' => '0', + 'HasAddressCount' => 'false', + 'IsPaymentFacilitator' => 'false', + 'OrgTxnType' => 'PostAuth', + 'F11_ORG' => '20769', + 'F12_ORG' => '10909', + 'F13_ORG' => '1229', + 'F22_ORG' => '812', + 'F25_ORG' => '59', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankSpecificRequest' => '0', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', ], 'ExtraParameters' => [ @@ -1257,148 +1288,148 @@ public static function decodeDataProvider(): Generator 3 => [ 'PaymentRequest' => [ - 'UseExistingDataWhenInserting' => 'false', - 'RequestGuid' => '1000000093565668', - 'status' => '1', - 'InsertDatetime' => '2023-12-29T01:10:01', - 'lastUpdated' => '2023122901100153', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '20231228C01D', - 'PaymentSeq' => '0', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'RequestStartDatetime' => '20231229011001458', - 'MpiStartDatetime' => '0', - 'MpiEndDatetime' => '0', - 'PaymentStartDatetime' => '20231229011001489', - 'PaymentEndDatetime' => '20231229011001536', - 'RequestEndDatetime' => '20231229011001536', - 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', - 'Expiry' => '2501', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'TxnAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'UserCode' => 'QNB_API_KULLANICI_3DPAY', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'Void', - 'TerminalTxnType' => '2', - 'MOTO' => '', - 'OrgOrderId' => '20231228C01D', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'Expsign' => '', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'Accept' => '*/*', - 'Agent' => 'Symfony HttpClient/Curl', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => '', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Stat' => '', - 'TxnResult' => 'Success', - 'AuthCode' => 'S74990', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '3322', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '96705532', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20231229', - 'SysDate' => '20231229', - 'F11' => '20884', - 'F37' => '336301020884', - 'F37_ORG' => '336301020764', - 'Mti' => '0', - 'Pcode' => '0', - 'F12' => '11001', - 'F13' => '1229', - 'F22' => '812', - 'F25' => '59', - 'F32' => '', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '78', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '9', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'false', - 'TemplateType' => '0', - 'HasAddressCount' => 'false', - 'IsPaymentFacilitator' => 'false', - 'OrgTxnType' => 'PostAuth', - 'F11_ORG' => '20764', - 'F12_ORG' => '10909', - 'F13_ORG' => '1229', - 'F22_ORG' => '812', - 'F25_ORG' => '59', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankSpecificRequest' => '0', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', + 'UseExistingDataWhenInserting' => 'false', + 'RequestGuid' => '1000000093565668', + 'status' => '1', + 'InsertDatetime' => '2023-12-29T01:10:01', + 'lastUpdated' => '2023122901100153', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '20231228C01D', + 'PaymentSeq' => '0', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'RequestStartDatetime' => '20231229011001458', + 'MpiStartDatetime' => '0', + 'MpiEndDatetime' => '0', + 'PaymentStartDatetime' => '20231229011001489', + 'PaymentEndDatetime' => '20231229011001536', + 'RequestEndDatetime' => '20231229011001536', + 'Pan' => '9E3EAA293B389C4AD4B22F1B28E15ED0', + 'Expiry' => '2501', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'TxnAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'UserCode' => 'QNB_API_KULLANICI_3DPAY', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'Void', + 'TerminalTxnType' => '2', + 'MOTO' => '', + 'OrgOrderId' => '20231228C01D', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'Expsign' => '', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'Accept' => '*/*', + 'Agent' => 'Symfony HttpClient/Curl', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => '', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Stat' => '', + 'TxnResult' => 'Success', + 'AuthCode' => 'S74990', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '3322', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '96705532', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20231229', + 'SysDate' => '20231229', + 'F11' => '20884', + 'F37' => '336301020884', + 'F37_ORG' => '336301020764', + 'Mti' => '0', + 'Pcode' => '0', + 'F12' => '11001', + 'F13' => '1229', + 'F22' => '812', + 'F25' => '59', + 'F32' => '', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '78', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '9', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'false', + 'TemplateType' => '0', + 'HasAddressCount' => 'false', + 'IsPaymentFacilitator' => 'false', + 'OrgTxnType' => 'PostAuth', + 'F11_ORG' => '20764', + 'F12_ORG' => '10909', + 'F13_ORG' => '1229', + 'F22_ORG' => '812', + 'F25_ORG' => '59', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankSpecificRequest' => '0', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', ], 'ExtraParameters' => [ @@ -1426,8 +1457,15 @@ public static function decodeDataProvider(): Generator ], ], - '@xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + '@xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', ], ]; + + yield 'test_with_redundant_whitespaces' => [ + + 'input' => "\r\n\r\n S31432\r\n", + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, + 'expected' => ['AuthCode' => 'S31432'], + ]; } } diff --git a/tests/Unit/Serializer/PosNetSerializerTest.php b/tests/Unit/Serializer/PosNetSerializerTest.php index 939efb11..8ab7b1ea 100644 --- a/tests/Unit/Serializer/PosNetSerializerTest.php +++ b/tests/Unit/Serializer/PosNetSerializerTest.php @@ -9,6 +9,7 @@ use Generator; use Mews\Pos\Gateways\PosNet; use Mews\Pos\Serializer\PosNetSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -35,12 +36,13 @@ public function testSupports(): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, $expected): void { - $result = $this->serializer->encode($data); + $result = $this->serializer->encode($data, null, $format); $expected = str_replace(["\r"], '', $expected); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -56,21 +58,45 @@ public function testDecodeXML(string $input, array $expected): void public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => [ - 'mid' => '6706598320', - 'tid' => '67005551', + 'input' => [ + 'mid' => '6706598320', + 'tid' => '67005551', 'tranDateRequired' => '1', - 'sale' => [ - 'orderID' => '0000190620093100_024', - 'installment' => '00', - 'amount' => 175, + 'sale' => [ + 'orderID' => '0000190620093100_024', + 'installment' => '00', + 'amount' => 175, 'currencyCode' => 'TL', - 'ccno' => '5555444433332222', - 'expDate' => '2112', - 'cvc' => '122', - ] + 'ccno' => '5555444433332222', + 'expDate' => '2112', + 'cvc' => '122', + ], ], - 'expected' => ' + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +67065983206700555110000190620093100_02400175TL55554444333322222112122 +', + ]; + + yield 'test2' => [ + 'input' => [ + 'mid' => '6706598320', + 'tid' => '67005551', + 'tranDateRequired' => '1', + 'sale' => [ + 'orderID' => '0000190620093100_024', + 'installment' => '00', + 'amount' => 175, + 'currencyCode' => 'TL', + 'ccno' => '5555444433332222', + 'expDate' => '2112', + 'cvc' => '122', + ], + ], + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' 67065983206700555110000190620093100_02400175TL55554444333322222112122 ', ]; diff --git a/tests/Unit/Serializer/PosNetV1PosSerializerTest.php b/tests/Unit/Serializer/PosNetV1PosSerializerTest.php index 51bdad6a..cac4a188 100644 --- a/tests/Unit/Serializer/PosNetV1PosSerializerTest.php +++ b/tests/Unit/Serializer/PosNetV1PosSerializerTest.php @@ -9,6 +9,7 @@ use Generator; use Mews\Pos\Gateways\PosNetV1Pos; use Mews\Pos\Serializer\PosNetV1PosSerializer; +use Mews\Pos\Serializer\SerializerInterface; use PHPUnit\Framework\TestCase; /** @@ -35,11 +36,12 @@ public function testSupports(): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, $expected): void { - $result = $this->serializer->encode($data); + $result = $this->serializer->encode($data, null, $format); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -55,39 +57,51 @@ public function testDecode(string $input, array $expected): void public static function encodeDataProvider(): Generator { yield 'test1' => [ - 'input' => [ - 'ApiType' => 'JSON', - 'ApiVersion' => 'V100', - 'MACParams' => 'MerchantNo:TerminalNo:CardNo:Cvc2:ExpireDate:Amount', - 'MerchantNo' => '6700950031', - 'TerminalNo' => '67540050', - 'CipheredData' => null, - 'DealerData' => null, - 'IsEncrypted' => null, + 'input' => [ + 'ApiType' => 'JSON', + 'ApiVersion' => 'V100', + 'MACParams' => 'MerchantNo:TerminalNo:CardNo:Cvc2:ExpireDate:Amount', + 'MerchantNo' => '6700950031', + 'TerminalNo' => '67540050', + 'CipheredData' => null, + 'DealerData' => null, + 'IsEncrypted' => null, 'PaymentFacilitatorData' => null, - 'AdditionalInfoData' => null, - 'CardInformationData' => [ - 'CardNo' => '5555444433332222', - 'ExpireDate' => '2112', - 'Cvc2' => '122', + 'AdditionalInfoData' => null, + 'CardInformationData' => [ + 'CardNo' => '5555444433332222', + 'ExpireDate' => '2112', + 'Cvc2' => '122', 'CardHolderName' => 'ahmet', ], - 'IsMailOrder' => 'N', - 'IsRecurring' => null, - 'IsTDSecureMerchant' => null, - 'PaymentInstrumentType' => 'CARD', - 'ThreeDSecureData' => null, - 'Amount' => 175, - 'CurrencyCode' => 'TL', - 'OrderId' => '0000000620093100_024', - 'InstallmentCount' => '0', - 'InstallmentType' => 'N', - 'KOICode' => null, - 'MerchantMessageData' => null, - 'PointAmount' => null, - 'MAC' => 'ACUIQYdc6CDEoGqii4E/9Ec8cnN4++LmtrJvR8cn17A=', + 'IsMailOrder' => 'N', + 'IsRecurring' => null, + 'IsTDSecureMerchant' => null, + 'PaymentInstrumentType' => 'CARD', + 'ThreeDSecureData' => null, + 'Amount' => 175, + 'CurrencyCode' => 'TL', + 'OrderId' => '0000000620093100_024', + 'InstallmentCount' => '0', + 'InstallmentType' => 'N', + 'KOICode' => null, + 'MerchantMessageData' => null, + 'PointAmount' => null, + 'MAC' => 'ACUIQYdc6CDEoGqii4E/9Ec8cnN4++LmtrJvR8cn17A=', ], - 'expected' => '{"ApiType":"JSON","ApiVersion":"V100","MACParams":"MerchantNo:TerminalNo:CardNo:Cvc2:ExpireDate:Amount","MerchantNo":"6700950031","TerminalNo":"67540050","CipheredData":null,"DealerData":null,"IsEncrypted":null,"PaymentFacilitatorData":null,"AdditionalInfoData":null,"CardInformationData":{"CardNo":"5555444433332222","ExpireDate":"2112","Cvc2":"122","CardHolderName":"ahmet"},"IsMailOrder":"N","IsRecurring":null,"IsTDSecureMerchant":null,"PaymentInstrumentType":"CARD","ThreeDSecureData":null,"Amount":175,"CurrencyCode":"TL","OrderId":"0000000620093100_024","InstallmentCount":"0","InstallmentType":"N","KOICode":null,"MerchantMessageData":null,"PointAmount":null,"MAC":"ACUIQYdc6CDEoGqii4E\/9Ec8cnN4++LmtrJvR8cn17A="}', + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_JSON, + 'expected' => '{"ApiType":"JSON","ApiVersion":"V100","MACParams":"MerchantNo:TerminalNo:CardNo:Cvc2:ExpireDate:Amount","MerchantNo":"6700950031","TerminalNo":"67540050","CipheredData":null,"DealerData":null,"IsEncrypted":null,"PaymentFacilitatorData":null,"AdditionalInfoData":null,"CardInformationData":{"CardNo":"5555444433332222","ExpireDate":"2112","Cvc2":"122","CardHolderName":"ahmet"},"IsMailOrder":"N","IsRecurring":null,"IsTDSecureMerchant":null,"PaymentInstrumentType":"CARD","ThreeDSecureData":null,"Amount":175,"CurrencyCode":"TL","OrderId":"0000000620093100_024","InstallmentCount":"0","InstallmentType":"N","KOICode":null,"MerchantMessageData":null,"PointAmount":null,"MAC":"ACUIQYdc6CDEoGqii4E\/9Ec8cnN4++LmtrJvR8cn17A="}', + ]; + + yield 'test2' => [ + 'input' => [ + 'ApiType' => 'JSON', + 'ApiVersion' => 'V100', + ], + 'format' => SerializerInterface::FORMAT_JSON, + 'expected_format' => SerializerInterface::FORMAT_JSON, + 'expected' => '{"ApiType":"JSON","ApiVersion":"V100"}', ]; } diff --git a/tests/Unit/Serializer/ToslaPosSerializerTest.php b/tests/Unit/Serializer/ToslaPosSerializerTest.php index 8b1df388..9f060fd9 100644 --- a/tests/Unit/Serializer/ToslaPosSerializerTest.php +++ b/tests/Unit/Serializer/ToslaPosSerializerTest.php @@ -9,6 +9,7 @@ use Mews\Pos\Gateways\EstV3Pos; use Mews\Pos\Gateways\ToslaPos; use Mews\Pos\PosInterface; +use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Serializer\ToslaPosSerializer; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\ToslaPosRequestDataMapperTest; use PHPUnit\Framework\TestCase; @@ -42,11 +43,12 @@ public function testSupports(): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $data, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, $expected): void { - $result = $this->serializer->encode($data); + $result = $this->serializer->encode($data, null, $format); - $this->assertSame($expected, $result); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } @@ -64,8 +66,18 @@ public static function encodeDataProvider(): array { return [ [ - 'input' => ToslaPosRequestDataMapperTest::paymentRegisterRequestDataProvider()[0]['expected'], - 'expected' => '{"clientId":"1000000494","apiUser":"POS_ENT_Test_001","callbackUrl":"https:\/\/domain.com\/success","orderId":"order222","amount":10025,"currency":949,"installmentCount":0,"rnd":"rand","timeSpan":"20231209214708","hash":"+XGO1qv+6W7nXZwSsYMaRrWXhi+99jffLvExGsFDodYyNadOG7OQKsygzly5ESDoNIS19oD2U+hSkVeT6UTAFA=="}', + 'input' => ToslaPosRequestDataMapperTest::paymentRegisterRequestDataProvider()[0]['expected'], + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_JSON, + 'expected' => '{"clientId":"1000000494","apiUser":"POS_ENT_Test_001","callbackUrl":"https:\/\/domain.com\/success","orderId":"order222","amount":10025,"currency":949,"installmentCount":0,"rnd":"rand","timeSpan":"20231209214708","hash":"+XGO1qv+6W7nXZwSsYMaRrWXhi+99jffLvExGsFDodYyNadOG7OQKsygzly5ESDoNIS19oD2U+hSkVeT6UTAFA=="}', + ], + [ + 'input' => [ + 'an' => 'ac', + ], + 'format' => SerializerInterface::FORMAT_JSON, + 'expected_format' => SerializerInterface::FORMAT_JSON, + 'expected' => '{"an":"ac"}', ], ]; } diff --git a/tests/Unit/Serializer/VakifKatilimPosSerializerTest.php b/tests/Unit/Serializer/VakifKatilimPosSerializerTest.php index 969c444d..353c6de4 100644 --- a/tests/Unit/Serializer/VakifKatilimPosSerializerTest.php +++ b/tests/Unit/Serializer/VakifKatilimPosSerializerTest.php @@ -9,6 +9,7 @@ use Generator; use Mews\Pos\Gateways\VakifKatilimPos; use Mews\Pos\PosInterface; +use Mews\Pos\Serializer\SerializerInterface; use Mews\Pos\Serializer\VakifKatilimPosSerializer; use Mews\Pos\Tests\Unit\DataMapper\RequestDataMapper\VakifKatilimPosRequestDataMapperTest; use PHPUnit\Framework\TestCase; @@ -37,22 +38,13 @@ public function testSupports(): void /** * @dataProvider encodeDataProvider */ - public function testEncode(array $input, string $expected): void + public function testEncode(array $data, ?string $format, string $expectedFormat, $expected): void { - $actual = $this->serializer->encode($input, PosInterface::TX_TYPE_PAY_AUTH); + $result = $this->serializer->encode($data, PosInterface::TX_TYPE_PAY_AUTH, $format); $expected = str_replace(["\r"], '', $expected); - $this->assertSame($expected, $actual); - } - - /** - * @dataProvider decodeHtmlDataProvider - */ - public function testDecodeHtml(string $input, array $expected): void - { - $actual = $this->serializer->decode($input, PosInterface::TX_TYPE_PAY_AUTH); - - $this->assertSame($expected, $actual); + $this->assertSame($expected, $result->getData()); + $this->assertSame($expectedFormat, $result->getFormat()); } /** @@ -75,67 +67,6 @@ public function testDecodeXML(string $input, string $txType, array $expected): v $this->assertSame($expected, $actual); } - public static function decodeHtmlDataProvider(): array - { - $vakifKatilimHTML = << - - - - - -
- - - - - - - - - - - -
- - - -HTML; - - return [ - '3d_auth_fail' => [ - 'html' => $vakifKatilimHTML, - 'expected' => [ - 'gateway' => 'https://localhost/VirtualPos/ThreeDModel/Fail', - 'form_inputs' => [ - 'ResponseCode' => 'CardNotEnrolled', - 'ResponseMessage' => 'Card 3D Secure kayitli degil.', - 'ProvisionNumber' => '', - 'MerchantOrderId' => '', - 'OrderId' => '0', - 'RRN' => '', - 'Stan' => '', - 'HashData' => '', - 'MD' => '', - ], - ], - ], - ]; - } - public static function decodeXmlDataProvider(): iterable { yield [ @@ -276,8 +207,7 @@ public static function decodeXmlDataProvider(): iterable 00 -A_WRAP - ; +A_WRAP; yield 'test_utf_16' => [ 'input' => $testUtf16, 'txType' => PosInterface::TX_TYPE_PAY_AUTH, @@ -433,9 +363,21 @@ public static function encodeDataProvider(): array { return [ [ - 'input' => VakifKatilimPosRequestDataMapperTest::create3DPaymentRequestDataDataProvider()[0]['expected'], - 'expected' => ' + 'input' => VakifKatilimPosRequestDataMapperTest::create3DPaymentRequestDataDataProvider()[0]['expected'], + 'format' => null, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' 1.0.0sFxxO809/N3Yif4p/js1UKFMRro=111111APIUSER01002020110828BC30http://localhost/finansbank-payfor/3d/response.phphttp://localhost/finansbank-payfor/3d/response.phpMD67YtBfBRTZ0XBKnAHi8c/A== +', + ], + [ + 'input' => [ + 'ac' => 'ds', + ], + 'format' => SerializerInterface::FORMAT_XML, + 'expected_format' => SerializerInterface::FORMAT_XML, + 'expected' => ' +ds ', ], ];