@@ -4,7 +4,7 @@ use std::sync::LazyLock;
4
4
5
5
use common_utils:: {
6
6
errors:: CustomResult ,
7
- ext_traits:: BytesExt ,
7
+ ext_traits:: { BytesExt , XmlExt } ,
8
8
request:: { Method , Request , RequestBuilder , RequestContent } ,
9
9
types:: { AmountConvertor , StringMinorUnit , StringMinorUnitForConnector } ,
10
10
} ;
@@ -29,7 +29,7 @@ use hyperswitch_domain_models::{
29
29
types:: {
30
30
PaymentsAuthorizeRouterData , PaymentsCancelRouterData , PaymentsCaptureRouterData ,
31
31
PaymentsCompleteAuthorizeRouterData , PaymentsPreProcessingRouterData ,
32
- RefundExecuteRouterData ,
32
+ PaymentsSyncRouterData , RefundExecuteRouterData , RefundSyncRouterData ,
33
33
} ,
34
34
} ;
35
35
use hyperswitch_interfaces:: {
@@ -42,13 +42,14 @@ use hyperswitch_interfaces::{
42
42
events:: connector_api_logs:: ConnectorEvent ,
43
43
types:: {
44
44
PaymentsAuthorizeType , PaymentsCaptureType , PaymentsCompleteAuthorizeType ,
45
- PaymentsPreProcessingType , PaymentsVoidType , RefundExecuteType , Response ,
45
+ PaymentsPreProcessingType , PaymentsSyncType , PaymentsVoidType , RefundExecuteType ,
46
+ RefundSyncType , Response ,
46
47
} ,
47
48
webhooks,
48
49
} ;
49
50
use transformers as redsys;
50
51
51
- use crate :: { types:: ResponseRouterData , utils as connector_utils} ;
52
+ use crate :: { constants :: headers , types:: ResponseRouterData , utils as connector_utils} ;
52
53
53
54
#[ derive( Clone ) ]
54
55
pub struct Redsys {
@@ -78,11 +79,6 @@ impl api::PaymentToken for Redsys {}
78
79
impl api:: PaymentsPreProcessing for Redsys { }
79
80
impl api:: PaymentsCompleteAuthorize for Redsys { }
80
81
81
- impl < Flow , Request , Response > ConnectorCommonExt < Flow , Request , Response > for Redsys where
82
- Self : ConnectorIntegration < Flow , Request , Response >
83
- {
84
- }
85
-
86
82
impl ConnectorCommon for Redsys {
87
83
fn id ( & self ) -> & ' static str {
88
84
"redsys"
@@ -143,6 +139,29 @@ impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsRespons
143
139
}
144
140
}
145
141
142
+ impl < Flow , Request , Response > ConnectorCommonExt < Flow , Request , Response > for Redsys
143
+ where
144
+ Self : ConnectorIntegration < Flow , Request , Response > ,
145
+ {
146
+ fn build_headers (
147
+ & self ,
148
+ _req : & RouterData < Flow , Request , Response > ,
149
+ _connectors : & Connectors ,
150
+ ) -> CustomResult < Vec < ( String , masking:: Maskable < String > ) > , errors:: ConnectorError > {
151
+ let headers = vec ! [
152
+ (
153
+ headers:: CONTENT_TYPE . to_string( ) ,
154
+ "application/xml" . to_string( ) . into( ) ,
155
+ ) ,
156
+ (
157
+ headers:: SOAP_ACTION . to_string( ) ,
158
+ redsys:: REDSYS_SOAP_ACTION . to_string( ) . into( ) ,
159
+ ) ,
160
+ ] ;
161
+ Ok ( headers)
162
+ }
163
+ }
164
+
146
165
impl ConnectorIntegration < PreProcessing , PaymentsPreProcessingData , PaymentsResponseData >
147
166
for Redsys
148
167
{
@@ -621,9 +640,159 @@ impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Redsys
621
640
}
622
641
}
623
642
624
- impl ConnectorIntegration < PSync , PaymentsSyncData , PaymentsResponseData > for Redsys { }
643
+ impl ConnectorIntegration < PSync , PaymentsSyncData , PaymentsResponseData > for Redsys {
644
+ fn get_headers (
645
+ & self ,
646
+ req : & PaymentsSyncRouterData ,
647
+ connectors : & Connectors ,
648
+ ) -> CustomResult < Vec < ( String , masking:: Maskable < String > ) > , errors:: ConnectorError > {
649
+ self . build_headers ( req, connectors)
650
+ }
651
+
652
+ fn get_url (
653
+ & self ,
654
+ _req : & PaymentsSyncRouterData ,
655
+ connectors : & Connectors ,
656
+ ) -> CustomResult < String , errors:: ConnectorError > {
657
+ Ok ( format ! (
658
+ "{}/apl02/services/SerClsWSConsulta" ,
659
+ self . base_url( connectors)
660
+ ) )
661
+ }
662
+
663
+ fn get_content_type ( & self ) -> & ' static str {
664
+ self . common_get_content_type ( )
665
+ }
666
+
667
+ fn get_request_body (
668
+ & self ,
669
+ req : & PaymentsSyncRouterData ,
670
+ _connectors : & Connectors ,
671
+ ) -> CustomResult < RequestContent , errors:: ConnectorError > {
672
+ let connector_req = redsys:: build_payment_sync_request ( req) ?;
673
+ Ok ( RequestContent :: RawBytes ( connector_req) )
674
+ }
675
+
676
+ fn build_request (
677
+ & self ,
678
+ req : & PaymentsSyncRouterData ,
679
+ connectors : & Connectors ,
680
+ ) -> CustomResult < Option < Request > , errors:: ConnectorError > {
681
+ Ok ( Some (
682
+ RequestBuilder :: new ( )
683
+ . method ( Method :: Post )
684
+ . url ( & PaymentsSyncType :: get_url ( self , req, connectors) ?)
685
+ . attach_default_headers ( )
686
+ . headers ( PaymentsSyncType :: get_headers ( self , req, connectors) ?)
687
+ . set_body ( self . get_request_body ( req, connectors) ?)
688
+ . build ( ) ,
689
+ ) )
690
+ }
691
+ fn handle_response (
692
+ & self ,
693
+ data : & PaymentsSyncRouterData ,
694
+ event_builder : Option < & mut ConnectorEvent > ,
695
+ res : Response ,
696
+ ) -> CustomResult < PaymentsSyncRouterData , errors:: ConnectorError > {
697
+ let response = String :: from_utf8 ( res. response . to_vec ( ) )
698
+ . change_context ( errors:: ConnectorError :: ResponseDeserializationFailed ) ?;
699
+ let response_data = html_escape:: decode_html_entities ( & response) . to_ascii_lowercase ( ) ;
700
+ let response = response_data
701
+ . parse_xml :: < redsys:: RedsysSyncResponse > ( )
702
+ . change_context ( errors:: ConnectorError :: ResponseDeserializationFailed ) ?;
703
+
704
+ event_builder. map ( |i| i. set_response_body ( & response) ) ;
705
+ router_env:: logger:: info!( connector_response=?response) ;
706
+ RouterData :: try_from ( ResponseRouterData {
707
+ response,
708
+ data : data. clone ( ) ,
709
+ http_code : res. status_code ,
710
+ } )
711
+ }
712
+ fn get_error_response (
713
+ & self ,
714
+ res : Response ,
715
+ event_builder : Option < & mut ConnectorEvent > ,
716
+ ) -> CustomResult < ErrorResponse , errors:: ConnectorError > {
717
+ self . build_error_response ( res, event_builder)
718
+ }
719
+ }
720
+
721
+ impl ConnectorIntegration < RSync , RefundsData , RefundsResponseData > for Redsys {
722
+ fn get_headers (
723
+ & self ,
724
+ req : & RefundSyncRouterData ,
725
+ connectors : & Connectors ,
726
+ ) -> CustomResult < Vec < ( String , masking:: Maskable < String > ) > , errors:: ConnectorError > {
727
+ self . build_headers ( req, connectors)
728
+ }
729
+ fn get_content_type ( & self ) -> & ' static str {
730
+ self . common_get_content_type ( )
731
+ }
732
+ fn get_url (
733
+ & self ,
734
+ _req : & RefundSyncRouterData ,
735
+ connectors : & Connectors ,
736
+ ) -> CustomResult < String , errors:: ConnectorError > {
737
+ Ok ( format ! (
738
+ "{}/apl02/services/SerClsWSConsulta" ,
739
+ self . base_url( connectors)
740
+ ) )
741
+ }
742
+
743
+ fn get_request_body (
744
+ & self ,
745
+ req : & RefundSyncRouterData ,
746
+ _connectors : & Connectors ,
747
+ ) -> CustomResult < RequestContent , errors:: ConnectorError > {
748
+ let connector_req = redsys:: build_refund_sync_request ( req) ?;
749
+ Ok ( RequestContent :: RawBytes ( connector_req) )
750
+ }
751
+
752
+ fn build_request (
753
+ & self ,
754
+ req : & RefundSyncRouterData ,
755
+ connectors : & Connectors ,
756
+ ) -> CustomResult < Option < Request > , errors:: ConnectorError > {
757
+ Ok ( Some (
758
+ RequestBuilder :: new ( )
759
+ . method ( Method :: Post )
760
+ . url ( & RefundSyncType :: get_url ( self , req, connectors) ?)
761
+ . attach_default_headers ( )
762
+ . headers ( RefundSyncType :: get_headers ( self , req, connectors) ?)
763
+ . set_body ( self . get_request_body ( req, connectors) ?)
764
+ . build ( ) ,
765
+ ) )
766
+ }
767
+ fn handle_response (
768
+ & self ,
769
+ data : & RefundSyncRouterData ,
770
+ event_builder : Option < & mut ConnectorEvent > ,
771
+ res : Response ,
772
+ ) -> CustomResult < RefundSyncRouterData , errors:: ConnectorError > {
773
+ let response = String :: from_utf8 ( res. response . to_vec ( ) )
774
+ . change_context ( errors:: ConnectorError :: ResponseDeserializationFailed ) ?;
775
+ let response_data = html_escape:: decode_html_entities ( & response) . to_ascii_lowercase ( ) ;
776
+ let response = response_data
777
+ . parse_xml :: < redsys:: RedsysSyncResponse > ( )
778
+ . change_context ( errors:: ConnectorError :: ResponseDeserializationFailed ) ?;
625
779
626
- impl ConnectorIntegration < RSync , RefundsData , RefundsResponseData > for Redsys { }
780
+ event_builder. map ( |i| i. set_response_body ( & response) ) ;
781
+ router_env:: logger:: info!( connector_response=?response) ;
782
+ RouterData :: try_from ( ResponseRouterData {
783
+ response,
784
+ data : data. clone ( ) ,
785
+ http_code : res. status_code ,
786
+ } )
787
+ }
788
+ fn get_error_response (
789
+ & self ,
790
+ res : Response ,
791
+ event_builder : Option < & mut ConnectorEvent > ,
792
+ ) -> CustomResult < ErrorResponse , errors:: ConnectorError > {
793
+ self . build_error_response ( res, event_builder)
794
+ }
795
+ }
627
796
628
797
impl ConnectorIntegration < PaymentMethodToken , PaymentMethodTokenizationData , PaymentsResponseData >
629
798
for Redsys
0 commit comments