I would like to use an external Login provider such as Auth0. The current document https://docs.abp.io/en/commercial/latest/modules/identity/oauth-login seems to using Identity Server and not OpenID Connect, which is provided by default for new installations using ABP Suite.
Can you provide a link or directions to set that up for an Angular project? I am assuming that I would have to maintain roles and permissions in Auth0? or would that still be maintained in the Admin UI?
<br>
I am unable to deploy to Azure. I am using an Azure App Service for both the front and the back. Deploying the backend seems to working fine. I had to generate certificates in order to get it working after deployment. However when I try to login from the UI, I am getting a 400 error.
If I test the front end code locally, while having the backend pointed to the deployed in Azure web service, it works fine....
I noticed when I test locally, the url is in the form "/Account/Login?ReturnUrl=connect/authorize&response_type=code&client_id..."
However, deployed the deployed version has a url starting with "/connect/authorize&response_type=code&client_id"
Also it looks for the endpoint /getEnvConfig which needs to get redirected... as it only works with nginx, so I had to create a web.config and create rewrite rules to map to dynamic-env.json?
Here is my web.config for the frontend
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<customErrors mode="On"/>
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00"/>
<remove fileExtension=".woff" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
<rewrite>
<rules>
<rule name="Angular Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(getEnvConfig)" negate="true" />
</conditions>
<action type="Rewrite" url="/" redirectType="Found" />
</rule>
<rule name="getEnvConfig" enabled="true" patternSyntax="ExactMatch" stopProcessing="true">
<match url="getEnvConfig" />
<action type="Redirect" url="dynamic-env.json" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Hi @christophe.baille
You can't use
Volo.Payment.Web
andVolo.Payment.Stripe.Web
packages inside your Blazor WebAssembly. Web layers are only compatible with Blazor Server.Thank you for your answer, I'll plan to publish an article about making payments in Blazor UI.
I believe this would be very helpful. Thanks. If we had access to the source code, of course, this wouldn't be necessary. But as things stand, documentation is key.
Thanks that helped. It works now. I am now able to confirm a completed payment in the admin page.
When I create the SessionCreateOptions
object, I add the PaymentRequestId
to the Metadata dictionary.
Quick question, are the webhooks going to work? Or do I need to implement that separately? I believe that they should be included in the Volo.Payment.Stripe.HttpApi
nuget. However, when I test it from Stripe, I am getting a 404.
This is the full stack trace:
ystem.Collections.Generic.KeyNotFoundException: The given key 'PaymentRequestId' was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Volo.Payment.Stripe.StripePaymentGateway.IsValid(PaymentRequest paymentRequest, Dictionary`2 properties)
at Volo.Payment.Requests.PaymentRequestAppService.CompleteAsync(CompletePaymentRequestDto input)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
at ReferMe.Payments.StripePaymentService.CompletePayment(SessionDto completedPayment) in D:\_dev\ReferMe\src\ReferMe.Application\Payments\StripePaymentService.cs:line 62
This is how I am using it:
await _paymentRequestAppService.CompleteAsync(new CompletePaymentRequestDto()
{
Id = completedPayment.PaymentRequestId, GateWay = "stripe",
ExtraProperties = { { "SessionId", completedPayment.Id } }
});
the PaymentRequestId is what is returned from
var paymentRequest = await _paymentRequestAppService.CreateAsync(new PaymentRequestCreateDto()
{
Products = paymentRequestDto.Products
});
Also, I updated to the latest stripe nuget as it supports server-side redirects. When you create a stripe session it returns a URL in the response that you can redirect to. I thought this would be the simpler/better approach rather than integrating with stripe.js and having to do Javascript Interop.
I basically followed the method that I mentioned above, and everything works, however, when I try to complete the transaction by calling CompleteAsync on the PaymentRequestAppService it throws an exception
"System.Collections.Generic.KeyNotFoundException: The given key 'PaymentRequestId' was not present in the dictionary."
I am able to verify that the transaction has been completed in the stripe dashboard, however, I would like it to be updated on the admin page as well.
In my opinion, stating that the payment process is really simple when you haven't tried it, and your documentation is geared towards MVC, is not really helpful.
I am not able to get the Payment to succeed so I am not sure how CallbackUrl
in PaymentWebOptions
would be helpful. The PaymentWebOptions
is also geared towards an MVC application.
It would be very helpful if you could provide some sample code or update your documentation to include Blazor Server.
Actually, I do not really care about the other Gateways. I intend on only using Stripe. Can you provide an example of how this will be done to integrate it with ABP?
Otherwise, I will have to write out my own Stripe integration.
At a high level, It would seem that I would use IPaymentRequestAppService to create a PaymentRequest. Map the PaymentRequest to a Stripe LineItems Object. Create a session using the Session Service. Then pass that SessionId to IPaymentRequestAppService's CompleteAsync method.
One of the main reasons why I signed up for the Commercial version of ABP, is actually because of the payments module. I am a sole developer, it's not really worth it to upgrade to one of your higher plans that include the complete source code. The payment's module without proper Blazor support seems incomplete.