55using System . Collections . Generic ;
66using System . Linq ;
77using System . Net ;
8+ using System . Net . Http ;
9+ using System . Net . Http . Headers ;
810using System . Runtime . Serialization ;
911using System . Text ;
1012using System . Threading ;
@@ -815,6 +817,8 @@ public class StripeGateway : IRestGateway
815817 private string stripeAccount ;
816818 public ICredentials Credentials { get ; set ; }
817819 private string UserAgent { get ; set ; }
820+
821+ public HttpClient Client { get ; set ; }
818822
819823 public StripeGateway ( string apiKey , string publishableKey = null , string stripeAccount = null )
820824 {
@@ -823,92 +827,97 @@ public StripeGateway(string apiKey, string publishableKey = null, string stripeA
823827 this . stripeAccount = stripeAccount ;
824828 Credentials = new NetworkCredential ( apiKey , "" ) ;
825829 Timeout = TimeSpan . FromSeconds ( 60 ) ;
826- UserAgent = "servicestack .net stripe v1 " ;
830+ UserAgent = "ServiceStack.Stripe " ;
827831 Currency = Currencies . UnitedStatesDollar ;
832+ Client = new HttpClient ( new HttpClientHandler {
833+ Credentials = Credentials ,
834+ PreAuthenticate = true ,
835+ AutomaticDecompression = DecompressionMethods . GZip | DecompressionMethods . Deflate ,
836+ } , disposeHandler : true ) ;
828837 JsConfig . InitStatics ( ) ;
829-
830- //https://support.stripe.com/questions/how-do-i-upgrade-my-stripe-integration-from-tls-1-0-to-tls-1-2#dotnet
831- ServicePointManager . SecurityProtocol = SecurityProtocolType . Tls12 | SecurityProtocolType . Tls11 | SecurityProtocolType . Tls ;
832838 }
833839
834- protected virtual void InitRequest ( HttpWebRequest req , string method , string idempotencyKey )
840+ private HttpRequestMessage PrepareRequest ( string relativeUrl , string method , string requestBody , string idempotencyKey )
835841 {
836- req . Accept = MimeTypes . Json ;
837- req . Credentials = Credentials ;
842+ var url = BaseUrl . CombineWith ( relativeUrl ) ;
843+
844+ var httpReq = new HttpRequestMessage ( new HttpMethod ( method ) , url ) ;
838845
839- if ( method == HttpMethods . Post || method == HttpMethods . Put )
840- req . ContentType = MimeTypes . FormUrlEncoded ;
846+ httpReq . Headers . UserAgent . Add ( new ProductInfoHeaderValue ( UserAgent , Env . VersionString ) ) ;
847+ httpReq . Headers . Add ( HttpHeaders . Accept , MimeTypes . Json ) ;
841848
842849 if ( ! string . IsNullOrWhiteSpace ( idempotencyKey ) )
843- req . Headers [ "Idempotency-Key" ] = idempotencyKey ;
850+ httpReq . Headers . Add ( "Idempotency-Key" , idempotencyKey ) ;
844851
845- req . Headers [ "Stripe-Version" ] = APIVersion ;
852+ httpReq . Headers . Add ( "Stripe-Version" , APIVersion ) ;
846853
847- if ( ! string . IsNullOrWhiteSpace ( stripeAccount ) )
854+ if ( requestBody != null )
848855 {
849- req . Headers [ "Stripe-Account" ] = stripeAccount ;
856+ httpReq . Content = new StringContent ( requestBody , Encoding . UTF8 ) ;
857+ if ( method is HttpMethods . Post or HttpMethods . Put )
858+ httpReq . Content ! . Headers . ContentType = new MediaTypeHeaderValue ( MimeTypes . FormUrlEncoded ) ;
850859 }
851860
852- PclExport . Instance . Config ( req ,
853- userAgent : UserAgent ,
854- timeout : Timeout ,
855- preAuthenticate : true ) ;
861+ return httpReq ;
856862 }
857863
858- protected virtual void HandleStripeException ( WebException ex )
864+ private Exception CreateException ( HttpResponseMessage httpRes )
859865 {
860- string errorBody = ex . GetResponseBody ( ) ;
861- var errorStatus = ex . GetStatus ( ) ?? HttpStatusCode . BadRequest ;
866+ #if NET6_0_OR_GREATER
867+ return new HttpRequestException ( httpRes . ReasonPhrase , null , httpRes . StatusCode ) ;
868+ #else
869+ return new HttpRequestException ( httpRes . ReasonPhrase ) ;
870+ #endif
871+ }
862872
863- if ( ex . IsAny400 ( ) )
873+ protected virtual string Send ( string relativeUrl , string method , string requestBody , string idempotencyKey )
874+ {
875+ var httpReq = PrepareRequest ( relativeUrl , method , requestBody , idempotencyKey ) ;
876+
877+ #if NET6_0_OR_GREATER
878+ var httpRes = Client . Send ( httpReq ) ;
879+ var responseBody = httpRes . Content . ReadAsStream ( ) . ReadToEnd ( Encoding . UTF8 ) ;
880+ #else
881+ var httpRes = Client . SendAsync ( httpReq ) . GetAwaiter ( ) . GetResult ( ) ;
882+ var responseBody = httpRes . Content . ReadAsStreamAsync ( ) . GetAwaiter ( ) . GetResult ( ) . ReadToEnd ( Encoding . UTF8 ) ;
883+ #endif
884+
885+ if ( httpRes . IsSuccessStatusCode )
886+ return responseBody ;
887+
888+ if ( httpRes . StatusCode is >= HttpStatusCode . BadRequest and < HttpStatusCode . InternalServerError )
864889 {
865- var result = errorBody . FromJson < StripeErrors > ( ) ;
890+ var result = responseBody . FromJson < StripeErrors > ( ) ;
866891 throw new StripeException ( result . Error )
867892 {
868- StatusCode = errorStatus
893+ StatusCode = httpRes . StatusCode
869894 } ;
870895 }
896+
897+ httpRes . EnsureSuccessStatusCode ( ) ;
898+ throw CreateException ( httpRes ) ; // should never reach here
871899 }
872900
873- protected virtual string Send ( string relativeUrl , string method , string body , string idempotencyKey )
901+ protected virtual async Task < string > SendAsync ( string relativeUrl , string method , string requestBody , string idempotencyKey , CancellationToken token = default )
874902 {
875- try
876- {
877- var url = BaseUrl . CombineWith ( relativeUrl ) ;
878- var response = url . SendStringToUrl ( method : method , requestBody : body , requestFilter : req =>
879- {
880- InitRequest ( req , method , idempotencyKey ) ;
881- } ) ;
882-
883- return response ;
884- }
885- catch ( WebException ex )
886- {
887- HandleStripeException ( ex ) ;
903+ var httpReq = PrepareRequest ( relativeUrl , method , requestBody , idempotencyKey ) ;
888904
889- throw ;
890- }
891- }
905+ var httpRes = await Client . SendAsync ( httpReq , token ) . ConfigAwait ( ) ;
906+ var responseBody = await ( await httpRes . Content . ReadAsStreamAsync ( ) ) . ReadToEndAsync ( Encoding . UTF8 ) . ConfigAwait ( ) ;
907+ if ( httpRes . IsSuccessStatusCode )
908+ return responseBody ;
892909
893- protected virtual async Task < string > SendAsync ( string relativeUrl , string method , string body , string idempotencyKey , CancellationToken token = default )
894- {
895- try
910+ if ( httpRes . StatusCode is >= HttpStatusCode . BadRequest and < HttpStatusCode . InternalServerError )
896911 {
897- var url = BaseUrl . CombineWith ( relativeUrl ) ;
898- var response = await url . SendStringToUrlAsync ( method : method , requestBody : body , requestFilter : req =>
912+ var result = responseBody . FromJson < StripeErrors > ( ) ;
913+ throw new StripeException ( result . Error )
899914 {
900- InitRequest ( req , method , idempotencyKey ) ;
901- } ) ;
902-
903- return response ;
915+ StatusCode = httpRes . StatusCode
916+ } ;
904917 }
905- catch ( Exception ex )
906- {
907- if ( ex . UnwrapIfSingleException ( ) is WebException webEx )
908- HandleStripeException ( webEx ) ;
909918
910- throw ;
911- }
919+ httpRes . EnsureSuccessStatusCode ( ) ;
920+ throw CreateException ( httpRes ) ; // should never reach here
912921 }
913922
914923 public class ConfigScope : IDisposable
0 commit comments