I am attempting to create new Interactions programmatically on Genesys Platform SDK 8.5 for Java.
I use the example on the API reference
public void createInteraction(String ixnType, String ixnSubtype, String queue) throws Exception
{
RequestSubmit req = RequestSubmit.create();
req.setInteractionType(ixnType);
req.setInteractionSubtype(ixnSubtype);
req.setQueue(queue);
req.setMediaType("email");
Message response = mPMService.getProtocol("IxnSrv").request(req);
if(response == null || response.messageId() != EventAck.ID) {
// For this sample, no error handling is implemented
return;
}
EventAck event = (EventAck)response;
mInteractionId = event.getExtension().getString("InteractionId");
}
However, this gives me an Unsupported protocol element error.
'EventError' (126) attributes:
attr_error_desc [str] = "Unsupported protocol element"
attr_ref_id [int] = 2
attr_error_code [int] = 4
How do I create a new Interaction programmatically?
Interaction server should be connected with ClientType as either MediaServer or AgentApplication for this request(RequestSubmit).
First of all, you must open your protocol as Media Server. After that you must submit your interaction to interaction server.
Firstly your protocol config must be like this;
interactionServerConfiguration.ClientName = "TestClient";
interactionServerConfiguration.ClientType = InteractionClient.MediaServer;
// Register this connection configuration with Protocol Manager
protocolManagementService.Register(interactionServerConfiguration);
Note : You must have MediaServer type application definition on your Configuration Env., you must see it in CME.
After open you connection to ixn server. You can submit your interaction what you like. Even you can create new type interaction just like i do. I did for our coopate sms system. Its name is not important. We defined it on our bussiness attribute, so our agent can send coopate 3rd party sms system from their agent desktop. Without new extension or new license :) Just tricked it system. Also genesys allows it. i know it because we are genesys official support team in our country :) (But agent seat license may be required depends on agent head count).
RequestSubmit request = RequestSubmit.Create();
request.TenantId = 1;
request.MediaType = "email";
request.Queue = c_inboundQueue;
request.InteractionType = "Inbound";
request.InteractionSubtype = "InboundNew";
// Prepare the message to send. It is inserted in the request as UserData
KeyValueCollection userData =
new KeyValueCollection();
// Prepare the message to send
userData.Add("Subject", "subject goes here");
request.UserData = userData; protocolManagementService[c_interactionServerConfigurationIdentifier].Send(request);
Turns out I needed to set ClientType to InteractionClient.ReportingEngine.
Related
We've migrated from adal4j to msal4j in our java web applications.
All works well but the big difference is that when the user is already logged (maybe in other applications but same browser session) we always see the "select user" page and the user is not logged automatically and redirected to redirect uri as before with adal4j.
This is how we redirect to autentication page:
private static void redirectToAuthorizationEndpoint(IdentityContextAdapter contextAdapter) throws IOException {
final IdentityContextData context = contextAdapter.getContext();
final String state = UUID.randomUUID().toString();
final String nonce = UUID.randomUUID().toString();
context.setStateAndNonce(state, nonce);
contextAdapter.setContext(context);
final ConfidentialClientApplication client = getConfidentialClientInstance();
AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
.builder(props.getProperty("aad.redirectURI"), Collections.singleton(props.getProperty("aad.scopes"))).responseMode(ResponseMode.QUERY)
.prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
contextAdapter.redirectUser(authorizeUrl);
}
I've tried to remove .prompt(Prompt.SELECT_ACCOUNT)
but I receive an error
Any ideas?
• You might be getting the option for selecting the user account after switching to MSAL4J in your browser even after the SSO is enabled because either clearing the token cache is enabled in your code or MsalInteractionRequiredException option is thrown and specified accordingly due to which the application asks for a token interactively.
Thus, please check which accounts information is stored in the cache as below: -
ConfidentialClientApplication pca = new ConfidentialClientApplication.Builder(
labResponse.getAppId()).
authority(TestConstants.ORGANIZATIONS_AUTHORITY).
build();
Set<IAccount> accounts = pca.getAccounts().join(); ’
Then, from the above information, if you want to remove the accounts whose prompts you don’t want to see during the user account selection such that the default account should get selected and signed in automatically, execute the below code by modifying the required information: -
Set<IAccount> accounts = pca.getAccounts().join();
IAccount accountToBeRemoved = accounts.stream().filter(
x -> x.username().equalsIgnoreCase(
UPN_OF_USER_TO_BE_REMOVED)).findFirst().orElse(null);
pca.removeAccount(accountToBeRemoved).join();
• And for the MsalInteractiveRequiredException class in the code, kindly refer to the below official documentation link for the AcquireTokenSilently and other reasons responsible for the behaviour. Also, refer to the sample code given below for your reference regarding the same: -
https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-error-handling-java#msalinteractionrequiredexception
IAuthenticationResult result;
try {
ConfidentialClientApplication application =
ConfidentialClientApplication
.builder("clientId")
.b2cAuthority("authority")
.build();
SilentParameters parameters = SilentParameters
.builder(Collections.singleton("scope"))
.build();
result = application.acquireTokenSilently(parameters).join();
}
catch (Exception ex){
if(ex instanceof MsalInteractionRequiredException){
// AcquireToken by either AuthorizationCodeParameters or DeviceCodeParameters
} else{
// Log and handle exception accordingly
}
}
I have the following setup (using java 11).
A user enters his browser, sends request to a java backend secured with kerberos.
Server responds with "Negotiate...", browser responds with user ticket.
Then java backend impersonates that user and goes to postgres pretending to be that user.
Impersonation is done with the following code:
((ExtendedGSSCredential) serviceCredentials).impersonate(gssName);
The code for impersonate() method (from jdk):
public GSSCredential impersonate(GSSName name) throws GSSException {
if (destroyed) {
throw new IllegalStateException("This credential is " +
"no longer valid");
}
Oid mech = tempCred.getMechanism();
GSSNameSpi nameElement = (name == null ? null :
((GSSNameImpl)name).getElement(mech));
GSSCredentialSpi cred = tempCred.impersonate(nameElement);
return (cred == null ?
null : GSSManagerImpl.wrap(new GSSCredentialImpl(gssManager, cred)));
}
The class of tempCred here SpNegoCredElement and it supports impersonate method.
This works with the default java kerberos implementation.
Now I want to use a native GSS-API kerberos (linux with libgssapi_krb5.so.2).
For that I start java process with the following options:
-Dsun.security.jgss.native=true -Djavax.security.auth.useSubjectCredsOnly=false
The code above doesn't work with this setup because now the variable tempCred is of type GSSCredElement and it has the following implementation of impersonate() method:
#Override
public GSSCredentialSpi impersonate(GSSNameSpi name) throws GSSException {
throw new GSSException(GSSException.FAILURE, -1,
"Not supported yet");
}
So it simply throws an exception.
Does anyone know why it doesn't support impersonation?
How can I make impersonation work with native GSS-API?
I am wondering if anyone knows best practices for handling Plaid webhooks with Java Springboot?
Does the Plaid SDK offer any easy way to convert the webhook request object to a model object for the given event type? I only see they have Node Express examples which seems to only deconstruct the JSON request object by key.
Also wondering if their is anyway to verify the incoming webhook request is actually from Plaid
#PostMapping(value = "/webhook/plaid", produces =
MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity plaidWebhook(#RequestBody String payload) {
JSONParser parser = new JSONParser(payload);
JSONObject plaidWebhookRequest = null;
try {
plaidWebhookRequest = (JSONObject) parser.parse();
String webhookType = plaidWebhookRequest.has("webhook_type") ? (String) plaidWebhookRequest.get("webhook_type") : null;
String webhookCode = plaidWebhookRequest.has("webhook_code") ? (String) plaidWebhookRequest.get("webhook_code") : null;
String error = plaidWebhookRequest.has("error") ? (String) plaidWebhookRequest.get("error") : null;
String itemID = plaidWebhookRequest.has("item_id") ? (String) plaidWebhookRequest.get("item_id") : null;
if (webhookType != null && webhookCode != null && webhookType.equals(WebhookType.ITEM.name())) {
switch (webhookCode) {
case ERROR_WEBCODE:
log.info("Plaid webhook received: " + ERROR_WEBCODE);
break;
case PENDING_EXPIRATION:
log.info("Plaid webhook received: " + PENDING_EXPIRATION);
break;
case USER_PERMISSION_REVOKED:
log.info("Plaid webhook received: " + USER_PERMISSION_REVOKED);
break;
}
}
} catch (ParseException e) {
log.debug("Plaid webhook object failed to convert to JSONObject");
}
return ResponseEntity.status(HttpStatus.OK).body("");
}
I am not a Java expert but I can speak to some of the other parts of your question:
You can use the webhook verification endpoint to verify that the webhook is from Plaid: https://plaid.com/docs/api/webhooks/webhook-verification/ although I will admit the process is not as easy as most of the other things you can do with the Plaid API.
As an alternative option -- for a situation like this, you can always check the Item status by calling /item/get to confirm that the Item needs to be updated before sending the user through update mode. As a rule, Plaid doesn't ever send sensitive information in webhooks, and information in webhooks can be verified by calling endpoints that are free to call, so you should never need to "trust" a Plaid webhook without verifying it if you don't want to. This is generally smart to do anyway, for example: even if you got a webhook indicating that the Item is in an error state, the user may have resolved it or it may have self-healed in the interim.
I'm trying to use something like this:
UpdateEventSourceMappingRequest request = new UpdateEventSourceMappingRequest()
.withFunctionName("arn:aws:lambda:us-east-1:9999999999:function:"+functionName)
.withEnabled(false);
But I received a error because I have to use .withUUID(uuid):
UpdateEventSourceMappingRequest request = new UpdateEventSourceMappingRequest()
.withUUID(uuid))
.withFunctionName("arn:aws:lambda:us-east-1:9999999999:function:"+functionName)
.withEnabled(false);
I don't know how to get the value of uuid ( uuid from aws lambda ).
Can you help me with the solution to my problem ?
You need to provide the UUID identifier of the event source mapping to update it (and this field is mandatory). Update-request is not intended to create it.
When you create an event source mapping (here) - aws should return a response with a UUID identifier which you then may use in the update request.
That's the solution that I founded:
String strUUID = "";
ListEventSourceMappingsRequest requestList = new ListEventSourceMappingsRequest()
.withEventSourceArn("arn:aws:sqs:us-east-1:9999999999:test");
ListEventSourceMappingsResult result = awsLambda.listEventSourceMappings(requestList);
List<EventSourceMappingConfiguration> eventSourceMappings = result.getEventSourceMappings();
for (EventSourceMappingConfiguration eventLambda : eventSourceMappings) {
strUUID = eventLambda.getUUID();
}
System.out.println("Output UUID " + strUUID);
We have to use the ARN of the SQS that's trigger of the aws lambda.
I am receiving notification payload as
[AnyHashable("jsonData"): {"packageName":"com.company.appName","appName":"AppName","orderId":"0","workflow":"PAGE_OWNER_STATUS_WORKFLOW"}, AnyHashable("aps"): {
alert = {
body = "You have received a new Order! ";
title = Orders;
};
sound = default;
},AnyHashable("google.c.a.e"): 1, AnyHashable("gcm.notification.jsonData"): {"packageName":"com.company.appName","appName":"AppName","orderId":"0","workflow":"PAGE_OWNER_STATUS_WORKFLOW"}, AnyHashable("title"): Orders, AnyHashable("google.c.sender.id"): 34781329473, AnyHashable("body"): You have received a new Order! , AnyHashable("sound"): phone_ringing.caf, AnyHashable("gcm.message_id"): 1597347128946557]
It does not add sound name in aps alert. Will it be done from backend?
We are using JAVA for Backend.
I believe the sound property has to be set as a property of the aps and not of the alert object, like you're receiving now and like it is specified in apple documentation. Apple example:
{
“aps” : {
“badge” : 9
“sound” : “bingbong.aiff”
},
“messageID” : “ABCDEFGHIJ”
}
You should specify the string "default" to play the default notification sound, otherwise a filename must be set and the file needs to exist on the app. These changes would have to be done on the server side.