Can you share the screenshot of
list
page?I think you can only customize the
list
page to do this.
What do you mean by the List page? Which one?
I still have the following problem: I want to use a payment method type (Twint) that only works for one-time payments and not for subscriptions. But I need to be able to offer both.
This means that if a one-time payment is to be made, the PaymentMethodTypes
Twint should be added. And if it is a payment for a subscription, this should not be in the list, otherwise it will result in an error message:
Is there a solution for this or do we have to do without Twint?
By the way: When we add "card" to the list, then there is also an error, as “card” is added by default and therefore appears twice.
Ok, I found the solution for the "No such price" problem.
It is not the product ID but the price ID that must be stored as the external ID for the gateway.
I only saw this by chance on the picture in the documentation. But I probably wouldn't have figured it out otherwise, because in my understanding you link a subscription product from Stripe to a plan in ABP.
It would be great if you could add this information to the documentation to explain exactly WHAT the External ID must be. That is quite unclear.
We have now come a few steps further... One-time payment is working, but the subscription payment not.
Payment.razor.cs
private async Task AddOneTimePaymentAsync()
{
try
{
var paymentRequest = await PaymentRequestAppService.CreateAsync(new PaymentRequestCreateDto()
{
Currency = "CHF",
Products = new List<PaymentRequestProductCreateDto>()
{
new PaymentRequestProductCreateDto
{
Code = "prod_QmPjjjJOhLTY6x",
Name = "Sperrfristenrechner Einzelabfrage",
Count = 1,
UnitPrice = 250,
TotalPrice = 250
}
}
});
await RedirectPreserveMethod($"/Payment/GatewaySelection?paymentRequestId={paymentRequest.Id}");
}
catch (Exception e)
{
Logger.LogError(e, e.Message);
}
}
private async Task AddSubscriptionPaymentAsync(string testEditionId)
{
try
{
// Prefered method (not working)
//var paymentRequest = await SubscriptionAppService.CreateSubscriptionAsync(testEditionId, tenantId);
// Code from documentation (not working)
var paymentRequest = await PaymentRequestAppService.CreateAsync(new PaymentRequestCreateDto()
{
Currency = "CHF",
Products = new List<PaymentRequestProductCreateDto>()
{
new PaymentRequestProductCreateDto
{
PaymentType = PaymentType.Subscription,
Name = "Jahresabo Light",
Code = "",
Count = 1,
PlanId = new Guid("9C404C8E-6CDF-A540-8BE2-3A14CA8412FE"),
}
}
});
await RedirectPreserveMethod($"/Payment/GatewaySelection?paymentRequestId={paymentRequest.Id}");
}
catch (Exception e)
{
Logger.LogError(e, e.Message);
}
}
private async Task RedirectPreserveMethod(string uri)
{
await JSRuntime.InvokeVoidAsync("eval", $"document.getElementById('Form').action = '{uri}'; document.getElementById('Form').submit()");
}
One-Time Payment seems to be working:
Subscription Payment not working:
StripeException: No such price: 'prod_QmPea3rNNFRqW4'
Stripe.StripeClient.ProcessResponse<T>(StripeResponse response) in StripeClient.cs
Stripe.StripeClient.RequestAsync<T>(HttpMethod method, string path, BaseOptions options, RequestOptions requestOptions, CancellationToken cancellationToken) in StripeClient.cs
Stripe.Service<TEntityReturned>.RequestAsync<T>(HttpMethod method, string path, BaseOptions options, RequestOptions requestOptions, CancellationToken cancellationToken) in Service.cs
Volo.Payment.Stripe.StripePaymentGateway.StartAsync(PaymentRequest paymentRequest, PaymentRequestStartInput input)
Volo.Payment.Requests.PaymentRequestAppService.StartAsync(string gateway, PaymentRequestStartDto inputDto)
Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo)
Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue<TResult>.ProceedAsync()
Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter<TInterceptor>.InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo)
Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue<TResult>.ProceedAsync()
Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter<TInterceptor>.InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo)
Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue<TResult>.ProceedAsync()
Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter<TInterceptor>.InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo)
Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue<TResult>.ProceedAsync()
Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter<TInterceptor>.InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
Volo.Payment.Stripe.Pages.Payment.Stripe.PrePaymentModel.OnPostAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory+NonGenericTaskHandlerMethod.Execute(object receiver, object[] arguments)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Volo.Abp.AspNetCore.Security.Claims.AbpDynamicClaimsMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Volo.Abp.AspNetCore.Uow.AbpUnitOfWorkMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Volo.Abp.AspNetCore.MultiTenancy.MultiTenancyMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Microsoft.AspNetCore.Builder.ApplicationBuilderAbpOpenIddictMiddlewareExtension+<>c__DisplayClass0_0+<<UseAbpOpenIddictValidation>b__0>d.MoveNext()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Volo.Abp.AspNetCore.Security.AbpSecurityHeadersMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Volo.Abp.AspNetCore.Tracing.AbpCorrelationIdMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+InterfaceMiddlewareBinder+<>c__DisplayClass2_0+<<CreateMiddleware>b__0>d.MoveNext()
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
We would like to use the payment module under Blazor Server. We would currently do this with Stripe as provider. In the end, a tenant should be able to buy a subscription and thus activate services on our platform.
We have studied the documentation, but it leaves some questions unanswered, especially in relation to Blazor. Much is still very unclear and is like a trial and error process to implement this.
Code
property in the PaymentRequestProduct
correspond to the Product-ID in Stripe?There will probably be a few more questions, but this is for now.
Thanks, Adrian
For the template it would be cool if you would provide the KeyPrefix for the cache configurable. I use the same cache for different deployments of the application (testing, production, ...). And then of course I would like to use different KeyPrefixes.
I have added this to my code as follows:
Configuration of service:
private void ConfigureCache(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options =>
{
options.KeyPrefix = configuration["Redis:KeyPrefix"] ?? "MyApp:";
});
}
appsettings.json (for development):
"Redis": {
"IsEnabled": "true",
"Configuration": "127.0.0.1",
"KeyPrefix": "MyApp:Development:"
},
I hope this gets fixed in the next Release Candidate because old personal license holders lost many features and this I guess It goes against many terms and conditions. In the last ABP Community was answered a question I did to Halil Ibrahim Kalkan and He compromised we will get these features (if not in ABP Suite but in ABP Studio). I sent an email asking for confirmation but didn't get one. Sincerely, I hope these changes they are doing to their license configuration don't affect us.
As I understand it, you now have to do this via the studio. And as I heard in the last Community Talk, "old" license holders still have the same options as before.
In any case, I can still create solutions via Studio. Have you tried it yet?
I have installed ABP Studio for the first time and wanted to add an existing solution. Nothing is displayed in the Solution Runner. Do I have to add the individual projects myself or should they be displayed automatically?
And is there a possibility to show the application logs in the Studio? I mean, for example, the log file of the Blazor app.
Ok, I now know that as soon as you set PageLayout.MenuItemName
, you have to remove it yourself. Otherwise the value remains until it is overwritten...
This should be mentioned in the documentation, it is quite error-prone... Or even better, rethink this concept...
I have now solved this in my page:
protected override async Task OnInitializedAsync()
{
if (TerminationId != Guid.Empty)
{
PageLayout.MenuItemName = "None";
}
}
protected override void Dispose(bool disposing)
{
PageLayout.MenuItemName = null;
base.Dispose(disposing);
}