I use 'AsyncCallbacks' to the server (Tomcat) to query a database for 'resultsets', which should be shown as the result of the 'SuggestOracle'.
My problem is that, while typing in the input field, several 'AsyncCallbacks' are fired, but they are not fired in the order as they are entered.
For example:
If I enter the string "user1" there should be 5 callbacks be fired off. Now look at the server log:
Dez 30, 2017 9:27:59 AM com.test.server.dispatch.actionhandlers.SuggestUsersActionHandler execute
INFORMATION: Giving suggestinos for query u searching for contacts of user 136141
Dez 30, 2017 9:27:59 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: suggesting ... with query:u
Dez 30, 2017 9:28:00 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: query resulted in: 4 elements
Dez 30, 2017 9:28:00 AM com.test.server.dispatch.ActionExecutor execute
INFORMATION: com.test.entities.User(Id: 136141, Email: h#h.com) finished executing action com.test.services.dispatch.actions.SuggestUsersAction
Dez 30, 2017 9:28:01 AM com.test.server.dispatch.actionhandlers.SuggestUsersActionHandler execute
INFORMATION: Giving suggestinos for query user1 searching for contacts of user 136141
Dez 30, 2017 9:28:01 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: suggesting ... with query:user1
Dez 30, 2017 9:28:02 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: query resulted in: 1 elements
Dez 30, 2017 9:28:02 AM com.test.server.dispatch.ActionExecutor execute
INFORMATION: com.test.entities.User(Id: 136141, Email: h#h.com) finished executing action com.test.services.dispatch.actions.SuggestUsersAction
Dez 30, 2017 9:28:02 AM com.test.server.dispatch.actionhandlers.SuggestUsersActionHandler execute
INFORMATION: Giving suggestinos for query user searching for contacts of user 136141
Dez 30, 2017 9:28:02 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: suggesting ... with query:user
Dez 30, 2017 9:28:03 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: query resulted in: 4 elements
Dez 30, 2017 9:28:03 AM com.test.server.dispatch.ActionExecutor execute
INFORMATION: com.test.entities.User(Id: 136141, Email: h#h.com) finished executing action com.test.services.dispatch.actions.SuggestUsersAction
Dez 30, 2017 9:28:03 AM com.test.server.dispatch.actionhandlers.SuggestUsersActionHandler execute
INFORMATION: Giving suggestinos for query us searching for contacts of user 136141
Dez 30, 2017 9:28:03 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: suggesting ... with query:us
Dez 30, 2017 9:28:04 AM com.test.server.dao.UserDAO getSuggestions
INFORMATION: query resulted in: 4 elements
Dez 30, 2017 9:28:04 AM com.test.server.dispatch.ActionExecutor execute
INFORMATION: com.test.entities.User(Id: 136141, Email: h#h.com) finished executing action com.test.services.dispatch.actions.SuggestUsersAction
It first queries for "u" then for "user1" then for "user" then for "us" ..
so the requests are not sent in the right order.
Do you know any tip of how to send those async queries in the right order?
I fear that using 'AsyncCallbacks' in combination with 'SuggestOracles' are not a good idea.
You should never assume that asynchronous callbacks would be fired in any special order. There are many factors that can cause some calls to be delayed and thus the order can be random.
My favorite method is to just keep the last callback. Please, note, that while you are typing, let's say user1 you get 5 calls to the server, but you are only interested in the result for user1 results. Previous (like us, use etc.) can (or even should) be omitted.
So I've extended AsyncCallback to CancelableAsyncCallback:
public abstract class CancelableAsyncCallback<T> implements AsyncCallback<T> {
private boolean cancelled = false;
public void cancel() {
cancelled = true;
}
public boolean isCancelled() {
return cancelled;
}
}
I keep track of the last callback and cancel the unwanted previous results like this:
if(lastCallback != null)
lastCallback.cancel();
lastCallback = new CancelableAsyncCallback<Type>() {
#Override
public void onFailure(Throwable caught) {
if(!isCancelled()) {
// do the stuff
}
}
#Override
public void onSuccess(Type result) {
if(!isCancelled()) {
// do the stuff
}
}
};
Adams answer will probably work in a lot of situations. He is absolutely right that you can never assume AsyncCallbacks will be handled in any order that you expect.
I handle this in a slightly different way: in my response object, I also return the original query. I can then check to see if the response still applies to the state that the client application is now in.
This would be something like:
callback = new AsyncCallback<Type>() {
#Override
public void onFailure(Throwable caught) {
// handle error
}
#Override
public void onSuccess(Type result) {
String originalQuery = result.getOriginalQuery();
if (originalQuery.equals(oracleBox.getValue())) {
// handle return values
}
}
};
Related
I'm implementing the ClassyTaxiAppKotlin + ClassyTaxiServer project but without success.
I followed all the steps in the tutorial.
Apparently the ClassyTaxiAppKotlin android app is functional, processes the subscription purchase order and sends the information to the CLOUD FUNCTIONS, but does not receive the purchase registration/confirmation.
In my understanding, upon receiving the payment confirmation, PLAY STORE must send this confirmation to the ClassyTaxiServer server so that the server returns the registration/confirmation of the purchase and grants access to the ClassyTaxiAppKotlin application.
So when confirming payment in ClassyTaxiAppKotlin app, I notice that I get some logs in firebase functions from (instanceId_register_v2, realtime_notification_listener AND subscription_register_v2), but the registration/confirmation of payment doesn't complete due to a server error (500) and doesn't release the access in the ClassyTaxiAppKotlin app.
Note: service-account.json is already configured
Does anyone have any idea why this error is occurring and indicate how I can solve it?
Code where the error points:
private async querySubscriptionPurchaseWithTriggerV2(packageName: string, product: string, purchaseToken: string, triggerNotificationType?: NotificationType): Promise<SubscriptionPurchaseV2> {
// STEP 1. Query Play Developer API to verify the purchase token
const apiResponseV2 = await new Promise((resolve, reject) => {
this.playDeveloperApiClient.purchases.subscriptionsv2.get({ // <<=== Server error: Cannot read property 'get' of undefined
packageName: packageName,
token: purchaseToken
}, (err, result) => {
if (err) {
reject(this.convertPlayAPIErrorToLibraryError(err));
} else {
resolve(result.data);
}
})
});
LOGS Firebase Functions
6:55:28.798 PM instanceId_register_v2 Function execution started
6:55:31.025 PM instanceId_register_v2 Instance id is ddR1Hi...NOO2Z
6:55:31.122 PM instanceId_register_v2 Instance Id specified and verified
6:55:31.122 PM instanceId_register_v2 Instance verification passed
6:55:31.774 PM instanceId_register_v2 Function execution took 2976 ms, finished with status code: 200
6:55:53.623 PM realtime_notification_listener ========> purchase: null PACKAGE_NAME: com.example.subscriptions
6:55:53.624 PM realtime_notification_listener Function execution took 5 ms, finished with status: 'ok'
6:55:57.537 PM subscription_register_v2 Function execution started
6:55:59.817 PM subscription_register_v2 Server error: Cannot read property 'get' of undefined
6:55:59.825 PM subscription_register_v2 Function execution took 2289 ms, finished with status code: 500
LOGS Android Studio
D/OkHttp: --> PUT https://us-central1-postosgnv.cloudfunctions.net/subscription_register_v2 http/1.1 (437-byte body)
D/OkHttp: <-- 500 https://us-central1-postosgnv.cloudfunctions.net/subscription_register_v2 (2661ms, 86-byte body)
E/RemoteServerFunction: Failed to call API (Error code: 500) - {"status":500,"error":"not-found","message":"Cannot read property 'get' of undefined"}
As per the answer found HERE, the issue was solved by updating the GoogleApis package in the package.json from "googleapis": "^67.0.0" -> "googleapis": "105.0.0"
First encounter with RealtimeDatabse - My database structure looks like this:
I use this code to read the data:
Map<String, BookingItem> bookingMap={}; // Need to populate this
final db = FirebaseDatabase(databaseURL:"https:MYURL");
final fb = db.reference();
fb.child('1b***APkCeLs/Form Responses 1').once()
.then((DataSnapshot data) {
print(jsonEncode(data.value)); // Shows up fine
var encod = jsonEncode(data.value);
try { // Problem here
// Need some code help with getting the data into MAP format please
} on Exception catch(e) {
print ('Error: $e');
}
debugPrint(bookingList.toString());
}).catchError((onError){
if (kDebugMode) print (onError);
});
My booking item class is simple:
class BookingItem {
String email;
//String chooseYourBookingLocation;
BookingItem({required this.email});//, required this.chooseYourBookingLocation});
BookingItem.fromJson(Map<String, dynamic> json)
: //chooseYourBookingLocation = json['Choose your booking location'],
email = json['Email'];
}
I want - Fri Jul 09 2021 07:33:09 GMT+0100 (British Summer Time) as key and BookingItem object with sub-details as a value.
I want to just start by grabbing the email and then the rest in the next steps.
End goal is to have BookingItem Map with all the details so I can update field/fields later as well.
jsonEncode prints this on the screen
{"Fri Jul 09 2021 07:33:09 GMT+0100 (British Summer Time)":{"Additional Information":"","Email":"litl.com","First Name":"Laura","Choose your booking location":"Brentwood","Time":"13:00","Last Name":"Irving","Phone Number":"074","Number of Guests":5,"Timestamp":"2021-07-09T06:33:09.675Z","Date":"","Email Address":""},"Fri Jul 09 2021 10:51:06 GMT+0100 (British Summer Time)":{"Additional Information":"","Email":"sa***uk.com","First Name":"Sacha","Choose your booking location":"Brentwood","Time":"18:30","Last Name":"Leal","Phone Number":"07**4","Number of Guests":2,"Timestamp":"2021-07-09T09:51:06.939Z","Date":"","Email Address":""},"Fri Jul 09 2021 12:02:22 GMT+0100 (British Summer Time)":{"Additional Information":"","Email":"nic**om","First Name":"Nicola","Choose your booking location":"Hatfield","Time":"15:00","Last Name":"Coan","Phone Number":"07***4","Number of Guests":2,"Timestamp":"2021-07-09T11:02:22.663Z","Date":"","Email Address":""},"Fri Ju...
I just want to simply do the following to start with:
I'm trying to retrieve all the events programmed within a domain entreprise.tn using Google Calendar API.
On google admin console, I create a new project and a new service account with owner role as described by that thread.
I enabled Google Calendar API and Admin SDK like described by that thread.
the list of scopes added on Admin console>Security are :
https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group, https://www.googleapis.com/auth/admin.directory.resource.calendar, https://www.googleapis.com/auth/calendar.events.readonly, https://www.googleapis.com/auth/calendar.readonly
My code is:
Calendar service = getCalendarService();
List<Event> items = new ArrayList<Event>();
String pageToken = null;
do
{
Events events = service.events().list("service-account-esp1#my-first-project-274515.iam.gserviceaccount.com").setPageToken(pageToken).execute();
items = events.getItems();
for (Event event : items)
{
System.out.println(event.getSummary());
}
pageToken = events.getNextPageToken();
} while (pageToken != null);
if (items.isEmpty())
{
System.out.println("Empty");
}
else
{
System.out.println("Exists");
}
the file my-first-project-274515-361633451f1c.json is the generated file when creating the service account and performing G Suite Domain-Wide Delegation of Authority.
the service-account-esp1#my-first-project-274515.iam.gserviceaccount.com is the client email
It looks ok, all the required configurations are done.
How evere, I got that exception:
avr. 18, 2020 12:28:59 PM
com.google.api.client.util.store.FileDataStoreFactory
setPermissionsToOwnerOnly AVERTISSEMENT: Unable to set permissions for
C:\Users\Administrateur\credentials, because you are running on a
non-POSIX file system. Charge Calendars: Sat Apr 18 12:28:59 BST 2020
a Exception in thread "main" java.lang.IllegalArgumentException at
com.google.common.base.Preconditions.checkArgument(Preconditions.java:128)
at
com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:35)
at
com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.getDetails(GoogleClientSecrets.java:82)
at
com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow$Builder.(GoogleAuthorizationCodeFlow.java:197)
at
tn.esprit.spring.google.calendar.Service.getCredentials(Service.java:75)
at
tn.esprit.spring.google.calendar.Service.getCalendarService(Service.java:90)
at tn.esprit.spring.google.calendar.Service.main(Test.java:102)
it's blocked on GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();
Could you please tell me what I missed ?.
Thanks in advance.
You should use mail user instead:
Events events = service.events().list(user#entreprise.tn)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute();
HTH
I have the Following CouchBase Template Bean:
#PostConstruct
public void initIt() throws Exception {
if(couchbaseDisabled)
return;
couchbaseClient= new CouchbaseClient(
bootstrapUris(Arrays.asList(hosts.split(","))),
CouchbaseConstants.BUCKET,
""
);
couchbaseTemplate();
}
public void couchbaseTemplate() throws Exception {
logger.info("Enabling CouchBase Template");
couchbaseTemplate= new CouchbaseTemplate(couchbaseClient);
//couchbaseTemplate.
}
and
#PreDestroy
public void cleanup() throws Exception {
logger.info("Closing couchbase connection.");
if (couchbaseClient != null) {
couchbaseClient.shutdown();
couchbaseTemplate=null;
couchbaseClient=null;
}
}
While the Server is being Shut Down i am geting the Following Logs:
SEVERE: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#5ddaa15d]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#3c9810ce]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#23776376]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:24 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal#40c94525]) and a value of type [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap] (value [com.couchbase.client.deps.io.netty.util.internal.InternalThreadLocalMap#7322ea2a]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
Jan 8, 2016 4:57:32 PM org.apache.coyote.http11.Http11Protocol destroy
INFO: Stopping Coyote HTTP/1.1 on http-8099
What can be Done Here?
Ok so you have both SDK 1.4.x and 2.x running in your application (since you have com.couchbase.client:java-client in your pom).
The thread leak message comes from the later. You must have instantiated a Cluster somewhere (as in com.couchbase.client.java.Cluster).
Make sure to also clean it up at the end of the application's lifecycle by calling cluster.disconnect() (I guess from a #PreDestroy method, as you did for the CouchbaseClient).
If you also created a custom CouchbaseEnvironment, you have to also properly shut it down (in the same method as the Cluster cleanup) by calling environment.shutdownAsync().toBlocking().single().
Make sure to use the latest version of the 2.x SDK as some older versions had bugs relative to proper thread cleanup on shutdown (see JCBC-773 and JVMCBC-251 issues).
I want to use Authorize.net SIM payment method in Symfony using payum.org.
There is no official gateway for it but there is one in omnipay: omnipay-authorizenet. There is also omnipay-bridge in payum so it is possible to use omnipay gateways in payum.
So I use this setup and after submitting the authorize.net form I get the error:
[date] request.CRITICAL: Uncaught PHP Exception Omnipay\Common\Exception\InvalidRequestException: "Incorrect hash" at .../authorize/vendor/omnipay/authorizenet/src/Message/SIMCompleteAuthorizeRequest.php line 42 {"exception":"[object] (Omnipay\\Common\\Exception\\InvalidRequestException(code: 0): Incorrect hash at .../authorize/vendor/omnipay/authorizenet/src/Message/SIMCompleteAuthorizeRequest.php:42)"} []
BUT this is NOT because of the generated hashes being incorrect - it is because capture url is called second time without the POST data.
On a clean installation of Symfony2 with 3 packages:
composer.json:
"payum/payum-bundle": "0.15.*",
"omnipay/authorizenet": "~2.0",
"payum/omnipay-bridge": "*#stable"
config.yml:
payum:
security:
token_storage:
AppBundle\Entity\PaymentToken: { doctrine: orm }
storages:
AppBundle\Entity\Payment: { doctrine: orm }
gateways:
authorizeGateway:
omnipay_offsite:
type: AuthorizeNet_SIM
options:
hashSecret: 'Simon'
ApiLoginId: 'xxx'
transactionkey: 'xxx'
testMode: false
developerMode: true
Controller:
/**
* #Route("/prepare", name="prepare")
*/
public function prepareAction()
{
$gatewayName = 'authorizeGateway';
$storage = $this->get('payum')->getStorage('AppBundle\Entity\Payment');
$payment = $storage->create();
$payment->setNumber(uniqid());
$payment->setCurrencyCode('USD');
$payment->setTotalAmount(1);
$payment->setDescription('A description');
$payment->setClientId('anId');
$payment->setClientEmail('foo#example.com');
$storage->update($payment);
$captureToken = $this->get('payum.security.token_factory')->createCaptureToken(
$gatewayName,
$payment,
'done' // the route to redirect after capture
);
return $this->redirect($captureToken->getTargetUrl());
}
/**
* #Route("/done", name="done")
*/
public function doneAction(Request $request)
{
...
}
Going to /prepare shows a redirecting to authorize.net page for a second and I'm redirected to external test.authorize.net/gateway/transact.dll (on https) page where I specify card number (test card number) and expiration date in the future.
Submitting this form gives:
An error occurred while trying to report this transaction to the merchant. An e-mail has been sent to the merchant informing them of the error. The following is the result of the attempt to charge your credit card.
This transaction has been approved.
It is advisable for you to contact the merchant to verify that you will receive the product or service.
I'm getting the email about Merchant Email Receipt and the one about the error:
Authorize.Net Developer Center Merchant,
Your script timed out while we were trying to post transaction results to it.
Transaction ID: XXX
Transaction Result: This transaction has been approved.
The transaction is processed correctly, the capture script is called, hashes match and then the capture is called again without post data - then hashes don't match and authorize displays error.
Requests that are made from symfony profiler:
Token IP Method URL Time Status
fe39ec 198.241.162.104 GET .../payment/capture/vVgoUCPtgCOglv6rLwhIbUp64RZ_oIql1_KDpWjdrdk Tue, 17 Nov 2015 09:47:36 +0100 500
bba47c 198.241.162.104 GET .../payment/capture/vVgoUCPtgCOglv6rLwhIbUp64RZ_oIql1_KDpWjdrdk Tue, 17 Nov 2015 09:47:36 +0100 200
c95b83 198.241.162.104 POST .../payment/capture/vVgoUCPtgCOglv6rLwhIbUp64RZ_oIql1_KDpWjdrdk Tue, 17 Nov 2015 09:47:36 +0100 302
a87347 myip GET .../payment/capture/vVgoUCPtgCOglv6rLwhIbUp64RZ_oIql1_KDpWjdrdk Tue, 17 Nov 2015 09:47:30 +0100 200
c95d57 myip GET .../prepare Tue, 17 Nov 2015 09:47:29 +0100 302
From what i see when we call /prepare we get redirected to capture right away this goes to authorize's form. Then after a few seconds (when credit card data is filled in and submitted) authorize (different ip) makes post request to capture. This is 302 redirect (and probably should be a SIM response with javascript code to go back to our page?). Capture is called secod time with GET and calculated hashes don't match - this is 500 response - authorize stays on their url and shows the error message. Done script is never called.
What can be the issue? It's difficult to debug this further because there is payum, omnipay-bridge, omnipay, authorize combined.
Im testing this on the environment accessible from the internet with account on http://developer.authorize.net/ with test mode off.
UPDATE:
If I add notify token to the controller, like this:
/**
* #Route("/prepare", name="prepare")
*/
public function prepareAction()
{
$gatewayName = 'authorizeGateway';
$storage = $this->get('payum')->getStorage('AppBundle\Entity\Payment');
$payment = $storage->create();
$payment->setNumber(uniqid());
$payment->setCurrencyCode('USD');
$payment->setTotalAmount(1); // 1.23 EUR
$payment->setDescription('A description');
$payment->setClientId('anId');
$payment->setClientEmail('foo#example.com');
$storage->update($payment);
$captureToken = $this->get('payum.security.token_factory')->createCaptureToken(
$gatewayName,
$payment,
'done' // the route to redirect after capture
);
$tokenFactory = $this->get('payum.security.token_factory');
$notifyToken = $tokenFactory->createNotifyToken($gatewayName, $payment);
$payment->setDetails(['notifyUrl' => $notifyToken->getTargetUrl()]);
$storage->update($payment);
return $this->redirect($captureToken->getTargetUrl());
}
I get error "Request Notify{model: ArrayObject} is not supported.":
[2015-11-17 17:46:50] request.INFO: Matched route "payum_notify_do". {"route_parameters":{"_controller":"Payum\\Bundle\\PayumBundle\\Controller\\NotifyController::doAction","payum_token":"Lv5ovrC-8vikIB9ItDVLcNfuRzjjaD_pPiE3-6VIV8Y","_route":"payum_notify_do"},"request_uri":".../payment/notify/Lv5ovrC-8vikIB9ItDVLcNfuRzjjaD_pPiE3-6VIV8Y"} []
[2015-11-17 17:46:50] security.INFO: Populated the TokenStorage with an anonymous Token. [] []
[2015-11-17 17:46:50] request.CRITICAL: Uncaught PHP Exception Payum\Core\Exception\RequestNotSupportedException: "Request Notify{model: ArrayObject} is not supported." at .../authorize/vendor/payum/core/Payum/Core/Exception/RequestNotSupportedException.php line 29 {"exception":"[object] (Payum\\Core\\Exception\\RequestNotSupportedException(code: 0): Request Notify{model: ArrayObject} is not supported. at .../authorize/vendor/payum/core/Payum/Core/Exception/RequestNotSupportedException.php:29)"} []
Omnipay bridge 0.15.x does not set a notifyUrl, and the omnipay gateway uses return url as notify one. When notification comes (before you are redirected) the capture token is invalidated and no longer available.
There are two solutions:
Upgrade to 1.0 where notifyUrl is generated. Btw you can use omnipay gateway factory instead of omnipay_offsite.
or you have to generate notify url yourself, and set it to notifyUrl
$tokenFactory = $this->get('payum.security.token_factory');
$notifyToken = $tokenFactory->createNotifyToken($gatewayName, $payment);
$payment->setDetails(['notifyUrl' => $notifyToken->getTargetUrl()]);
$storage->update($payment);