- ABP Framework version: v7.4.0
- UI Type: Angular
- Database System: MongoDB
- Tiered (for MVC) or Auth Server Separated (for Angular): yes
- Exception message and full stack trace: Stripe payment gateway, payment request with parameter "success_url": "https://{{tenantName}}.is.clienteleapp.net/Payment/Stripe/PostPayment?SessionId={CHECKOUT_SESSION_ID}" And "cancel_url": "https://{{tenantName}}.is.clienteleapp.net" gives error "The success_url parameter must correspond to a valid URL."
- Steps to reproduce the issue: We have added the stripe payment module, we are using tenant specific url for both angular and identity server, in appsettings of Identity project self url is configured as "SelfUrl": "https://{{tenantName}}.is.clienteleapp.net". We expect the tenant name should be resolved at the time of PrePayment and PostPayment method of Stripe payment module but it's not resolving the tenant name and causing the error when trying to process payment with stripe payment module.
20 Answer(s)
-
0
Hi,
I will check it
-
0
Hi,
This looks like a bug. I will fix it and provide you with a temporary solution.
-
0
Hi,
You can try to overwrite the page: https://docs.abp.io/en/abp/latest/UI/AspNetCore/Customization-User-Interface
public class UrlHelper : ITransientDependency { private readonly ICurrentTenant _currentTenant; public UrlHelper(ICurrentTenant currentTenant) { _currentTenant = currentTenant; } public const string TenantNamePlaceHolder = "{{tenantName}}"; public string ReplaceTenantPlaceholder(string url) { var tenantNamePlaceHolder = TenantNamePlaceHolder; if (url.Contains(TenantNamePlaceHolder + '.')) { tenantNamePlaceHolder = TenantNamePlaceHolder + '.'; } if (url.Contains(tenantNamePlaceHolder)) { url = _currentTenant.Id.HasValue ? url.Replace(tenantNamePlaceHolder, _currentTenant.Name + ".") : url.Replace(tenantNamePlaceHolder, ""); } return url; } }
Pages/Payment/GatewaySelection.cshtml
@page @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Payment.Localization @model Volo.Payment.Pages.Payment.MyGatewaySelectionModel @inject IHtmlLocalizer<PaymentResource> Localizer @section scripts { <abp-script-bundle> <abp-script src="/client-proxies/payment-proxy.js" /> <abp-script src="/Pages/Payment/gateway-selection.js" /> </abp-script-bundle> } <div class="container"> <div class="row"> <div class="col-md-7 mx-auto"> <div class="card"> <div class="card-header"> <h4 class="m-0 text-center">Select a Payment Gateway</h4> </div> <div class="card-body"> <form id="frmGatewaySelection" method="post" action=""> @Html.AntiForgeryToken() <div class="row"> @for (int gatewayIndex = 0; gatewayIndex < Model.Gateways.Count; gatewayIndex++) { var gateway = Model.Gateways[gatewayIndex]; <div class="col"> <div class="form-check"> <input type="hidden" id="@($"{@gateway.Name}PrePaymentUrl")" value="@(Model.UrlHelper.ReplaceTenantPlaceholder(gateway.PrePaymentUrl))?paymentRequestId=@Model.PaymentRequestId"/> <input type="radio" name="gateway" class="form-check-input" checked="@(gatewayIndex == 0)" value="@gateway.Name" id="@gateway.Name"> <label for="@gateway.Name" class="form-check-label"> <strong>@Localizer["PayWithGateway", Localizer[gateway.Name]]</strong> @if (gateway.Recommended) { <small class="text-muted">(Recommended)</small> } </label> @if (gateway.ExtraInfos.Any()) { <div class="payment-info-boxes"> @foreach (var extraInfo in gateway.ExtraInfos) { <p class="mt-1 mb-0 text-muted"> <small class="d-block"><i class="fa fa-info-circle"></i> @Html.Raw(extraInfo)</small> </p> } </div> } </div> </div> <input type="hidden" name="paymentRequestId" value="@Model.PaymentRequestId" /> } </div> </form> </div> <div class="card-body"> <div class="d-grid gap-2"> <a id="btnSubmit" href="#" class="btn btn btn-success @Model.CheckoutButtonStyle">Continue to Checkout <i class="fas fa-arrow-right"></i></a> </div> <p class="mt-2 mb-1 text-muted text-center"> <small> <i class="fa fa-info-circle"></i> Next, you will be redirected to the selected payment gateway's website for the transaction </small> </p> </div> </div> </div> </div> </div>
[ExposeServices(typeof(GatewaySelectionModel))] public class MyGatewaySelectionModel : GatewaySelectionModel { private readonly IOptions<PaymentWebOptions> _paymentWebOptions; private readonly IGatewayAppService _gatewayAppService; private readonly IPaymentRequestAppService _paymentRequestAppService; public UrlHelper UrlHelper { get; set; } public MyGatewaySelectionModel( IPaymentRequestAppService paymentRequestAppService, IOptions<PaymentWebOptions> paymentWebOptions, IGatewayAppService gatewayAppService) : base(paymentRequestAppService, paymentWebOptions, gatewayAppService) { _paymentWebOptions = paymentWebOptions; _gatewayAppService = gatewayAppService; _paymentRequestAppService = paymentRequestAppService; } public override async Task<IActionResult> OnPostAsync() { CheckoutButtonStyle = _paymentWebOptions.Value.GatewaySelectionCheckoutButtonStyle; var paymentRequest = await _paymentRequestAppService.GetAsync(PaymentRequestId); List<GatewayDto> gatewaysDtos; if (paymentRequest.Products.Any(a => a.PaymentType == PaymentType.Subscription)) { gatewaysDtos = await _gatewayAppService.GetSubscriptionSupportedGatewaysAsync(); } else { gatewaysDtos = await _gatewayAppService.GetGatewayConfigurationAsync(); } Gateways = _paymentWebOptions.Value.Gateways .Where(x => gatewaysDtos.Any(a => a.Name == x.Key)) .Select(x => x.Value) .ToList(); if (!Gateways.Any()) { throw new ApplicationException("No payment gateway configured!"); } if (Gateways.Count == 1) { var gateway = Gateways.First(); return LocalRedirectPreserveMethod(UrlHelper.ReplaceTenantPlaceholder((gateway.PrePaymentUrl) + "?paymentRequestId=" + PaymentRequestId)); } return Page(); } }
[ExposeServices(typeof(PostPaymentModel))] public class MyPostPaymentModel : PostPaymentModel { public UrlHelper UrlHelper { get; set; } private IOptions<PaymentWebOptions> _paymentWebOptions; public MyPostPaymentModel(IPaymentRequestAppService paymentRequestAppService, IOptions<PaymentWebOptions> paymentWebOptions) : base(paymentRequestAppService, paymentWebOptions) { _paymentWebOptions = paymentWebOptions; } public override async Task<IActionResult> OnGetAsync() { if (SessionId.IsNullOrWhiteSpace()) { return BadRequest(); } var paymentRequest = await PaymentRequestAppService.CompleteAsync( StripeConsts.GatewayName, new() { { StripeConsts.ParameterNames.SessionId, SessionId }, }); if (!_paymentWebOptions.Value.CallbackUrl.IsNullOrWhiteSpace()) { var callbackUrl = UrlHelper.ReplaceTenantPlaceholder(_paymentWebOptions.Value.CallbackUrl + "?paymentRequestId=" + paymentRequest.Id); Response.Redirect(callbackUrl); } return Page(); } }
-
0
Hi liangshiwei,
Thanks for response
We had configured solutions you provided and override page and page model but we still face issue of tenant resolving
please look below screen that we have tried locally and on productions
Also when trying with debugging we found this with ReplaceTenantPlaceholder() method in UrlHelper class
In this both url.contains condition goes false,so url will remain as is
-
0
Hi,
I'm checking
-
0
Hi,
Will it work if you try this?
[ExposeServices(typeof(PrePaymentModel))] public class MyPrePaymentModel: PrePaymentModel { public override async Task OnPostAsync() { StartResult = await PaymentRequestAppService.StartAsync(StripeConsts.GatewayName, new PaymentRequestStartDto { ReturnUrl = UrlHelper.ReplaceTenantPlaceholder(PaymentWebOptions.RootUrl.RemovePostFix("/") + StripeConsts.PostPaymentUrl + "?SessionId={CHECKOUT_SESSION_ID}"), CancelUrl = UrlHelper.ReplaceTenantPlaceholder(PaymentWebOptions.RootUrl), PaymentRequestId = PaymentRequestId }); PublishableKey = StartResult.ExtraProperties[StripeConsts.ParameterNames.PublishableKey].ToString(); SessionId = StartResult.ExtraProperties[StripeConsts.ParameterNames.SessionId].ToString(); } }
-
0
Hi,
While integrating we face this issue
The type 'StripeOptions' exists in both 'Volo.Payment.Stripe.Domain, Version=7.4.0.0, Culture=neutral, PublicKeyToken=null' and 'Volo.Payment.Stripe.Web, Version=7.4.0.0, Culture=neutral, PublicKeyToken=null'
here our packages in identity server project
can you take a look?
Thanks in advance
-
0
Hi,
You can try:
using StripeOptions = Volo.Payment.Stripe.StripeOptions;
-
0
-
0
Hi,
Sorry, I realize that it is impossible to replace the
PrePaymentModel
, you can try this:[ExposeServices(typeof(IPaymentRequestAppService))] public class MyPaymentRequestAppService : PaymentRequestAppService { private readonly UrlHelper _urlHelper; public MyPaymentRequestAppService( IPaymentRequestRepository paymentRequestRepository, PaymentGatewayResolver paymentMethodResolver, IDistributedEventBus distributedEventBus, UrlHelper urlHelper) : base(paymentRequestRepository, paymentMethodResolver, distributedEventBus) { _urlHelper = urlHelper; } public override Task<PaymentRequestStartResultDto> StartAsync(string gateway, PaymentRequestStartDto inputDto) { inputDto.CancelUrl = _urlHelper.ReplaceTenantPlaceholder(inputDto.CancelUrl); inputDto.ReturnUrl = _urlHelper.ReplaceTenantPlaceholder(inputDto.ReturnUrl); return base.StartAsync(gateway, inputDto); } }
-
0
Hi,
Thanks for your response & Sorry for late reply due to weekends,
We have congifured this solution but no luck ,look below screen
also face same error
while running project locally there is no any break points trigger in MyPaymentRequestAppService.cs method
Solutions configured is on right class library or something i missed?
Please let me know
Thanks
-
0
Hi,
Solutions configured is on right class library or something i missed?
I'm not sure. could you use the suite to create a new project to reproduce the problem and share it with me? my email is shiwei.liang@volosoft.com I will check it asap.
-
0
Hi,
Ok i have asked for it and we will let you soon for that
Thanks
-
0
ok
-
0
Hi, we are in process of giving access to the repository we are working on, so you can check and give the proper solution.
-
0
Hi,
May I ask which branch of the repo I should check?
-
0
Hi, Please check in branch "521 SocialExternalLogin", we have separate identity server and the changes you suggested are all in that web application only.
-
0
-
0
Hi, Thanks for all your help, the issue has been fixed now.
-
0
:)